trackler 2.2.1.147 → 2.2.1.148

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/trackler/version.rb +1 -1
  3. data/tracks/crystal/Makefile +1 -1
  4. data/tracks/crystal/exercises/acronym/spec/acronym_spec.cr +2 -6
  5. data/tracks/crystal/exercises/binary/spec/binary_spec.cr +1 -1
  6. data/tracks/crystal/exercises/difference-of-squares/spec/difference_of_squares_spec.cr +10 -14
  7. data/tracks/crystal/exercises/run-length-encoding/spec/run_length_encoding_spec.cr +29 -9
  8. data/tracks/crystal/generator/src/generators/acronym.cr +1 -1
  9. data/tracks/crystal/generator/src/generators/binary.cr +1 -1
  10. data/tracks/crystal/generator/src/generators/difference_of_squares.cr +6 -7
  11. data/tracks/crystal/generator/src/generators/run_length_encoding.cr +20 -10
  12. data/tracks/csharp/config.json +477 -477
  13. data/tracks/elixir/exercises/largest-series-product/example.exs +1 -1
  14. data/tracks/elm/exercises/phone-number/PhoneNumber.elm +1 -6
  15. data/tracks/elm/exercises/phone-number/tests/Tests.elm +22 -37
  16. data/tracks/elm/exercises/run-length-encoding/tests/Tests.elm +55 -31
  17. data/tracks/fsharp/generators/Exercise.fs +27 -6
  18. data/tracks/fsharp/generators/Generators.fs +37 -45
  19. data/tracks/fsharp/generators/Templates.fs +15 -44
  20. data/tracks/haskell/.travis.yml +1 -0
  21. data/tracks/haskell/bin/check-configlet-fmt.sh +42 -0
  22. data/tracks/haskell/config/maintainers.json +13 -13
  23. data/tracks/haskell/config.json +212 -250
  24. data/tracks/java/exercises/sublist/.meta/version +1 -1
  25. data/tracks/java/exercises/word-search/.meta/version +1 -1
  26. data/tracks/nim/config.json +10 -0
  27. data/tracks/nim/exercises/reverse-string/README.md +13 -0
  28. data/tracks/nim/exercises/reverse-string/example.nim +4 -0
  29. data/tracks/nim/exercises/reverse-string/reverse_string_test.nim +20 -0
  30. data/tracks/objective-c/config.json +10 -0
  31. data/tracks/objective-c/exercises/reverse-string/README.md +34 -0
  32. data/tracks/objective-c/exercises/reverse-string/ReverseStringExample.h +7 -0
  33. data/tracks/objective-c/exercises/reverse-string/ReverseStringExample.m +22 -0
  34. data/tracks/objective-c/exercises/reverse-string/ReverseStringTest.m +51 -0
  35. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.pbxproj +18 -0
  36. data/tracks/objective-c/xcodeProject/ObjectiveC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  37. data/tracks/ruby/config/maintainers.json +25 -25
  38. data/tracks/ruby/config.json +203 -371
  39. data/tracks/ruby/exercises/bob/.meta/.version +1 -1
  40. data/tracks/ruby/exercises/bob/.meta/generator/bob_case.rb +3 -2
  41. data/tracks/ruby/exercises/bob/.meta/solutions/bob.rb +3 -1
  42. data/tracks/ruby/exercises/bob/README.md +2 -0
  43. data/tracks/ruby/exercises/bob/bob_test.rb +27 -27
  44. data/tracks/ruby/exercises/hamming/RUNNING_TESTS.md +1 -1
  45. data/tracks/rust/.travis.yml +1 -0
  46. data/tracks/rust/_test/check-configlet-fmt.sh +37 -0
  47. data/tracks/rust/config/maintainers.json +23 -23
  48. data/tracks/rust/config.json +246 -246
  49. metadata +12 -3
  50. data/tracks/elm/exercises/run-length-encoding/RunLengthEncodingPropertyChecks.elm +0 -63
@@ -36,7 +36,7 @@ defmodule Series do
36
36
  end
37
37
 
38
38
  # Handle Enum.chunks -> Enum.chunk renaming.
39
- if not ({:chunk, 3} in Enum.__info__(:functions)) do
39
+ if {:chunk, 3} not in Enum.__info__(:functions) do
40
40
  defp chunk(coll, n, step), do: Enum.chunks(coll, n, step)
41
41
  else
42
42
  defp chunk(coll, n, step), do: Enum.chunk(coll, n, step)
@@ -1,11 +1,6 @@
1
- module PhoneNumber exposing (getNumber, prettyPrint)
1
+ module PhoneNumber exposing (getNumber)
2
2
 
3
3
 
4
4
  getNumber : String -> Maybe String
5
5
  getNumber phoneNumber =
6
6
  Debug.crash "Please implement this function"
7
-
8
-
9
- prettyPrint : String -> Maybe String
10
- prettyPrint input =
11
- Debug.crash "Please implement this function"
@@ -1,67 +1,52 @@
1
1
  module Tests exposing (..)
2
2
 
3
3
  import Expect
4
- import PhoneNumber exposing (getNumber, prettyPrint)
4
+ import PhoneNumber exposing (getNumber)
5
5
  import Test exposing (..)
6
6
 
7
7
 
8
8
  tests : Test
9
9
  tests =
10
10
  describe "PhoneNumber"
11
- [ test "cleans number" <|
11
+ [ test "cleans the number" <|
12
12
  \() -> Expect.equal (Just "2234567890") (getNumber "(223) 456-7890")
13
13
  , skip <|
14
- test "invalid when empty" <|
15
- \() -> Expect.equal Nothing (getNumber "")
16
- , skip <|
17
- test "cleans number with dots" <|
14
+ test "cleans numbers with dots" <|
18
15
  \() -> Expect.equal (Just "2234567890") (getNumber "223.456.7890")
16
+ , skip <|
17
+ test "cleans numbers with multiple spaces" <|
18
+ \() -> Expect.equal (Just "2234567890") (getNumber "223 456 7890 ")
19
19
  , skip <|
20
20
  test "invalid when 9 digits" <|
21
21
  \() -> Expect.equal Nothing (getNumber "223456789")
22
22
  , skip <|
23
- test "cleans number with multiple spaces" <|
24
- \() -> Expect.equal (Just "2234567890") (getNumber "223 456 7890")
25
- , skip <|
26
- test "invalid when 12 digits" <|
27
- \() -> Expect.equal Nothing (getNumber "223456789012")
23
+ test "invalid when 11 digits does not start with a 1" <|
24
+ \() -> Expect.equal Nothing (getNumber "22234567890")
28
25
  , skip <|
29
- test "valid when 11 digits and first is 1" <|
26
+ test "valid when 11 digits and starting with 1" <|
30
27
  \() -> Expect.equal (Just "2234567890") (getNumber "12234567890")
31
28
  , skip <|
32
- test "invalid when 11 digits and first is not 1" <|
33
- \() -> Expect.equal Nothing (getNumber "22234567890")
34
- , skip <|
35
- test "valid when 11 digits and first is 1 with punctuation" <|
29
+ test "valid when 11 digits and starting with 1 even with punctuation" <|
36
30
  \() -> Expect.equal (Just "2234567890") (getNumber "+1 (223) 456-7890")
31
+ , skip <|
32
+ test "invalid when more than 11 digits" <|
33
+ \() -> Expect.equal Nothing (getNumber "321234567890")
37
34
  , skip <|
38
35
  test "invalid with letters" <|
39
- \() -> Expect.equal Nothing (getNumber "223-abc-789012")
36
+ \() -> Expect.equal Nothing (getNumber "123-abc-7890")
40
37
  , skip <|
41
- test "invalid with multiple punctuation marks" <|
42
- \() -> Expect.equal Nothing (getNumber "223-@:!-789012")
38
+ test "invalid with punctuations" <|
39
+ \() -> Expect.equal Nothing (getNumber "123-@:!-7890")
43
40
  , skip <|
44
- test "invalid when area code starts with 1" <|
45
- \() -> Expect.equal Nothing (getNumber "(123) 456-7890")
46
- , skip <|
47
- test "invalid when area code starts with 0" <|
41
+ test "invalid if area code starts with 0" <|
48
42
  \() -> Expect.equal Nothing (getNumber "(023) 456-7890")
49
43
  , skip <|
50
- test "invalid when exchange code starts with 1" <|
51
- \() -> Expect.equal Nothing (getNumber "(223) 156-7890")
44
+ test "invalid if area code starts with 1" <|
45
+ \() -> Expect.equal Nothing (getNumber "(123) 456-7890")
52
46
  , skip <|
53
- test "invalid when exchange code starts with 0" <|
47
+ test "invalid if exchange code starts with 0" <|
54
48
  \() -> Expect.equal Nothing (getNumber "(223) 056-7890")
55
49
  , skip <|
56
- test "invalid when N in exchange code is 1" <|
57
- \() -> Expect.equal Nothing (getNumber "2341567890")
58
- , skip <|
59
- test "invalid when no digits present" <|
60
- \() -> Expect.equal Nothing (getNumber " (-) ")
61
- , skip <|
62
- test "pretty print" <|
63
- \() -> Expect.equal (Just "(223) 456-7890") (prettyPrint "2234567890")
64
- , skip <|
65
- test "pretty print with full us phone number" <|
66
- \() -> Expect.equal (Just "(223) 456-7890") (prettyPrint "12234567890")
50
+ test "invalid if exchange code starts with 1" <|
51
+ \() -> Expect.equal Nothing (getNumber "(223) 156-7890")
67
52
  ]
@@ -10,35 +10,59 @@ tests =
10
10
  describe "RunLengthEncoding"
11
11
  [ test "the solution is for the correct version of the test" <|
12
12
  \() -> Expect.equal 2 version
13
- , test "encode simple" <|
14
- \() -> Expect.equal "2A3B4C" (encode "AABBBCCCC")
15
- , skip <|
16
- test "decode simple" <|
17
- \() -> Expect.equal "AABBBCCCC" (decode "2A3B4C")
18
- , skip <|
19
- test "encode with single values" <|
20
- \() ->
21
- Expect.equal "12WB12W3B24WB"
22
- (encode "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB")
23
- , skip <|
24
- test "decode with single values" <|
25
- \() ->
26
- Expect.equal "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB"
27
- (decode "12WB12W3B24WB")
28
- , skip <|
29
- test "(decode (encode (...)) combination" <|
30
- \() ->
31
- Expect.equal "zzz ZZ zZ"
32
- (decode (encode "zzz ZZ zZ"))
33
- , skip <|
34
- test "decode with a x10 value" <|
35
- \() ->
36
- Expect.equal "WWWWWWWWWW"
37
- (decode "10W")
38
- , skip <|
39
- test "encode unicode" <|
40
- \() -> Expect.equal "⏰3⚽2⭐⏰" (encode "⏰⚽⚽⚽⭐⭐⏰")
41
- , skip <|
42
- test "decode unicode" <|
43
- \() -> Expect.equal "⏰⚽⚽⚽⭐⭐⏰" (decode "⏰3⚽2⭐⏰")
13
+ , describe "run-length encode a string"
14
+ [ test "empty string" <|
15
+ \() -> Expect.equal "" (encode "")
16
+ , skip <|
17
+ test "single characters only are encoded without count" <|
18
+ \() -> Expect.equal "XYZ" (encode "XYZ")
19
+ , skip <|
20
+ test "string with no single characters" <|
21
+ \() -> Expect.equal "2A3B4C" (encode "AABBBCCCC")
22
+ , skip <|
23
+ test "single characters mixed with repeated characters" <|
24
+ \() ->
25
+ Expect.equal "12WB12W3B24WB"
26
+ (encode "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB")
27
+ , skip <|
28
+ test "multiple whitespace mixed in string" <|
29
+ \() -> Expect.equal "2 hs2q q2w2 " (encode " hsqq qww ")
30
+ , skip <|
31
+ test "lowercase characters" <|
32
+ \() -> Expect.equal "2a3b4c" (encode "aabbbcccc")
33
+ ]
34
+ , describe "run-length decode a string"
35
+ [ skip <|
36
+ test "empty string" <|
37
+ \() -> Expect.equal "" (decode "")
38
+ , skip <|
39
+ test "single characters only" <|
40
+ \() -> Expect.equal "XYZ" (decode "XYZ")
41
+ , skip <|
42
+ test "string with no single characters" <|
43
+ \() -> Expect.equal "AABBBCCCC" (decode "2A3B4C")
44
+ , skip <|
45
+ test "single characters with repeated characters" <|
46
+ \() ->
47
+ Expect.equal "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB"
48
+ (decode "12WB12W3B24WB")
49
+ , skip <|
50
+ test "multiple whitespace mixed in string" <|
51
+ \() -> Expect.equal " hsqq qww " (decode "2 hs2q q2w2 ")
52
+ , skip <|
53
+ test "lower case string" <|
54
+ \() -> Expect.equal "" (decode "")
55
+ , skip <|
56
+ test "with a x10 value" <|
57
+ \() ->
58
+ Expect.equal "WWWWWWWWWW"
59
+ (decode "10W")
60
+ ]
61
+ , describe "encode and then decode"
62
+ [ skip <|
63
+ test "encode followed by decode gives original string" <|
64
+ \() ->
65
+ Expect.equal "zzz ZZ zZ"
66
+ (decode (encode "zzz ZZ zZ"))
67
+ ]
44
68
  ]
@@ -11,6 +11,11 @@ open Templates
11
11
  open CanonicalData
12
12
  open Track
13
13
 
14
+ let [<Literal>] private AssertEmptyTemplate = "AssertEmpty"
15
+ let [<Literal>] private AssertEqualTemplate = "AssertEqual"
16
+ let [<Literal>] private AssertEqualWithinTemplate = "AssertEqualWithin"
17
+ let [<Literal>] private AssertThrowsTemplate = "AssertThrows"
18
+
14
19
  let private exerciseNameFromType (exerciseType: Type) = exerciseType.Name.Kebaberize()
15
20
 
16
21
  [<AbstractClass>]
@@ -109,9 +114,25 @@ type GeneratorExercise() =
109
114
  let expectedHasIdentifier = List.contains "expected" (this.PropertiesWithIdentifier canonicalDataCase)
110
115
 
111
116
  if expectedIsArray && expectedIsEmpty && not expectedHasIdentifier then
112
- "AssertEmpty"
117
+ AssertEmptyTemplate
113
118
  else
114
- "AssertEqual"
119
+ AssertEqualTemplate
120
+
121
+ member __.RenderAssertEmpty sut expected =
122
+ { Sut = sut; Expected = expected }
123
+ |> renderTemplate AssertEmptyTemplate
124
+
125
+ member __.RenderAssertEqual sut expected =
126
+ { Sut = sut; Expected = expected }
127
+ |> renderTemplate AssertEqualTemplate
128
+
129
+ member __.RenderAssertEqualWithin sut expected =
130
+ { Sut = sut; Expected = expected }
131
+ |> renderTemplate AssertEqualWithinTemplate
132
+
133
+ member __.RenderAssertThrows sut expected =
134
+ { Sut = sut; Expected = expected }
135
+ |> renderTemplate AssertThrowsTemplate
115
136
 
116
137
  default __.TestFileFormat = TestFileFormat.Module
117
138
 
@@ -120,21 +141,21 @@ type GeneratorExercise() =
120
141
  member this.Render canonicalData =
121
142
  canonicalData
122
143
  |> this.ToTestFile
123
- |> renderPartialTemplate this.TestFileTemplate
144
+ |> renderTemplate this.TestFileTemplate
124
145
 
125
146
  member this.RenderTestMethod (index, canonicalDataCase) =
126
147
  let template = this.TestMethodTemplate (index, canonicalDataCase)
127
148
 
128
149
  (index, canonicalDataCase)
129
150
  |> this.ToTestMethod
130
- |> renderPartialTemplate template
151
+ |> renderTemplate template
131
152
 
132
153
  member this.RenderTestMethodBody canonicalDataCase =
133
154
  let template = this.TestMethodBodyTemplate canonicalDataCase
134
155
 
135
156
  canonicalDataCase
136
157
  |> this.ToTestMethodBody
137
- |> renderPartialTemplate template
158
+ |> renderTemplate template
138
159
 
139
160
  default this.TestMethodName canonicalDataCase =
140
161
  match this.UseFullMethodName canonicalDataCase with
@@ -213,7 +234,7 @@ type GeneratorExercise() =
213
234
 
214
235
  canonicalDataCase
215
236
  |> this.ToTestMethodBodyAssert
216
- |> renderPartialTemplate template
237
+ |> renderTemplate template
217
238
  |> List.singleton
218
239
 
219
240
  default this.RenderSut canonicalDataCase =
@@ -28,20 +28,18 @@ type Allergies() =
28
28
 
29
29
  let renderAllergenEnum (jToken: JToken) = Obj.renderEnum "Allergen" jToken
30
30
 
31
- let renderAllergicToAssert canonicalDataCase (jToken: JToken) =
31
+ member this.RenderAllergicToAssert canonicalDataCase (jToken: JToken) =
32
32
  let substance = renderAllergenEnum jToken.["substance"]
33
33
  let score = canonicalDataCase.Input.["score"].ToObject<int>()
34
34
  let sut = sprintf "allergicTo %d %s" score substance
35
35
  let expected = jToken.Value<bool>("result") |> Bool.render
36
-
37
- { Sut = sut; Expected = expected }
38
- |> renderPartialTemplate "AssertEqual"
36
+ this.RenderAssertEqual sut expected
39
37
 
40
- override __.RenderAssert canonicalDataCase =
38
+ override this.RenderAssert canonicalDataCase =
41
39
  match canonicalDataCase.Property with
42
40
  | "allergicTo" ->
43
41
  canonicalDataCase.Expected
44
- |> Seq.map (renderAllergicToAssert canonicalDataCase)
42
+ |> Seq.map (this.RenderAllergicToAssert canonicalDataCase)
45
43
  |> Seq.toList
46
44
  | _ ->
47
45
  base.RenderAssert canonicalDataCase
@@ -97,7 +95,7 @@ type BinarySearch() =
97
95
  type BinarySearchTree() =
98
96
  inherit GeneratorExercise()
99
97
 
100
- let rec renderAssertions previousPaths (tree: JToken) =
98
+ member this.RenderAssertions previousPaths (tree: JToken) =
101
99
  let previousPath = previousPaths |> List.rev |> String.concat " |> "
102
100
  let rootPath = List.length previousPaths = 1
103
101
 
@@ -108,30 +106,30 @@ type BinarySearchTree() =
108
106
  match data.Type with
109
107
  | JTokenType.Null ->
110
108
  let expected = if rootPath then failwith "Invalid data" else "None"
111
- [ sprintf "%s |> %s |> should equal %s" previousPath dataPath expected ]
109
+ [ this.RenderAssertEqual (sprintf "%s |> %s" previousPath dataPath) expected ]
112
110
  | _ ->
113
111
  let expected = if rootPath then string data else sprintf "(Some %s)" (string data)
114
- [ sprintf "%s |> %s |> should equal %s" previousPath dataPath expected ]
112
+ [ this.RenderAssertEqual (sprintf "%s |> %s" previousPath dataPath) expected ]
115
113
 
116
114
  let renderNodeAssertions nodeName (node: JToken) =
117
115
  let nodePath = if rootPath then nodeName else sprintf "Option.bind %s" nodeName
118
116
 
119
117
  match node.Type with
120
118
  | JTokenType.Null ->
121
- [ sprintf "%s |> %s |> should equal None" previousPath nodePath ]
119
+ [ this.RenderAssertEqual (sprintf "%s |> %s" previousPath nodePath) "None" ]
122
120
  | _ ->
123
- renderAssertions (nodePath :: previousPaths) node
121
+ this.RenderAssertions (nodePath :: previousPaths) node
124
122
 
125
123
  [ renderDataAssertions
126
124
  renderNodeAssertions "left" tree.["left"]
127
125
  renderNodeAssertions "right" tree.["right"] ]
128
126
  |> List.concat
129
127
 
130
- override __.RenderAssert canonicalDataCase =
128
+ override this.RenderAssert canonicalDataCase =
131
129
  match canonicalDataCase.Property with
132
130
  | "data" ->
133
131
  canonicalDataCase.Expected
134
- |> renderAssertions ["treeData"]
132
+ |> this.RenderAssertions ["treeData"]
135
133
  | _ -> base.RenderAssert canonicalDataCase
136
134
 
137
135
  override __.RenderInput (_, _, value) =
@@ -211,8 +209,7 @@ type CircularBuffer() =
211
209
 
212
210
  override __.RenderAssert _ = []
213
211
 
214
- member __.ExceptionCheck command =
215
- sprintf "(fun () -> %s |> ignore) |> should throw typeof<Exception>" command
212
+ member this.ExceptionCheck command = this.RenderAssertThrows command typeof<Exception>.Name
216
213
 
217
214
  override this.RenderArrange canonicalDataCase =
218
215
  seq {
@@ -243,16 +240,14 @@ type CircularBuffer() =
243
240
  yield sprintf "let (val%i, _) = %s" ind command
244
241
  else
245
242
  yield sprintf "let (val%i, buffer%i) = %s" ind ind command
246
- yield sprintf "val%i |> should equal %i" ind expected
243
+ yield this.RenderAssertEqual (sprintf "val%i" ind) (string expected)
247
244
  | "overwrite" ->
248
245
  yield sprintf "let buffer%i = forceWrite %i buffer%i" ind (dict.["item"].ToObject<int>()) (ind-1)
249
246
  | "clear" ->
250
247
  yield sprintf "let buffer%i = clear buffer%i" ind (ind - 1)
251
248
  | _ -> ()
252
249
  ind <- ind + 1
253
-
254
- }
255
- |> Seq.toList
250
+ } |> Seq.toList
256
251
 
257
252
  type Clock() =
258
253
  inherit GeneratorExercise()
@@ -316,12 +311,11 @@ type ComplexNumbers() =
316
311
  | JTokenType.Integer -> sprintf "%d.0" (value.ToObject<int>())
317
312
  | _ -> base.RenderValue (canonicalDataCase, key, value)
318
313
 
319
- override __.RenderAssert canonicalDataCase =
314
+ override this.RenderAssert canonicalDataCase =
320
315
  match canonicalDataCase.Expected.Type with
321
316
  | JTokenType.Array ->
322
317
  let renderAssertion testedFunction expected =
323
- { Sut = sprintf "%s sut" testedFunction; Expected = expected }
324
- |> renderPartialTemplate "AssertEqualWithin"
318
+ this.RenderAssertEqualWithin (sprintf "%s sut" testedFunction) expected
325
319
 
326
320
  [ canonicalDataCase.Expected.[0] |> renderNumber |> renderAssertion "real"
327
321
  canonicalDataCase.Expected.[1] |> renderNumber |> renderAssertion "imaginary" ]
@@ -451,7 +445,7 @@ type DiffieHellman() =
451
445
  List.append arrange ["let privateKeys = [for _ in 0 .. 10 -> privateKey p]" ]
452
446
  | _ -> arrange
453
447
 
454
- override __.RenderAssert canonicalDataCase =
448
+ override this.RenderAssert canonicalDataCase =
455
449
  match canonicalDataCase.Property with
456
450
  | "privateKeyIsInRange" ->
457
451
  let greaterThan = canonicalDataCase.Expected.["greaterThan"].ToObject<int>()
@@ -460,9 +454,9 @@ type DiffieHellman() =
460
454
  [ sprintf "privateKeys |> List.iter (fun x -> x |> should be (greaterThan %dI))" greaterThan;
461
455
  sprintf "privateKeys |> List.iter (fun x -> x |> should be (lessThan %s))" lessThan ]
462
456
  | "privateKeyIsRandom" ->
463
- [ "List.distinct privateKeys |> List.length |> should equal (List.length privateKeys)" ]
457
+ [ this.RenderAssertEqual "List.distinct privateKeys |> List.length" "(List.length privateKeys)" ]
464
458
  | "keyExchange" ->
465
- [ "secretA |> should equal secretB" ]
459
+ [ this.RenderAssertEqual "secretA" "secretB" ]
466
460
  | _ -> base.RenderAssert canonicalDataCase
467
461
 
468
462
  override __.MapCanonicalDataCase canonicalDataCase =
@@ -647,7 +641,7 @@ type Grep() =
647
641
 
648
642
  override __.RenderExpected (_, _, value) = List.renderMultiLine value |> indentExpected
649
643
 
650
- override __.RenderSetup _ = renderPartialTemplate "Generators/GrepSetup" Map.empty<string, obj>
644
+ override __.RenderSetup _ = renderTemplate "Generators/GrepSetup" Map.empty<string, obj>
651
645
 
652
646
  override __.RenderArrange canonicalDataCase =
653
647
  base.RenderArrange canonicalDataCase @ [""; "createFiles() |> ignore"]
@@ -1046,13 +1040,6 @@ type React() =
1046
1040
  )
1047
1041
  |> Seq.toList
1048
1042
  [ reactorVar ] @ cellVars
1049
-
1050
- let renderExpectedCellValueOperation (op: JToken) =
1051
- seq {
1052
- let cellName = op.["cell"].ToObject<string>()
1053
- let expectedValue = op.["value"].ToObject<int>()
1054
- yield sprintf "%s.Value |> should equal %i" cellName expectedValue
1055
- }
1056
1043
 
1057
1044
  let renderExpectedCallbacks (jToken: JToken) =
1058
1045
  match jToken with
@@ -1101,28 +1088,35 @@ type React() =
1101
1088
  let callbackName = op.["name"].ToObject<string>()
1102
1089
  yield sprintf "%s.Changed.RemoveHandler %sHandler" cellName callbackName
1103
1090
  }
1091
+
1092
+ member this.RenderExpectedCellValueOperation (op: JToken) =
1093
+ seq {
1094
+ let cellName = op.["cell"].ToObject<string>()
1095
+ let expectedValue = op.["value"].ToObject<string>()
1096
+ yield this.RenderAssertEqual (sprintf "%s.Value" cellName) expectedValue
1097
+ }
1098
+
1099
+ member this.RenderOperations canonicalDataCase =
1100
+ canonicalDataCase.Input.["operations"]
1101
+ |> Seq.collect this.renderOperation
1102
+ |> Seq.toList
1104
1103
 
1105
- let renderOperation (op: JToken) =
1104
+ member this.renderOperation (op: JToken) =
1106
1105
  let opType = op.["type"].ToObject<string>()
1107
1106
  match opType with
1108
- | "expect_cell_value" -> renderExpectedCellValueOperation op
1107
+ | "expect_cell_value" -> this.RenderExpectedCellValueOperation op
1109
1108
  | "set_value" -> renderSetValueOperation op
1110
1109
  | "add_callback" -> renderAddCallbackOperation op
1111
1110
  | "remove_callback" -> renderRemoveCallbackOperation op
1112
1111
  | _ -> failwith "Unknown operation type"
1113
1112
 
1114
- let renderOperations canonicalDataCase =
1115
- canonicalDataCase.Input.["operations"]
1116
- |> Seq.collect renderOperation
1117
- |> Seq.toList
1118
-
1119
1113
  override __.PropertiesWithIdentifier _ = []
1120
1114
 
1121
1115
  override __.RenderAssert _ = []
1122
1116
 
1123
- override __.RenderArrange canonicalDataCase =
1117
+ override this.RenderArrange canonicalDataCase =
1124
1118
  let initialVars = renderCells canonicalDataCase
1125
- let operations = renderOperations canonicalDataCase
1119
+ let operations = this.RenderOperations canonicalDataCase
1126
1120
  initialVars @ operations
1127
1121
 
1128
1122
  override __.AdditionalNamespaces = ["FakeItEasy"]
@@ -1170,9 +1164,7 @@ type RobotSimulator() =
1170
1164
  override this.RenderAssert canonicalDataCase =
1171
1165
  let renderAssertWithProperty prop =
1172
1166
  let expected = this.RenderExpected (canonicalDataCase, "expected", canonicalDataCase.Expected)
1173
-
1174
- { Sut = sprintf "sut.%s" prop; Expected = expected }
1175
- |> renderPartialTemplate "AssertEqual"
1167
+ this.RenderAssertEqual (sprintf "sut.%s" prop) expected
1176
1168
 
1177
1169
  match parseInput canonicalDataCase.Expected with
1178
1170
  | None, Some _ -> [renderAssertWithProperty "position"]
@@ -2,63 +2,34 @@ module Generators.Templates
2
2
 
3
3
  open System.IO
4
4
  open System.Collections.Generic
5
- open System.Reflection
6
5
  open FSharp.Reflection
7
6
  open DotLiquid
8
7
  open DotLiquid.FileSystems
9
8
  open Rendering
10
9
 
11
10
  type OutputFilter() =
12
- static member Format (input: string) = Obj.render input
13
-
14
11
  static member Indent (input: string) = String.indent 1 input
15
12
 
16
- let private fileSystem = LocalFileSystem(Path.GetFullPath("./Templates"))
17
- Template.RegisterFilter(OutputFilter().GetType())
18
- Template.FileSystem <- fileSystem :> DotLiquid.FileSystems.IFileSystem
13
+ let private initTemplate() =
14
+ Template.FileSystem <- LocalFileSystem(Path.GetFullPath("./Templates"))
15
+
16
+ Template.RegisterFilter(OutputFilter().GetType()) |> ignore
19
17
 
20
- let private registrations = Dictionary<_,_>()
21
- let rec private registerTypeTree templateDataType =
22
- if registrations.ContainsKey templateDataType then ()
23
- elif FSharpType.IsRecord templateDataType then
24
- let properties = templateDataType.GetProperties(BindingFlags.Instance ||| BindingFlags.Public)
25
- Template.RegisterSafeType(templateDataType, [| for p in properties -> p.Name |])
26
- registrations.[templateDataType] <- true
27
- for p in properties do registerTypeTree p.PropertyType
28
- elif templateDataType.IsGenericType then
29
- let t = templateDataType.GetGenericTypeDefinition()
30
- if t = typedefof<seq<_>> || t = typedefof<list<_>> then
31
- registrations.[templateDataType] <- true
32
- registerTypeTree (templateDataType.GetGenericArguments().[0])
33
- elif t = typedefof<IDictionary<_,_>> || t = typedefof<Map<_,_>> then
34
- registrations.[templateDataType] <- true
35
- registerTypeTree (templateDataType.GetGenericArguments().[0])
36
- registerTypeTree (templateDataType.GetGenericArguments().[1])
37
- elif t = typedefof<option<_>> then
38
- Template.RegisterSafeType(templateDataType, [|"Value"; "IsSome"; "IsNone";|])
39
- registrations.[templateDataType] <- true
40
- registerTypeTree (templateDataType.GetGenericArguments().[0])
41
- elif templateDataType.IsArray then
42
- registrations.[templateDataType] <- true
43
- registerTypeTree (templateDataType.GetElementType())
44
- else
45
- let properties = templateDataType.GetProperties(BindingFlags.Instance ||| BindingFlags.Public)
46
- Template.RegisterSafeType(templateDataType, [| for p in properties -> p.Name |])
47
- registrations.[templateDataType] <- true
48
- for p in properties do registerTypeTree p.PropertyType
18
+ Template.RegisterSafeType(typeof<TestMethodBodyAssert>, [| "Sut"; "Expected" |])
19
+ Template.RegisterSafeType(typeof<TestMethodBody>, [| "Arrange"; "Assert" |])
20
+ Template.RegisterSafeType(typeof<TestMethod>, [| "Skip"; "Name"; "Body" |])
21
+ Template.RegisterSafeType(typeof<TestFile>, [| "Version"; "TestModuleName"; "TestedModuleName"; "Namespaces"; "Setup"; "Methods" |])
49
22
 
50
23
  let private hashFromData (data: obj) =
51
24
  match FSharpType.IsRecord (data.GetType()) with
52
25
  | true -> Hash.FromAnonymousObject(data)
53
26
  | false -> Hash.FromDictionary(data :?> IDictionary<string, obj>)
54
27
 
55
- let renderInlineTemplate template data =
56
- data.GetType() |> registerTypeTree
57
-
58
- let parsedTemplate = Template.Parse template
59
- let hash = hashFromData data
60
- parsedTemplate.Render(hash)
28
+ let renderTemplate =
29
+ initTemplate()
61
30
 
62
- let renderPartialTemplate templateName data =
63
- let template = sprintf "{%% include \"%s\" %%}" templateName
64
- renderInlineTemplate template data
31
+ fun (name: string) (data: obj) ->
32
+ let template = sprintf "{%% include \"%s\" %%}" name
33
+ let parsedTemplate = Template.Parse template
34
+ let hashedData = hashFromData data
35
+ parsedTemplate.Render hashedData
@@ -34,6 +34,7 @@ install:
34
34
 
35
35
  script:
36
36
  - "sh ./bin/ensure-readmes-are-updated.sh"
37
+ - "sh ./bin/check-configlet-fmt.sh"
37
38
  - |
38
39
  differing_stack=""
39
40
  expected_stack=$(grep 'RESOLVER.*CURRENT' .travis.yml | head -1 | cut -d'"' -f2)
@@ -0,0 +1,42 @@
1
+ #!/bin/sh
2
+
3
+ # This ensures that config.json and config/maintainers.json are compatible
4
+ # with the output of configlet fmt.
5
+
6
+ repo=$(cd "$(dirname "$0")/.." && pwd)
7
+ configlet="${repo}/bin/configlet"
8
+
9
+ if [ ! -x "$configlet" ]; then
10
+ # Try it from the path.
11
+ configlet=configlet
12
+ fi
13
+
14
+ c="${repo}/config.json"
15
+ m="${repo}/config/maintainers.json"
16
+
17
+ md5() {
18
+ md5sum $1 | cut -d' ' -f1
19
+ }
20
+
21
+ # before S sum
22
+ bcs=$(md5 $c)
23
+ bms=$(md5 $m)
24
+
25
+ cfg=$($configlet fmt .)
26
+ if [ $? != 0 ]; then
27
+ echo "configlet fmt returned non-0 exit code with output:"
28
+ echo $cfg
29
+ exit 1
30
+ fi
31
+
32
+ # after S sum
33
+ acs=$(md5 $c)
34
+ ams=$(md5 $m)
35
+
36
+ if [ $bcs != $acs -o $bms != $ams ]; then
37
+ echo "configlet fmt:"
38
+ echo $cfg
39
+ echo "Please update the PR to incorporate those changes."
40
+ exit 1
41
+ fi
42
+ exit 0