Update from Hummingbird Project Template (#58)
* Update from hummingbird-project-template 572d468b2cabeca286314c5a35196bd42445c8ef * run swift-format * Remove .swiftformat --------- Co-authored-by: adam-fowler <adam-fowler@users.noreply.github.com> Co-authored-by: Adam Fowler <adamfowler71@gmail.com>
This commit is contained in:
committed by
GitHub
parent
8c5c8ead74
commit
ec4ef9aa04
@@ -17,11 +17,15 @@ import XCTest
|
||||
|
||||
final class ErrorTests: XCTestCase {
|
||||
func testSectionCloseNameIncorrect() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
{{/test2}}
|
||||
""")) { error in
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
{{/test2}}
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .sectionCloseNameIncorrect)
|
||||
@@ -36,11 +40,15 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testUnfinishedName() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{#test}}
|
||||
{{name}
|
||||
{{/test2}}
|
||||
""")) { error in
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{#test}}
|
||||
{{name}
|
||||
{{/test2}}
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .unfinishedName)
|
||||
@@ -55,10 +63,14 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testExpectedSectionEnd() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
""")) { error in
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{#test}}
|
||||
{{.}}
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .expectedSectionEnd)
|
||||
@@ -73,11 +85,15 @@ final class ErrorTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testInvalidSetDelimiter() {
|
||||
XCTAssertThrowsError(try MustacheTemplate(string: """
|
||||
{{=<% %>=}}
|
||||
<%.%>
|
||||
<%={{}}=%>
|
||||
""")) { error in
|
||||
XCTAssertThrowsError(
|
||||
try MustacheTemplate(
|
||||
string: """
|
||||
{{=<% %>=}}
|
||||
<%.%>
|
||||
<%={{}}=%>
|
||||
"""
|
||||
)
|
||||
) { error in
|
||||
switch error {
|
||||
case let error as MustacheTemplate.ParserError:
|
||||
XCTAssertEqual(error.error as? MustacheTemplate.Error, .invalidSetDelimiter)
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Mustache
|
||||
import XCTest
|
||||
|
||||
@testable import Mustache
|
||||
|
||||
final class LibraryTests: XCTestCase {
|
||||
func testDirectoryLoad() async throws {
|
||||
let fs = FileManager()
|
||||
@@ -54,11 +55,13 @@ final class LibraryTests: XCTestCase {
|
||||
let mustache = Data("<test>{{#value}}<value>{{.}}</value>{{/value}}</test>".utf8)
|
||||
try mustache.write(to: URL(fileURLWithPath: "templates/test.mustache"))
|
||||
defer { XCTAssertNoThrow(try fs.removeItem(atPath: "templates/test.mustache")) }
|
||||
let mustache2 = Data("""
|
||||
{{#test}}
|
||||
{{{name}}
|
||||
{{/test2}}
|
||||
""".utf8)
|
||||
let mustache2 = Data(
|
||||
"""
|
||||
{{#test}}
|
||||
{{{name}}
|
||||
{{/test2}}
|
||||
""".utf8
|
||||
)
|
||||
try mustache2.write(to: URL(fileURLWithPath: "templates/error.mustache"))
|
||||
defer { XCTAssertNoThrow(try fs.removeItem(atPath: "templates/error.mustache")) }
|
||||
|
||||
|
||||
@@ -12,120 +12,156 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Mustache
|
||||
import XCTest
|
||||
|
||||
@testable import Mustache
|
||||
|
||||
final class PartialTests: XCTestCase {
|
||||
/// Testing partials
|
||||
func testMustacheManualExample9() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
{{/names}}
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
<strong>{{.}}</strong>
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
{{/names}}
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
<strong>{{.}}</strong>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let library = MustacheLibrary(templates: ["base": template, "user": template2])
|
||||
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base"),
|
||||
"""
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// Test where last line of partial generates no content. It should not add a
|
||||
/// tab either
|
||||
func testPartialEmptyLineTabbing() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
{{/names}}
|
||||
Text after
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h2>Names</h2>
|
||||
{{#names}}
|
||||
{{> user}}
|
||||
{{/names}}
|
||||
Text after
|
||||
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
{{^empty(.)}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/empty(.)}}
|
||||
{{#empty(.)}}
|
||||
<strong>empty</strong>
|
||||
{{/empty(.)}}
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
{{^empty(.)}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/empty(.)}}
|
||||
{{#empty(.)}}
|
||||
<strong>empty</strong>
|
||||
{{/empty(.)}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
var library = MustacheLibrary()
|
||||
library.register(template, named: "base")
|
||||
library.register(template2, named: "user")
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
Text after
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base"),
|
||||
"""
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
Text after
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testTrailingNewLines() throws {
|
||||
let template1 = try MustacheTemplate(string: """
|
||||
{{> withNewLine }}
|
||||
>> {{> withNewLine }}
|
||||
[ {{> withNewLine }} ]
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
{{> withoutNewLine }}
|
||||
>> {{> withoutNewLine }}
|
||||
[ {{> withoutNewLine }} ]
|
||||
""")
|
||||
let withNewLine = try MustacheTemplate(string: """
|
||||
{{#things}}{{.}}, {{/things}}
|
||||
let template1 = try MustacheTemplate(
|
||||
string: """
|
||||
{{> withNewLine }}
|
||||
>> {{> withNewLine }}
|
||||
[ {{> withNewLine }} ]
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
{{> withoutNewLine }}
|
||||
>> {{> withoutNewLine }}
|
||||
[ {{> withoutNewLine }} ]
|
||||
"""
|
||||
)
|
||||
let withNewLine = try MustacheTemplate(
|
||||
string: """
|
||||
{{#things}}{{.}}, {{/things}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let withoutNewLine = try MustacheTemplate(string: "{{#things}}{{.}}, {{/things}}")
|
||||
let library = MustacheLibrary(templates: ["base1": template1, "base2": template2, "withNewLine": withNewLine, "withoutNewLine": withoutNewLine])
|
||||
let library = MustacheLibrary(templates: [
|
||||
"base1": template1, "base2": template2, "withNewLine": withNewLine, "withoutNewLine": withoutNewLine,
|
||||
])
|
||||
let object = ["things": [1, 2, 3, 4, 5]]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base1"), """
|
||||
1, 2, 3, 4, 5,
|
||||
>> 1, 2, 3, 4, 5,
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base1"),
|
||||
"""
|
||||
1, 2, 3, 4, 5,
|
||||
>> 1, 2, 3, 4, 5,
|
||||
|
||||
[ 1, 2, 3, 4, 5,
|
||||
]
|
||||
""")
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base2"), """
|
||||
1, 2, 3, 4, 5, >> 1, 2, 3, 4, 5,
|
||||
[ 1, 2, 3, 4, 5, ]
|
||||
""")
|
||||
[ 1, 2, 3, 4, 5,
|
||||
]
|
||||
"""
|
||||
)
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base2"),
|
||||
"""
|
||||
1, 2, 3, 4, 5, >> 1, 2, 3, 4, 5,
|
||||
[ 1, 2, 3, 4, 5, ]
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// Testing dynamic partials
|
||||
func testDynamicPartials() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h2>Names</h2>
|
||||
{{partial}}
|
||||
""")
|
||||
let template2 = try MustacheTemplate(string: """
|
||||
{{#names}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/names}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h2>Names</h2>
|
||||
{{partial}}
|
||||
"""
|
||||
)
|
||||
let template2 = try MustacheTemplate(
|
||||
string: """
|
||||
{{#names}}
|
||||
<strong>{{.}}</strong>
|
||||
{{/names}}
|
||||
"""
|
||||
)
|
||||
let library = MustacheLibrary(templates: ["base": template])
|
||||
|
||||
let object: [String: Any] = ["names": ["john", "adam", "claire"], "partial": template2]
|
||||
XCTAssertEqual(library.render(object, withTemplate: "base"), """
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "base"),
|
||||
"""
|
||||
<h2>Names</h2>
|
||||
<strong>john</strong>
|
||||
<strong>adam</strong>
|
||||
<strong>claire</strong>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test inheritance
|
||||
@@ -163,15 +199,18 @@ final class PartialTests: XCTestCase {
|
||||
""",
|
||||
named: "mypage"
|
||||
)
|
||||
XCTAssertEqual(library.render({}, withTemplate: "mypage")!, """
|
||||
<html>
|
||||
<head>
|
||||
<title>My page title</title>
|
||||
</head>
|
||||
<h1>Hello world</h1>
|
||||
</html>
|
||||
XCTAssertEqual(
|
||||
library.render({}, withTemplate: "mypage")!,
|
||||
"""
|
||||
<html>
|
||||
<head>
|
||||
<title>My page title</title>
|
||||
</head>
|
||||
<h1>Hello world</h1>
|
||||
</html>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testInheritanceIndentation() throws {
|
||||
@@ -194,11 +233,14 @@ final class PartialTests: XCTestCase {
|
||||
""",
|
||||
named: "template"
|
||||
)
|
||||
XCTAssertEqual(library.render({}, withTemplate: "template"), """
|
||||
Hi,
|
||||
one
|
||||
two
|
||||
XCTAssertEqual(
|
||||
library.render({}, withTemplate: "template"),
|
||||
"""
|
||||
Hi,
|
||||
one
|
||||
two
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@ extension AnyDecodable {
|
||||
self.init(dictionary.mapValues { $0.value })
|
||||
} else {
|
||||
throw DecodingError.dataCorruptedError(
|
||||
in: container, debugDescription: "AnyDecodable value cannot be decoded"
|
||||
in: container,
|
||||
debugDescription: "AnyDecodable value cannot be decoded"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -102,7 +103,8 @@ final class MustacheSpecTests: XCTestCase {
|
||||
\(result ?? "nil")
|
||||
expected:
|
||||
\(test.expected)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +115,8 @@ final class MustacheSpecTests: XCTestCase {
|
||||
|
||||
func testSpec(name: String, ignoring: [String] = []) async throws {
|
||||
let url = URL(
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json")!
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json"
|
||||
)!
|
||||
try await testSpec(url: url, ignoring: ignoring)
|
||||
}
|
||||
|
||||
@@ -135,7 +138,8 @@ final class MustacheSpecTests: XCTestCase {
|
||||
|
||||
func testSpec(name: String, only: [String]) async throws {
|
||||
let url = URL(
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json")!
|
||||
string: "https://raw.githubusercontent.com/mustache/spec/master/specs/\(name).json"
|
||||
)!
|
||||
try await testSpec(url: url, only: only)
|
||||
}
|
||||
|
||||
@@ -161,7 +165,12 @@ final class MustacheSpecTests: XCTestCase {
|
||||
"Interpolation": MustacheLambda { "world" },
|
||||
"Interpolation - Expansion": MustacheLambda { "{{planet}}" },
|
||||
"Interpolation - Alternate Delimiters": MustacheLambda { "|planet| => {{planet}}" },
|
||||
"Interpolation - Multiple Calls": MustacheLambda { return MustacheLambda { g += 1; return g }},
|
||||
"Interpolation - Multiple Calls": MustacheLambda {
|
||||
return MustacheLambda {
|
||||
g += 1
|
||||
return g
|
||||
}
|
||||
},
|
||||
"Escaping": MustacheLambda { ">" },
|
||||
"Section": MustacheLambda { text in text == "{{x}}" ? "yes" : "no" },
|
||||
"Section - Expansion": MustacheLambda { text in text + "{{planet}}" + text },
|
||||
|
||||
@@ -12,9 +12,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@testable import Mustache
|
||||
import XCTest
|
||||
|
||||
@testable import Mustache
|
||||
|
||||
final class TemplateParserTests: XCTestCase {
|
||||
func testText() throws {
|
||||
let template = try MustacheTemplate(string: "test template")
|
||||
|
||||
@@ -141,81 +141,103 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// variables
|
||||
func testMustacheManualVariables() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
Hello {{name}}
|
||||
You have just won {{value}} dollars!
|
||||
{{#in_ca}}
|
||||
Well, {{taxed_value}} dollars, after taxes.
|
||||
{{/in_ca}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
Hello {{name}}
|
||||
You have just won {{value}} dollars!
|
||||
{{#in_ca}}
|
||||
Well, {{taxed_value}} dollars, after taxes.
|
||||
{{/in_ca}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["name": "Chris", "value": 10000, "taxed_value": 10000 - (10000 * 0.4), "in_ca": true]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
Hello Chris
|
||||
You have just won 10000 dollars!
|
||||
Well, 6000.0 dollars, after taxes.
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
Hello Chris
|
||||
You have just won 10000 dollars!
|
||||
Well, 6000.0 dollars, after taxes.
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test escaped and unescaped text
|
||||
func testMustacheManualEscapedText() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
*{{name}}
|
||||
*{{age}}
|
||||
*{{company}}
|
||||
*{{{company}}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
*{{name}}
|
||||
*{{age}}
|
||||
*{{company}}
|
||||
*{{{company}}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["name": "Chris", "company": "<b>GitHub</b>"]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
*Chris
|
||||
*
|
||||
*<b>GitHub</b>
|
||||
*<b>GitHub</b>
|
||||
""")
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
*Chris
|
||||
*
|
||||
*<b>GitHub</b>
|
||||
*<b>GitHub</b>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test dotted names
|
||||
func test_MustacheManualDottedNames() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
* {{client.name}}
|
||||
* {{age}}
|
||||
* {{client.company.name}}
|
||||
* {{{company.name}}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
* {{client.name}}
|
||||
* {{age}}
|
||||
* {{client.company.name}}
|
||||
* {{{company.name}}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = [
|
||||
"client": (
|
||||
name: "Chris & Friends",
|
||||
age: 50
|
||||
),
|
||||
"company": [
|
||||
"name": "<b>GitHub</b>",
|
||||
"name": "<b>GitHub</b>"
|
||||
],
|
||||
]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
* Chris & Friends
|
||||
*
|
||||
*
|
||||
* <b>GitHub</b>
|
||||
""")
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
* Chris & Friends
|
||||
*
|
||||
*
|
||||
* <b>GitHub</b>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test implicit operator
|
||||
func testMustacheManualImplicitOperator() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
* {{.}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
* {{.}}
|
||||
"""
|
||||
)
|
||||
let object = "Hello!"
|
||||
XCTAssertEqual(template.render(object), """
|
||||
* Hello!
|
||||
""")
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
* Hello!
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test lambda
|
||||
func test_MustacheManualLambda() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
* {{time.hour}}
|
||||
* {{today}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
* {{time.hour}}
|
||||
* {{today}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = [
|
||||
"year": 1970,
|
||||
"month": 1,
|
||||
@@ -231,113 +253,151 @@ final class TemplateRendererTests: XCTestCase {
|
||||
return "{{year}}-{{month}}-{{day}}"
|
||||
},
|
||||
]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
* 0
|
||||
* 1970-1-1
|
||||
""")
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
* 0
|
||||
* 1970-1-1
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test boolean
|
||||
func testMustacheManualSectionFalse() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
Shown.
|
||||
{{#person}}
|
||||
Never shown!
|
||||
{{/person}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
Shown.
|
||||
{{#person}}
|
||||
Never shown!
|
||||
{{/person}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["person": false]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
Shown.
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
Shown.
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test non-empty lists
|
||||
func testMustacheManualSectionList() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test non-empty lists
|
||||
func testMustacheManualSectionList2() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{.}}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{.}}</b>
|
||||
{{/repo}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["resque", "hub", "rip"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test lambdas
|
||||
func testMustacheManualSectionLambda() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#wrapped}}{{name}} is awesome.{{/wrapped}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#wrapped}}{{name}} is awesome.{{/wrapped}}
|
||||
"""
|
||||
)
|
||||
func wrapped(_ s: String) -> Any? {
|
||||
return "<b>\(s)</b>"
|
||||
"<b>\(s)</b>"
|
||||
}
|
||||
let object: [String: Any] = ["name": "Willy", "wrapped": MustacheLambda(wrapped)]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>Willy is awesome.</b>
|
||||
""")
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>Willy is awesome.</b>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test setting context object
|
||||
func testMustacheManualContextObject() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#person?}}
|
||||
Hi {{name}}!
|
||||
{{/person?}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#person?}}
|
||||
Hi {{name}}!
|
||||
{{/person?}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["person?": ["name": "Jon"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
Hi Jon!
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
Hi Jon!
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test inverted sections
|
||||
func testMustacheManualInvertedSection() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
{{^repo}}
|
||||
No repos :(
|
||||
{{/repo}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
{{^repo}}
|
||||
No repos :(
|
||||
{{/repo}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": []]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
No repos :(
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
No repos :(
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test comments
|
||||
func testMustacheManualComment() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h1>Today{{! ignore me }}.</h1>
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h1>Today{{! ignore me }}.</h1>
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": []]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<h1>Today.</h1>
|
||||
""")
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<h1>Today.</h1>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
/// test dynamic names
|
||||
@@ -357,18 +417,23 @@ final class TemplateRendererTests: XCTestCase {
|
||||
|
||||
/// test block with defaults
|
||||
func testMustacheManualBlocksWithDefaults() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
<h1>{{$title}}The News of Today{{/title}}</h1>
|
||||
{{$body}}
|
||||
<p>Nothing special happened.</p>
|
||||
{{/body}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
<h1>{{$title}}The News of Today{{/title}}</h1>
|
||||
{{$body}}
|
||||
<p>Nothing special happened.</p>
|
||||
{{/body}}
|
||||
|
||||
""")
|
||||
XCTAssertEqual(template.render([]), """
|
||||
<h1>The News of Today</h1>
|
||||
<p>Nothing special happened.</p>
|
||||
"""
|
||||
)
|
||||
XCTAssertEqual(
|
||||
template.render([]),
|
||||
"""
|
||||
<h1>The News of Today</h1>
|
||||
<p>Nothing special happened.</p>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testMustacheManualParents() throws {
|
||||
@@ -405,7 +470,7 @@ final class TemplateRendererTests: XCTestCase {
|
||||
"headlines": [
|
||||
"A pug's handler grew mustaches.",
|
||||
"What an exciting day!",
|
||||
],
|
||||
]
|
||||
]
|
||||
XCTAssertEqual(
|
||||
library.render(object, withTemplate: "main"),
|
||||
@@ -474,11 +539,13 @@ final class TemplateRendererTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testPerformance() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
let date = Date()
|
||||
for _ in 1...10000 {
|
||||
|
||||
@@ -17,177 +17,233 @@ import XCTest
|
||||
|
||||
final class TransformTests: XCTestCase {
|
||||
func testLowercased() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{ lowercased(name) }}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{ lowercased(name) }}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["name": "Test"]
|
||||
XCTAssertEqual(template.render(object), "test")
|
||||
}
|
||||
|
||||
func testUppercased() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{ uppercased(name) }}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{ uppercased(name) }}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["name": "Test"]
|
||||
XCTAssertEqual(template.render(object), "TEST")
|
||||
}
|
||||
|
||||
func testNewline() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{name}}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>resque</b>
|
||||
<b>hub</b>
|
||||
<b>rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testFirstLast() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{#first()}}first: {{/first()}}{{#last()}}last: {{/last()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{#first()}}first: {{/first()}}{{#last()}}last: {{/last()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>first: resque</b>
|
||||
<b>hub</b>
|
||||
<b>last: rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>first: resque</b>
|
||||
<b>hub</b>
|
||||
<b>last: rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testIndex() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{#index()}}{{plusone(.)}}{{/index()}}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{#index()}}{{plusone(.)}}{{/index()}}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>1) resque</b>
|
||||
<b>2) hub</b>
|
||||
<b>3) rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>1) resque</b>
|
||||
<b>2) hub</b>
|
||||
<b>3) rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testDoubleSequenceTransformWorks() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
{{count(reversed(numbers))}}
|
||||
{{/repo}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
{{count(reversed(numbers))}}
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["numbers": [1, 2, 3]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
3
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
3
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testMultipleTransformWorks() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
{{minusone(plusone(last(reversed(numbers))))}}
|
||||
{{/repo}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
{{minusone(plusone(last(reversed(numbers))))}}
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["numbers": [5, 4, 3]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
5
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
5
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testNestedTransformWorks() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
{{#uppercased(string)}}{{reversed(.)}}{{/uppercased(string)}}
|
||||
{{/repo}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
{{#uppercased(string)}}{{reversed(.)}}{{/uppercased(string)}}
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["string": "a123a"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
A321A
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
A321A
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testEvenOdd() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{index()}}) {{#even()}}even {{/even()}}{{#odd()}}odd {{/odd()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{index()}}) {{#even()}}even {{/even()}}{{#odd()}}odd {{/odd()}}{{ name }}</b>
|
||||
{{/repo}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>0) even resque</b>
|
||||
<b>1) odd hub</b>
|
||||
<b>2) even rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>0) even resque</b>
|
||||
<b>1) odd hub</b>
|
||||
<b>2) even rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testReversed() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#reversed(repo)}}
|
||||
<b>{{ name }}</b>
|
||||
{{/reversed(repo)}}
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#reversed(repo)}}
|
||||
<b>{{ name }}</b>
|
||||
{{/reversed(repo)}}
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>rip</b>
|
||||
<b>hub</b>
|
||||
<b>resque</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>rip</b>
|
||||
<b>hub</b>
|
||||
<b>resque</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testArrayIndex() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#repo}}
|
||||
<b>{{ index() }}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#repo}}
|
||||
<b>{{ index() }}) {{ name }}</b>
|
||||
{{/repo}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": [["name": "resque"], ["name": "hub"], ["name": "rip"]]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>0) resque</b>
|
||||
<b>1) hub</b>
|
||||
<b>2) rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>0) resque</b>
|
||||
<b>1) hub</b>
|
||||
<b>2) rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testArraySorted() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#sorted(repo)}}
|
||||
<b>{{ index() }}) {{ . }}</b>
|
||||
{{/sorted(repo)}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#sorted(repo)}}
|
||||
<b>{{ index() }}) {{ . }}</b>
|
||||
{{/sorted(repo)}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["repo": ["resque", "hub", "rip"]]
|
||||
XCTAssertEqual(template.render(object), """
|
||||
<b>0) hub</b>
|
||||
<b>1) resque</b>
|
||||
<b>2) rip</b>
|
||||
XCTAssertEqual(
|
||||
template.render(object),
|
||||
"""
|
||||
<b>0) hub</b>
|
||||
<b>1) resque</b>
|
||||
<b>2) rip</b>
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
func testDictionaryEmpty() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#empty(array)}}Array{{/empty(array)}}{{#empty(dictionary)}}Dictionary{{/empty(dictionary)}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#empty(array)}}Array{{/empty(array)}}{{#empty(dictionary)}}Dictionary{{/empty(dictionary)}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["array": [], "dictionary": [:]]
|
||||
XCTAssertEqual(template.render(object), "ArrayDictionary")
|
||||
}
|
||||
@@ -199,18 +255,22 @@ final class TransformTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testDictionaryEnumerated() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#enumerated(.)}}<b>{{ key }} = {{ value }}</b>{{/enumerated(.)}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#enumerated(.)}}<b>{{ key }} = {{ value }}</b>{{/enumerated(.)}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["one": 1, "two": 2]
|
||||
let result = template.render(object)
|
||||
XCTAssertTrue(result == "<b>one = 1</b><b>two = 2</b>" || result == "<b>two = 2</b><b>one = 1</b>")
|
||||
}
|
||||
|
||||
func testDictionarySortedByKey() throws {
|
||||
let template = try MustacheTemplate(string: """
|
||||
{{#sorted(.)}}<b>{{ key }} = {{ value }}</b>{{/sorted(.)}}
|
||||
""")
|
||||
let template = try MustacheTemplate(
|
||||
string: """
|
||||
{{#sorted(.)}}<b>{{ key }} = {{ value }}</b>{{/sorted(.)}}
|
||||
"""
|
||||
)
|
||||
let object: [String: Any] = ["one": 1, "two": 2, "three": 3]
|
||||
let result = template.render(object)
|
||||
XCTAssertEqual(result, "<b>one = 1</b><b>three = 3</b><b>two = 2</b>")
|
||||
|
||||
Reference in New Issue
Block a user