trackler 2.0.6.0 → 2.0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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'"