trackler 2.2.1.147 → 2.2.1.148

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 (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