trackler 2.0.6.0 → 2.0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/csharp/.gitignore +3 -1
  4. data/tracks/csharp/README.md +1 -1
  5. data/tracks/csharp/build.fsx +6 -0
  6. data/tracks/csharp/circle.yml +16 -0
  7. data/tracks/csharp/paket.dependencies +2 -1
  8. data/tracks/csharp/paket.lock +3 -0
  9. data/tracks/ecmascript/exercises/phone-number/example.js +15 -28
  10. data/tracks/ecmascript/exercises/phone-number/phone-number.spec.js +28 -13
  11. data/tracks/fsharp/.gitignore +3 -1
  12. data/tracks/fsharp/README.md +1 -1
  13. data/tracks/fsharp/build.fsx +7 -1
  14. data/tracks/fsharp/circle.yml +16 -0
  15. data/tracks/fsharp/paket.dependencies +2 -1
  16. data/tracks/fsharp/paket.lock +3 -0
  17. data/tracks/ocaml/tools/test-generator/src/controller.ml +5 -5
  18. data/tracks/ocaml/tools/test-generator/src/model.ml +2 -0
  19. data/tracks/ocaml/tools/test-generator/src/parser.ml +35 -31
  20. data/tracks/ocaml/tools/test-generator/src/special_cases.ml +27 -23
  21. data/tracks/ocaml/tools/test-generator/src/utils.ml +2 -2
  22. data/tracks/ocaml/tools/test-generator/templates/dominoes/template.ml +40 -0
  23. data/tracks/ocaml/tools/test-generator/test/parser_test.ml +27 -21
  24. data/tracks/pony/config.json +5 -0
  25. data/tracks/pony/docs/ABOUT.md +12 -0
  26. data/tracks/pony/docs/INSTALLATION.md +4 -6
  27. data/tracks/pony/docs/LEARNING.md +7 -0
  28. data/tracks/pony/docs/RESOURCES.md +7 -0
  29. data/tracks/pony/docs/TESTS.md +11 -0
  30. data/tracks/pony/exercises/hamming/test.pony +2 -2
  31. data/tracks/pony/exercises/rna-transcription/example.pony +13 -0
  32. data/tracks/pony/exercises/rna-transcription/test.pony +32 -0
  33. data/tracks/r/exercises/anagram/example.R +18 -2
  34. data/tracks/r/exercises/bob/example.R +16 -1
  35. data/tracks/r/exercises/luhn/example.R +23 -7
  36. data/tracks/r/exercises/luhn/luhn.R +6 -0
  37. data/tracks/r/exercises/word-count/example.R +5 -0
  38. data/tracks/ruby/exercises/series/example.rb +12 -22
  39. data/tracks/ruby/exercises/series/series_test.rb +19 -12
  40. data/tracks/ruby/test/test_helper.rb +3 -3
  41. data/tracks/scala/config.json +7 -0
  42. data/tracks/scala/exercises/sieve/build.sbt +2 -2
  43. data/tracks/scala/exercises/simple-cipher/build.sbt +2 -2
  44. metadata +10 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d9790736cb76031c439b02a7ca4d77d543506267
4
- data.tar.gz: 84dabbea80eaef2ac6744e45c6adfac75a5d84e3
3
+ metadata.gz: e0a5ee73b9501fd6101f3faf9913c4634acd6cf8
4
+ data.tar.gz: 4c49bfef6fa06b4a9b9fed119dd455a7a2dd6859
5
5
  SHA512:
6
- metadata.gz: 7c18b8ab1aa1f1a04e99b9fec8cfe15e4e2ba7bbfa0350bcb8d06fbde2d369388dccca26cd48ed61e3d6306e897883456b04aacd865b36e8246a64eae77f13ad
7
- data.tar.gz: e9359d9665d6e91f3156fe4f32a3dc146c4ad32d97031d68dc46e8828f63a9e9afc642fa3b5aa33cd155e87ac088130963091bc1d0ecaa9a63a2e49e50d46a46
6
+ metadata.gz: 240744071c995385c5f96242c76a12c41ae1d60f4bc82194771c9feb90d9b0d2ee2efe97925a11a57ebb0969927572f6ecec12e721a7eb303111e5bde0d021ee
7
+ data.tar.gz: 76be73161db9c3d6114e2b2f2f7409c59ad09de0b79d56515b52e2df3d4a03b7909e9b0229ad84d4e0e88976ba37dae44f394a09a17d5512851cb83d7149fa7f
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.0.6.0"
2
+ VERSION = "2.0.6.1"
3
3
  end
@@ -9,4 +9,6 @@ bin/configlet.exe
9
9
  tools/
10
10
  build/
11
11
  packages/
12
- TestResult.xml
12
+ paket-files
13
+ TestResult.xml
14
+ junit-results.xml
@@ -1,6 +1,6 @@
1
1
  # xCSharp
2
2
 
3
- [![Build Status](https://travis-ci.org/exercism/xcsharp.svg?branch=master)](https://travis-ci.org/exercism/xcsharp) [![Build status](https://ci.appveyor.com/api/projects/status/r7o9t6gjoc09jpmn/branch/master?svg=true)](https://ci.appveyor.com/project/ErikSchierboom/xcsharp-c03a2/branch/master)
3
+ [![Build Status](https://travis-ci.org/exercism/xcsharp.svg?branch=master)](https://travis-ci.org/exercism/xcsharp) [![Build status](https://ci.appveyor.com/api/projects/status/r7o9t6gjoc09jpmn/branch/master?svg=true)](https://ci.appveyor.com/project/ErikSchierboom/xcsharp-c03a2/branch/master) [![CircleCI](https://circleci.com/gh/exercism/xcsharp.svg?style=svg)](https://circleci.com/gh/exercism/xcsharp)
4
4
 
5
5
  Exercism exercises in C#
6
6
 
@@ -11,6 +11,7 @@ let sourceDir = "./exercises/"
11
11
  // Files
12
12
  let solutionFile = buildDir @@ "/exercises.csproj"
13
13
  let compiledOutput = buildDir @@ "xcsharp.dll"
14
+ let nunitToJunitTransformFile = "./paket-files" @@ "nunit" @@ "nunit-transforms" @@ "nunit3-junit" @@ "nunit3-junit.xslt"
14
15
 
15
16
  // Targets
16
17
  Target "PrepareUnchanged" (fun _ ->
@@ -44,6 +45,11 @@ Target "Test" (fun _ ->
44
45
  |> NUnit3 (fun p -> { p with
45
46
  ShadowCopy = false
46
47
  ToolPath = "nunit3-console.exe" })
48
+ else if getEnvironmentVarAsBool "CIRCLECI" then
49
+ [compiledOutput]
50
+ |> NUnit3 (fun p -> { p with
51
+ ShadowCopy = false
52
+ ResultSpecs = [sprintf "junit-results.xml;transform=%s" nunitToJunitTransformFile] })
47
53
  else
48
54
  [compiledOutput]
49
55
  |> NUnit3 (fun p -> { p with ShadowCopy = false })
@@ -0,0 +1,16 @@
1
+ machine:
2
+ environment:
3
+ TERM: xterm-256color
4
+ dependencies:
5
+ pre:
6
+ - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
7
+ - echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
8
+ - sudo apt-get update
9
+ - sudo apt-get install mono-complete
10
+ test:
11
+ override:
12
+ - ./build.sh
13
+ post:
14
+ - mkdir -p $CIRCLE_TEST_REPORTS/junit/
15
+ - sed -i '1 s/^\xef\xbb\xbf//' .*/junit-results.xml
16
+ - find . -type f -regex ".*/junit-results.xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
@@ -2,4 +2,5 @@ source https://www.nuget.org/api/v2/
2
2
  nuget FAKE
3
3
  nuget NUnit
4
4
  nuget NUnit.ConsoleRunner
5
- nuget Sprache
5
+ nuget Sprache
6
+ github nunit/nunit-transforms nunit3-junit/nunit3-junit.xslt
@@ -75,3 +75,6 @@ NUGET
75
75
  Microsoft.NETCore.Platforms (>= 1.0.1) - framework: dnxcore50, netstandard10, >= netstandard13
76
76
  Microsoft.NETCore.Targets (>= 1.0.1) - framework: dnxcore50, netstandard10, >= netstandard13
77
77
  System.Runtime (>= 4.1) - framework: dnxcore50, netstandard10, >= netstandard13
78
+ GITHUB
79
+ remote: nunit/nunit-transforms
80
+ nunit3-junit/nunit3-junit.xslt (2a7c74198375b4b280ff3e79033c3d44e3083850)
@@ -2,40 +2,27 @@ export default class PhoneNumber {
2
2
 
3
3
  constructor(number) {
4
4
  this.rawNumber = number;
5
- this.cleanedNumber = cleanNumber(number);
6
5
  }
7
6
 
8
- number() { return this.cleanedNumber; }
7
+ number() {
8
+ if(/[a-zA-Z]/.test(this.rawNumber)) {
9
+ return null;
10
+ }
9
11
 
10
- areaCode() { return this.cleanedNumber.substr(0, 3); }
11
-
12
- toString() {
13
- return '(' + this.areaCode() + ')' +
14
- ' ' +
15
- exchangeCode(this.cleanedNumber) + '-' +
16
- subscriberNumber(this.cleanedNumber);
17
- }
18
- }
19
-
20
- function cleanNumber(number) {
21
- const num = number.replace(/\D/g,'');
22
-
23
- if (num.length === 10) {
24
- return num;
12
+ return this._cleanedNumber();
25
13
  }
26
14
 
27
- if (num.length === 11 && num[0] === '1') {
28
- return num.substr(1);
29
- }
15
+ _cleanedNumber() {
16
+ let num = this.rawNumber.replace(/\D/g,'');
30
17
 
31
- return '0000000000';
32
- }
18
+ if (num.length === 10) {
19
+ return num;
20
+ }
33
21
 
34
- function exchangeCode(number) {
35
- return number.substr(3, 3);
36
- }
22
+ if (num.length === 11 && num[0] === '1') {
23
+ return num.substr(1);
24
+ }
37
25
 
38
- function subscriberNumber(number) {
39
- return number.substr(6);
26
+ return null;
27
+ }
40
28
  }
41
-
@@ -2,7 +2,7 @@ import PhoneNumber from './phone-number';
2
2
 
3
3
  describe('PhoneNumber()', () => {
4
4
 
5
- it('cleans the number (123) 456-7890', () => {
5
+ it('cleans the number', () => {
6
6
  const phone = new PhoneNumber('(123) 456-7890');
7
7
  expect(phone.number()).toEqual('1234567890');
8
8
  });
@@ -12,29 +12,44 @@ describe('PhoneNumber()', () => {
12
12
  expect(phone.number()).toEqual('1234567890');
13
13
  });
14
14
 
15
- xit('valid when 11 digits and first digit is 1', () => {
16
- const phone = new PhoneNumber('11234567890');
15
+ xit('cleans numbers with multiple spaces', () => {
16
+ const phone = new PhoneNumber('123 456 7890 ');
17
17
  expect(phone.number()).toEqual('1234567890');
18
18
  });
19
19
 
20
+ xit('invalid when 9 digits', () => {
21
+ const phone = new PhoneNumber('123456789');
22
+ expect(phone.number()).toEqual(null);
23
+ });
24
+
20
25
  xit('invalid when 11 digits', () => {
21
26
  const phone = new PhoneNumber('21234567890');
22
- expect(phone.number()).toEqual('0000000000');
27
+ expect(phone.number()).toEqual(null);
23
28
  });
24
29
 
25
- xit('invalid when 9 digits', () => {
26
- const phone = new PhoneNumber('123456789');
27
- expect(phone.number()).toEqual('0000000000');
30
+ xit('valid when 11 digits and starting with 1', () => {
31
+ const phone = new PhoneNumber('11234567890');
32
+ expect(phone.number()).toEqual('1234567890');
33
+ });
34
+
35
+ xit('invalid when 12 digits', () => {
36
+ const phone = new PhoneNumber('321234567890');
37
+ expect(phone.number()).toEqual(null);
38
+ });
39
+
40
+ xit('invalid with letters', () => {
41
+ const phone = new PhoneNumber('123-abc-7890');
42
+ expect(phone.number()).toEqual(null);
28
43
  });
29
44
 
30
- xit('has an area code', () => {
31
- const phone = new PhoneNumber('1234567890');
32
- expect(phone.areaCode()).toEqual('123');
45
+ xit('invalid with punctuations', () => {
46
+ const phone = new PhoneNumber('123-@:!-7890');
47
+ expect(phone.number()).toEqual(null);
33
48
  });
34
49
 
35
- xit('formats a number', () => {
36
- const phone = new PhoneNumber('1234567890');
37
- expect(phone.toString()).toEqual('(123) 456-7890');
50
+ xit('invalid with right number of digits but letters mixed in', () => {
51
+ const phone = new PhoneNumber('1a2b3c4d5e6f7g8h9i0j');
52
+ expect(phone.number()).toEqual(null);
38
53
  });
39
54
 
40
55
  });
@@ -6,4 +6,6 @@ packages/
6
6
  tools/
7
7
  .fake/
8
8
  .paket/paket.exe
9
- TestResult.xml
9
+ paket-files
10
+ TestResult.xml
11
+ junit-results.xml
@@ -1,6 +1,6 @@
1
1
  # xFSharp
2
2
 
3
- [![Build Status](https://travis-ci.org/exercism/xfsharp.svg?branch=master)](https://travis-ci.org/exercism/xfsharp) [![Build status](https://ci.appveyor.com/api/projects/status/7r5bbsonqonf7d8t/branch/master?svg=true)](https://ci.appveyor.com/project/ErikSchierboom/xfsharp-8gbdd/branch/master)
3
+ [![Build Status](https://travis-ci.org/exercism/xfsharp.svg?branch=master)](https://travis-ci.org/exercism/xfsharp) [![Build status](https://ci.appveyor.com/api/projects/status/7r5bbsonqonf7d8t/branch/master?svg=true)](https://ci.appveyor.com/project/ErikSchierboom/xfsharp-8gbdd/branch/master) [![CircleCI](https://circleci.com/gh/exercism/xfsharp.svg?style=svg)](https://circleci.com/gh/exercism/xfsharp)
4
4
 
5
5
  Exercism exercises in F#
6
6
 
@@ -6,11 +6,12 @@ open Fake.Testing.NUnit3
6
6
 
7
7
  // Directories
8
8
  let buildDir = "./build/"
9
- let sourceDir = "./exercises/"
9
+ let sourceDir = "./exercises/"
10
10
 
11
11
  // Files
12
12
  let solutionFile = buildDir @@ "/exercises.fsproj"
13
13
  let compiledOutput = buildDir @@ "xfsharp.dll"
14
+ let nunitToJunitTransformFile = "./paket-files" @@ "nunit" @@ "nunit-transforms" @@ "nunit3-junit" @@ "nunit3-junit.xslt"
14
15
 
15
16
  // Targets
16
17
  Target "Clean" (fun _ ->
@@ -42,6 +43,11 @@ Target "Test" (fun _ ->
42
43
  |> NUnit3 (fun p -> { p with
43
44
  ShadowCopy = false
44
45
  ToolPath = "nunit3-console.exe" })
46
+ else if getEnvironmentVarAsBool "CIRCLECI" then
47
+ [compiledOutput]
48
+ |> NUnit3 (fun p -> { p with
49
+ ShadowCopy = false
50
+ ResultSpecs = [sprintf "junit-results.xml;transform=%s" nunitToJunitTransformFile] })
45
51
  else
46
52
  [compiledOutput]
47
53
  |> NUnit3 (fun p -> { p with ShadowCopy = false })
@@ -0,0 +1,16 @@
1
+ machine:
2
+ environment:
3
+ TERM: xterm-256color
4
+ dependencies:
5
+ pre:
6
+ - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
7
+ - echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
8
+ - sudo apt-get update
9
+ - sudo apt-get install mono-complete fsharp
10
+ test:
11
+ override:
12
+ - ./build.sh
13
+ post:
14
+ - mkdir -p $CIRCLE_TEST_REPORTS/junit/
15
+ - sed -i '1 s/^\xef\xbb\xbf//' .*/junit-results.xml
16
+ - find . -type f -regex ".*/junit-results.xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
@@ -3,4 +3,5 @@ nuget FAKE
3
3
  nuget FParsec
4
4
  nuget FSharp.Core
5
5
  nuget NUnit
6
- nuget NUnit.ConsoleRunner
6
+ nuget NUnit.ConsoleRunner
7
+ github nunit/nunit-transforms nunit3-junit/nunit3-junit.xslt
@@ -5,3 +5,6 @@ NUGET
5
5
  FSharp.Core (4.0.0.1)
6
6
  NUnit (3.5)
7
7
  NUnit.ConsoleRunner (3.5)
8
+ GITHUB
9
+ remote: nunit/nunit-transforms
10
+ nunit3-junit/nunit3-junit.xslt (2a7c74198375b4b280ff3e79033c3d44e3083850)
@@ -10,9 +10,9 @@ type content = string
10
10
 
11
11
  let find_nested_files (name: string) (base: string): (string * content) list =
12
12
  Sys.ls_dir base
13
- |> List.filter ~f:(fun slug -> Sys.is_directory_exn (base ^ "/" ^ slug))
14
- |> List.filter ~f:(fun slug -> Sys.file_exists_exn (base ^ "/" ^ slug ^ "/" ^ name))
15
- |> List.map ~f:(fun slug -> (slug, In_channel.read_all (base ^ "/" ^ slug ^ "/" ^ name)))
13
+ |> List.filter ~f:(fun slug -> Sys.is_directory_exn (base ^ "/" ^ slug))
14
+ |> List.filter ~f:(fun slug -> Sys.file_exists_exn (base ^ "/" ^ slug ^ "/" ^ name))
15
+ |> List.map ~f:(fun slug -> (slug, In_channel.read_all (base ^ "/" ^ slug ^ "/" ^ name)))
16
16
 
17
17
  let find_template_files = find_nested_files "template.ml"
18
18
 
@@ -28,7 +28,7 @@ let generate_code ~(slug: string) ~(template_file: content) ~(canonical_data_fil
28
28
  let fill_in_template = fill_in_template edit_expected edit_parameters in
29
29
  let open Result.Monad_infix in
30
30
  Result.of_option template ("cannot recognize file for " ^ slug ^ " as a template") >>= fun template ->
31
- parse_json_text canonical_data_file
31
+ parse_json_text canonical_data_file (expected_key_name slug)
32
32
  |> Result.map_error ~f:show_error >>= (function
33
33
  | Single cases ->
34
34
  fill_in_template template.template slug cases
@@ -60,7 +60,7 @@ let check_canonical_data canonical_data_folder =
60
60
  let canonical_data_files = List.sort canonical_data_files ~cmp:(fun (s1, _) (s2, _) -> String.compare s1 s2) in
61
61
  let total_count = List.length canonical_data_files in
62
62
  List.iter canonical_data_files ~f:(fun (slug, text) ->
63
- match parse_json_text text with
63
+ match parse_json_text text (expected_key_name slug) with
64
64
  | Error e -> print_endline @@ slug ^ ": " ^ (show_error e)
65
65
  | _ -> ok_count := !ok_count + 1
66
66
  );
@@ -10,6 +10,7 @@ type parameter =
10
10
  | Bool of bool
11
11
  | StringList of (string list)
12
12
  | IntList of (int list)
13
+ | IntTupleList of ((int * int) list)
13
14
  | IntStringMap of ((string * int) list) [@@deriving eq, show]
14
15
 
15
16
  type 'a elements = (string * 'a) list [@@deriving eq, show]
@@ -37,5 +38,6 @@ let parameter_to_string = function
37
38
  | Bool b -> Bool.to_string b
38
39
  | StringList xs -> "[" ^ String.concat ~sep:"; " (List.map ~f:(surround '\"' >> String.escaped) xs) ^ "]"
39
40
  | IntList xs -> "[" ^ String.concat ~sep:"; " (List.map ~f:Int.to_string xs) ^ "]"
41
+ | IntTupleList xs -> "[" ^ String.concat ~sep:"; " (List.map xs ~f:(fun (x,y) -> sprintf "(%d,%d)" x y)) ^ "]"
40
42
  | IntStringMap xs -> "[" ^ String.concat ~sep:"; "
41
43
  (List.map xs ~f:(fun (k,v) -> "(\"" ^ String.escaped k ^ "\", " ^ Int.to_string v ^ ")")) ^ "]"
@@ -1,7 +1,7 @@
1
1
  open Core.Std
2
2
  open Utils
3
- open Yojson.Safe
4
- open Yojson.Safe.Util
3
+ open Yojson.Basic
4
+ open Yojson.Basic.Util
5
5
  open Model
6
6
 
7
7
  type error =
@@ -9,46 +9,50 @@ type error =
9
9
  NoDescription | BadDescription | NoExpected of string | BadExpected | UnrecognizedJson [@@deriving eq, show]
10
10
 
11
11
  let to_int_safe = function
12
- | `Int x -> Some x
13
- | _ -> None
12
+ | `Int x -> Some x
13
+ | _ -> None
14
14
 
15
- let to_list_safe xs = let open Option.Monad_infix in match xs with
16
- | [] -> Some (StringList [])
17
- | `String x :: _ -> Some (StringList (List.map xs ~f:to_string))
18
- | `Int x :: _ -> List.map xs ~f:to_int_safe |> sequence_option >>= (fun xs -> Some (IntList xs))
19
- | _ -> None
15
+ let to_tuple_safe xs = match xs with
16
+ | `List [`Int x; `Int y] -> Some (x,y)
17
+ | _ -> None
18
+
19
+ let rec to_list_safe xs: parameter option = let open Option.Monad_infix in match xs with
20
+ | [] -> Some (StringList [])
21
+ | `String x :: _ -> Some (StringList (List.map xs ~f:to_string))
22
+ | `Int x :: _ -> List.map xs ~f:to_int_safe |> sequence_option >>= (fun xs -> Some (IntList xs))
23
+ | `List x :: _ -> List.map xs ~f:to_tuple_safe |> sequence_option >>= (fun xs -> Some (IntTupleList xs))
24
+ | _ -> None
20
25
 
21
26
  let q xs = let open Option.Monad_infix in
22
27
  List.map xs ~f:(fun (k,v) -> (to_int_safe v |> Option.map ~f:(fun v -> (k,v))))
23
28
 
24
29
  let to_parameter (s: json) = match s with
25
- | `Null -> Some (Null)
26
- | `String x -> Some (String x)
27
- | `Float x -> Some (Float x)
28
- | `Int x -> Some (Int x)
29
- | `Bool x -> Some (Bool x)
30
- | `List x -> to_list_safe x
31
- | `Assoc xs -> let open Option.Monad_infix in
32
- let xs = List.map xs ~f:(fun (k,v) -> (to_int_safe v |> Option.map ~f:(fun v -> (k,v)))) in
33
- sequence_option xs >>= fun xs -> Some (IntStringMap xs)
34
- | _ -> None
30
+ | `Null -> Some (Null)
31
+ | `String x -> Some (String x)
32
+ | `Float x -> Some (Float x)
33
+ | `Int x -> Some (Int x)
34
+ | `Bool x -> Some (Bool x)
35
+ | `List x -> to_list_safe x
36
+ | `Assoc xs -> let open Option.Monad_infix in
37
+ let xs = List.map xs ~f:(fun (k,v) -> (to_int_safe v |> Option.map ~f:(fun v -> (k,v)))) in
38
+ sequence_option xs >>= fun xs -> Some (IntStringMap xs)
35
39
 
36
40
  let parse_parameters (parameters: (string * json) list): parameter elements =
37
41
  List.filter_map parameters ~f:(fun (k, v) -> Option.map ~f:(fun v -> (k, v)) (to_parameter v))
38
42
 
39
- let parse_case_assoc (parameters: (string * json) list): (case, error) Result.t =
43
+ let parse_case_assoc (parameters: (string * json) list) (expected_key: string): (case, error) Result.t =
40
44
  let find name e = List.Assoc.find parameters name |> Result.of_option ~error:e in
41
45
  let test_parameters = List.Assoc.remove parameters "description" in
42
- let test_parameters = List.Assoc.remove test_parameters "expected" in
46
+ let test_parameters = List.Assoc.remove test_parameters expected_key in
43
47
  let open Result.Monad_infix in
44
48
  find "description" NoDescription >>=
45
49
  to_string_note BadDescription >>= fun description ->
46
- find "expected" (NoExpected description) >>= fun expectedJson ->
50
+ find expected_key (NoExpected description) >>= fun expectedJson ->
47
51
  to_parameter expectedJson |> Result.of_option ~error:BadExpected >>= fun expected ->
48
52
  Ok {description = description; parameters = parse_parameters test_parameters; expected = expected}
49
53
 
50
- let parse_case (s: json): (case, error) Result.t = match s with
51
- | `Assoc assoc -> parse_case_assoc assoc
54
+ let parse_case (expected_key: string) (s: json): (case, error) Result.t = match s with
55
+ | `Assoc assoc -> parse_case_assoc assoc expected_key
52
56
  | _ -> Error ExpectingMapForCase
53
57
 
54
58
  let parse_cases (text: string): (json, error) Result.t =
@@ -56,11 +60,11 @@ let parse_cases (text: string): (json, error) Result.t =
56
60
  | `Null -> Error (TestMustHaveKeyCalledCases "xx")
57
61
  | json -> Ok json
58
62
 
59
- let parse_single (text: string): (tests, error) Result.t =
63
+ let parse_single (text: string) (expected_key: string): (tests, error) Result.t =
60
64
  let open Result.Monad_infix in
61
65
  parse_cases text >>=
62
66
  to_list_note ExpectingListOfCases >>=
63
- (sequence >> (List.map ~f:parse_case)) >>= fun ts ->
67
+ (sequence >> (List.map ~f:(parse_case expected_key))) >>= fun ts ->
64
68
  Result.return (Single ts)
65
69
 
66
70
  let is_suite (json: json) =
@@ -72,24 +76,24 @@ let merge_result = function
72
76
  | (_, Error x) -> Error x
73
77
  | (n, Ok c) -> Ok {name = n; cases = c}
74
78
 
75
- let parse_cases_from_suite name suite =
79
+ let parse_cases_from_suite name suite expected_key =
76
80
  let open Result.Monad_infix in
77
81
  member_note (TestMustHaveKeyCalledCases name) "cases" suite >>=
78
82
  to_list_note ExpectingListOfCases >>= fun tests ->
79
- List.map tests ~f:parse_case |> sequence
83
+ List.map tests ~f:(parse_case expected_key) |> sequence
80
84
 
81
- let parse_json_text (text: string): (tests, error) Result.t =
85
+ let parse_json_text (text: string) (expected_key: string): (tests, error) Result.t =
82
86
  let open Result.Monad_infix in
83
87
  let json = from_string text in
84
88
  if is_suite json
85
89
  then
86
90
  to_assoc_note UnrecognizedJson json >>= fun tests ->
87
91
  let tests = List.filter tests ~f:(fun (n, _) -> n <> "#") in
88
- let tests = List.map tests ~f:(fun (name, suite) -> merge_result (name, parse_cases_from_suite name suite)) in
92
+ let tests = List.map tests ~f:(fun (name, suite) -> merge_result (name, parse_cases_from_suite name suite expected_key)) in
89
93
  sequence tests >>= fun tests ->
90
94
  Ok (Suite tests)
91
95
  else
92
- parse_single text
96
+ parse_single text expected_key
93
97
 
94
98
  let show_error = function
95
99
  | TestMustHaveKeyCalledCases name -> "Test named '" ^ name ^ "' is expected to have an object with a key: 'cases'"