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.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/csharp/.gitignore +3 -1
- data/tracks/csharp/README.md +1 -1
- data/tracks/csharp/build.fsx +6 -0
- data/tracks/csharp/circle.yml +16 -0
- data/tracks/csharp/paket.dependencies +2 -1
- data/tracks/csharp/paket.lock +3 -0
- data/tracks/ecmascript/exercises/phone-number/example.js +15 -28
- data/tracks/ecmascript/exercises/phone-number/phone-number.spec.js +28 -13
- data/tracks/fsharp/.gitignore +3 -1
- data/tracks/fsharp/README.md +1 -1
- data/tracks/fsharp/build.fsx +7 -1
- data/tracks/fsharp/circle.yml +16 -0
- data/tracks/fsharp/paket.dependencies +2 -1
- data/tracks/fsharp/paket.lock +3 -0
- data/tracks/ocaml/tools/test-generator/src/controller.ml +5 -5
- data/tracks/ocaml/tools/test-generator/src/model.ml +2 -0
- data/tracks/ocaml/tools/test-generator/src/parser.ml +35 -31
- data/tracks/ocaml/tools/test-generator/src/special_cases.ml +27 -23
- data/tracks/ocaml/tools/test-generator/src/utils.ml +2 -2
- data/tracks/ocaml/tools/test-generator/templates/dominoes/template.ml +40 -0
- data/tracks/ocaml/tools/test-generator/test/parser_test.ml +27 -21
- data/tracks/pony/config.json +5 -0
- data/tracks/pony/docs/ABOUT.md +12 -0
- data/tracks/pony/docs/INSTALLATION.md +4 -6
- data/tracks/pony/docs/LEARNING.md +7 -0
- data/tracks/pony/docs/RESOURCES.md +7 -0
- data/tracks/pony/docs/TESTS.md +11 -0
- data/tracks/pony/exercises/hamming/test.pony +2 -2
- data/tracks/pony/exercises/rna-transcription/example.pony +13 -0
- data/tracks/pony/exercises/rna-transcription/test.pony +32 -0
- data/tracks/r/exercises/anagram/example.R +18 -2
- data/tracks/r/exercises/bob/example.R +16 -1
- data/tracks/r/exercises/luhn/example.R +23 -7
- data/tracks/r/exercises/luhn/luhn.R +6 -0
- data/tracks/r/exercises/word-count/example.R +5 -0
- data/tracks/ruby/exercises/series/example.rb +12 -22
- data/tracks/ruby/exercises/series/series_test.rb +19 -12
- data/tracks/ruby/test/test_helper.rb +3 -3
- data/tracks/scala/config.json +7 -0
- data/tracks/scala/exercises/sieve/build.sbt +2 -2
- data/tracks/scala/exercises/simple-cipher/build.sbt +2 -2
- metadata +10 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0a5ee73b9501fd6101f3faf9913c4634acd6cf8
|
4
|
+
data.tar.gz: 4c49bfef6fa06b4a9b9fed119dd455a7a2dd6859
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 240744071c995385c5f96242c76a12c41ae1d60f4bc82194771c9feb90d9b0d2ee2efe97925a11a57ebb0969927572f6ecec12e721a7eb303111e5bde0d021ee
|
7
|
+
data.tar.gz: 76be73161db9c3d6114e2b2f2f7409c59ad09de0b79d56515b52e2df3d4a03b7909e9b0229ad84d4e0e88976ba37dae44f394a09a17d5512851cb83d7149fa7f
|
data/lib/trackler/version.rb
CHANGED
data/tracks/csharp/.gitignore
CHANGED
data/tracks/csharp/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# xCSharp
|
2
2
|
|
3
|
-
[](https://travis-ci.org/exercism/xcsharp) [](https://ci.appveyor.com/project/ErikSchierboom/xcsharp-c03a2/branch/master)
|
3
|
+
[](https://travis-ci.org/exercism/xcsharp) [](https://ci.appveyor.com/project/ErikSchierboom/xcsharp-c03a2/branch/master) [](https://circleci.com/gh/exercism/xcsharp)
|
4
4
|
|
5
5
|
Exercism exercises in C#
|
6
6
|
|
data/tracks/csharp/build.fsx
CHANGED
@@ -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/ \;
|
data/tracks/csharp/paket.lock
CHANGED
@@ -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() {
|
7
|
+
number() {
|
8
|
+
if(/[a-zA-Z]/.test(this.rawNumber)) {
|
9
|
+
return null;
|
10
|
+
}
|
9
11
|
|
10
|
-
|
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
|
-
|
28
|
-
|
29
|
-
}
|
15
|
+
_cleanedNumber() {
|
16
|
+
let num = this.rawNumber.replace(/\D/g,'');
|
30
17
|
|
31
|
-
|
32
|
-
|
18
|
+
if (num.length === 10) {
|
19
|
+
return num;
|
20
|
+
}
|
33
21
|
|
34
|
-
|
35
|
-
|
36
|
-
}
|
22
|
+
if (num.length === 11 && num[0] === '1') {
|
23
|
+
return num.substr(1);
|
24
|
+
}
|
37
25
|
|
38
|
-
|
39
|
-
|
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
|
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('
|
16
|
-
const phone = new PhoneNumber('
|
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(
|
27
|
+
expect(phone.number()).toEqual(null);
|
23
28
|
});
|
24
29
|
|
25
|
-
xit('
|
26
|
-
const phone = new PhoneNumber('
|
27
|
-
expect(phone.number()).toEqual('
|
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('
|
31
|
-
const phone = new PhoneNumber('
|
32
|
-
expect(phone.
|
45
|
+
xit('invalid with punctuations', () => {
|
46
|
+
const phone = new PhoneNumber('123-@:!-7890');
|
47
|
+
expect(phone.number()).toEqual(null);
|
33
48
|
});
|
34
49
|
|
35
|
-
xit('
|
36
|
-
const phone = new PhoneNumber('
|
37
|
-
expect(phone.
|
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
|
});
|
data/tracks/fsharp/.gitignore
CHANGED
data/tracks/fsharp/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# xFSharp
|
2
2
|
|
3
|
-
[](https://travis-ci.org/exercism/xfsharp) [](https://ci.appveyor.com/project/ErikSchierboom/xfsharp-8gbdd/branch/master)
|
3
|
+
[](https://travis-ci.org/exercism/xfsharp) [](https://ci.appveyor.com/project/ErikSchierboom/xfsharp-8gbdd/branch/master) [](https://circleci.com/gh/exercism/xfsharp)
|
4
4
|
|
5
5
|
Exercism exercises in F#
|
6
6
|
|
data/tracks/fsharp/build.fsx
CHANGED
@@ -6,11 +6,12 @@ open Fake.Testing.NUnit3
|
|
6
6
|
|
7
7
|
// Directories
|
8
8
|
let buildDir = "./build/"
|
9
|
-
let sourceDir
|
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/ \;
|
data/tracks/fsharp/paket.lock
CHANGED
@@ -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
|
-
|
14
|
-
|
15
|
-
|
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.
|
4
|
-
open Yojson.
|
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
|
-
|
13
|
-
|
12
|
+
| `Int x -> Some x
|
13
|
+
| _ -> None
|
14
14
|
|
15
|
-
let
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
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
|
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'"
|