diff --git a/CHANGELOG.md b/CHANGELOG.md index ac886951..86927278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ - Now accessing undefined keys in NSObject does not cause runtime crash and instead renders empty string. [Ilya Puchka](https://github.com/ilyapuchka) [#234](https://github.com/stencilproject/Stencil/pull/234) +- `for` tag: When iterating over a dictionary the keys will now always be sorted (in an ascending order) to ensure consistent output generation. + [David Jennes](https://github.com/djbe) + [#240](https://github.com/stencilproject/Stencil/pull/240) ### Breaking Changes diff --git a/Sources/ForTag.swift b/Sources/ForTag.swift index e2969a7d..0bc8775c 100644 --- a/Sources/ForTag.swift +++ b/Sources/ForTag.swift @@ -93,7 +93,7 @@ class ForNode : NodeType { var values: [Any] if let dictionary = resolved as? [String: Any], !dictionary.isEmpty { - values = dictionary.map { ($0.key, $0.value) } + values = dictionary.sorted { $0.key < $1.key } } else if let array = resolved as? [Any] { values = array } else if let range = resolved as? CountableClosedRange { diff --git a/Tests/StencilTests/ForNodeSpec.swift b/Tests/StencilTests/ForNodeSpec.swift index f292a153..e362e916 100644 --- a/Tests/StencilTests/ForNodeSpec.swift +++ b/Tests/StencilTests/ForNodeSpec.swift @@ -209,8 +209,9 @@ func testForNode() { let template = Template(templateString: templateString) let result = try template.render(context) - let sortedResult = result.split(separator: ",").map(String.init).sorted(by: <) - try expect(sortedResult) == ["one: I", "two: II"] + try expect(result) == """ + one: I,two: II, + """ } $0.it("renders supports iterating over dictionary") { @@ -222,8 +223,9 @@ func testForNode() { let node = ForNode(resolvable: Variable("dict"), loopVariables: ["key"], nodes: nodes, emptyNodes: emptyNodes, where: nil) let result = try node.render(context) - let sortedResult = result.split(separator: ",").map(String.init).sorted(by: <) - try expect(sortedResult) == ["one", "two"] + try expect(result) == """ + one,two, + """ } $0.it("renders supports iterating over dictionary") { @@ -235,11 +237,11 @@ func testForNode() { ] let emptyNodes: [NodeType] = [TextNode(text: "empty")] let node = ForNode(resolvable: Variable("dict"), loopVariables: ["key", "value"], nodes: nodes, emptyNodes: emptyNodes, where: nil) - let result = try node.render(context) - let sortedResult = result.split(separator: ",").map(String.init).sorted(by: <) - try expect(sortedResult) == ["one=I", "two=II"] + try expect(result) == """ + one=I,two=II, + """ } $0.it("handles invalid input") {