refactored environment tests

This commit is contained in:
Ilya Puchka
2017-12-26 20:48:43 +01:00
parent 7756522317
commit ed885f462a

View File

@@ -5,7 +5,13 @@ import PathKit
func testEnvironment() { func testEnvironment() {
describe("Environment") { describe("Environment") {
let environment = Environment(loader: ExampleLoader()) var environment: Environment!
var template: Template!
$0.before {
environment = Environment(loader: ExampleLoader())
template = nil
}
$0.it("can load a template from a name") { $0.it("can load a template from a name") {
let template = try environment.loadTemplate(name: "example.html") let template = try environment.loadTemplate(name: "example.html")
@@ -39,250 +45,264 @@ func testEnvironment() {
return TemplateSyntaxError(reason: description, token: token, template: template, parentError: nil) return TemplateSyntaxError(reason: description, token: token, template: template, parentError: nil)
} }
$0.it("reports syntax error on invalid for tag syntax") { func expectError(reason: String, token: String) throws {
let template: Template = "Hello {% for name in %}{{ name }}, {% endfor %}!" let expectedError = expectedSyntaxError(token: token, template: template, description: reason)
let error = expectedSyntaxError(token: "for name in", template: template, description: "'for' statements should use the following syntax 'for x in y where condition'.")
try expect(try environment.renderTemplate(string: template.templateString, context:["names": ["Bob", "Alice"]])).toThrow(error) let error = try expect(environment.render(template: template, context: ["names": ["Bob", "Alice"], "name": "Bob"]))
.toThrow(expectedError)
try expect(environment.errorReporter.renderError(error)) == environment.errorReporter.renderError(expectedError)
} }
$0.it("reports syntax error on missing endfor") { $0.context("given syntax error") {
let template: Template = "{% for name in names %}{{ name }}"
let error = expectedSyntaxError(token: "for name in names", template: template, description: "`endfor` was not found.") $0.it("reports syntax error on invalid for tag syntax") {
try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error) template = "Hello {% for name in %}{{ name }}, {% endfor %}!"
} try expectError(reason: "'for' statements should use the following syntax 'for x in y where condition'.", token: "for name in")
}
$0.it("reports syntax error on missing endfor") {
template = "{% for name in names %}{{ name }}"
try expectError(reason: "`endfor` was not found.", token: "for name in names")
}
$0.it("reports syntax error on unknown tag") {
template = "{% for name in names %}{{ name }}{% end %}"
try expectError(reason: "Unknown template tag 'end'", token: "end")
}
$0.it("reports syntax error on unknown tag") {
let template: Template = "{% for name in names %}{{ name }}{% end %}"
let error = expectedSyntaxError(token: "end", template: template, description: "Unknown template tag 'end'")
try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error)
} }
$0.context("given unknown filter") { $0.context("given unknown filter") {
func expectedFilterError(token: String, template: Template) -> TemplateSyntaxError {
return expectedSyntaxError(token: token, template: template, description: "Unknown filter 'unknown'")
}
$0.it("reports syntax error in for tag") { $0.it("reports syntax error in for tag") {
let template: Template = "{% for name in names|unknown %}{{ name }}{% endfor %}" template = "{% for name in names|unknown %}{{ name }}{% endfor %}"
let error = expectedFilterError(token: "names|unknown", template: template) try expectError(reason: "Unknown filter 'unknown'", token: "names|unknown")
try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error)
} }
$0.it("reports syntax error in for-where tag") { $0.it("reports syntax error in for-where tag") {
let template: Template = "{% for name in names where name|unknown %}{{ name }}{% endfor %}" template = "{% for name in names where name|unknown %}{{ name }}{% endfor %}"
let error = expectedFilterError(token: "name|unknown", template: template) try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown")
try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error)
} }
$0.it("reports syntax error in if tag") { $0.it("reports syntax error in if tag") {
let template: Template = "{% if name|unknown %}{{ name }}{% endif %}" template = "{% if name|unknown %}{{ name }}{% endif %}"
let error = expectedFilterError(token: "name|unknown", template: template) try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown")
try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error)
} }
$0.it("reports syntax error in elif tag") { $0.it("reports syntax error in elif tag") {
let template: Template = "{% if name %}{{ name }}{% elif name|unknown %}{% endif %}" template = "{% if name %}{{ name }}{% elif name|unknown %}{% endif %}"
let error = expectedFilterError(token: "name|unknown", template: template) try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown")
try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error)
} }
$0.it("reports syntax error in ifnot tag") { $0.it("reports syntax error in ifnot tag") {
let template: Template = "{% ifnot name|unknown %}{{ name }}{% endif %}" template = "{% ifnot name|unknown %}{{ name }}{% endif %}"
let error = expectedFilterError(token: "name|unknown", template: template) try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown")
try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error)
} }
$0.it("reports syntax error in filter tag") { $0.it("reports syntax error in filter tag") {
let template: Template = "{% filter unknown %}Text{% endfilter %}" template = "{% filter unknown %}Text{% endfilter %}"
let error = expectedFilterError(token: "filter unknown", template: template) try expectError(reason: "Unknown filter 'unknown'", token: "filter unknown")
try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error)
} }
$0.it("reports syntax error in variable tag") { $0.it("reports syntax error in variable tag") {
let template: Template = "{{ name|unknown }}" template = "{{ name|unknown }}"
let error = expectedFilterError(token: "name|unknown", template: template) try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown")
try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error)
} }
} }
$0.context("given rendering error") { $0.context("given rendering error") {
$0.it("reports rendering error in variable filter") {
let template: Template = "{{ name|throw }}"
var environment = environment $0.it("reports rendering error in variable filter") {
let filterExtension = Extension() let filterExtension = Extension()
filterExtension.registerFilter("throw") { (value: Any?) in filterExtension.registerFilter("throw") { (value: Any?) in
throw TemplateSyntaxError("Filter rendering error") throw TemplateSyntaxError("filter error")
} }
environment.extensions += [filterExtension] environment.extensions += [filterExtension]
let error = expectedSyntaxError(token: "name|throw", template: template, description: "Filter rendering error") template = Template(templateString: "{{ name|throw }}", environment: environment)
try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error) try expectError(reason: "filter error", token: "name|throw")
} }
$0.it("reports rendering error in filter tag") { $0.it("reports rendering error in filter tag") {
let template: Template = "{% filter throw %}Test{% endfilter %}"
var environment = environment
let filterExtension = Extension() let filterExtension = Extension()
filterExtension.registerFilter("throw") { (value: Any?) in filterExtension.registerFilter("throw") { (value: Any?) in
throw TemplateSyntaxError("Filter rendering error") throw TemplateSyntaxError("filter error")
} }
environment.extensions += [filterExtension] environment.extensions += [filterExtension]
let error = expectedSyntaxError(token: "filter throw", template: template, description: "Filter rendering error") template = Template(templateString: "{% filter throw %}Test{% endfilter %}", environment: environment)
try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error) try expectError(reason: "filter error", token: "filter throw")
} }
$0.it("reports rendering error in simple tag") { $0.it("reports rendering error in simple tag") {
let template: Template = "{% simpletag %}"
var environment = environment
let tagExtension = Extension() let tagExtension = Extension()
tagExtension.registerSimpleTag("simpletag") { context in tagExtension.registerSimpleTag("simpletag") { context in
throw TemplateSyntaxError("simpletag error") throw TemplateSyntaxError("simpletag error")
} }
environment.extensions += [tagExtension] environment.extensions += [tagExtension]
let error = expectedSyntaxError(token: "simpletag", template: template, description: "simpletag error") template = Template(templateString: "{% simpletag %}", environment: environment)
try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error) try expectError(reason: "simpletag error", token: "simpletag")
} }
$0.it("reporsts passing argument to simple filter") { $0.it("reporsts passing argument to simple filter") {
let template: Template = "{{ name|uppercase:5 }}" template = "{{ name|uppercase:5 }}"
try expectError(reason: "cannot invoke filter with an argument", token: "name|uppercase:5")
let error = expectedSyntaxError(token: "name|uppercase:5", template: template, description: "cannot invoke filter with an argument")
try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "kyle"])).toThrow(error)
} }
$0.it("reports rendering error in custom tag") { $0.it("reports rendering error in custom tag") {
let template: Template = "{% customtag %}"
var environment = environment
let tagExtension = Extension() let tagExtension = Extension()
tagExtension.registerTag("customtag") { parser, token in tagExtension.registerTag("customtag") { parser, token in
return ErrorNode(token: token) return ErrorNode(token: token)
} }
environment.extensions += [tagExtension] environment.extensions += [tagExtension]
let error = expectedSyntaxError(token: "customtag", template: template, description: "Custom Error") template = Template(templateString: "{% customtag %}", environment: environment)
try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error) try expectError(reason: "Custom Error", token: "customtag")
} }
$0.it("reports rendering error in for body") { $0.it("reports rendering error in for body") {
let template: Template = "{% for item in array %}{% customtag %}{% endfor %}"
var environment = environment
let tagExtension = Extension() let tagExtension = Extension()
tagExtension.registerTag("customtag") { parser, token in tagExtension.registerTag("customtag") { parser, token in
return ErrorNode(token: token) return ErrorNode(token: token)
} }
environment.extensions += [tagExtension] environment.extensions += [tagExtension]
let error = expectedSyntaxError(token: "customtag", template: template, description: "Custom Error") template = Template(templateString: "{% for name in names %}{% customtag %}{% endfor %}", environment: environment)
try expect(try environment.renderTemplate(string: template.templateString, context: ["array": ["a"]])).toThrow(error) try expectError(reason: "Custom Error", token: "customtag")
} }
$0.it("reports rendering error in block") { $0.it("reports rendering error in block") {
let template: Template = "{% block some %}{% customtag %}{% endblock %}"
var environment = environment
let tagExtension = Extension() let tagExtension = Extension()
tagExtension.registerTag("customtag") { parser, token in tagExtension.registerTag("customtag") { parser, token in
return ErrorNode(token: token) return ErrorNode(token: token)
} }
environment.extensions += [tagExtension] environment.extensions += [tagExtension]
let error = expectedSyntaxError(token: "customtag", template: template, description: "Custom Error") template = Template(templateString: "{% block some %}{% customtag %}{% endblock %}", environment: environment)
try expect(try environment.renderTemplate(string: template.templateString, context: ["array": ["a"]])).toThrow(error) try expectError(reason: "Custom Error", token: "customtag")
} }
} }
$0.context("given related templates") { $0.context("given included template") {
let path = Path(#file) + ".." + "fixtures" let path = Path(#file) + ".." + "fixtures"
let loader = FileSystemLoader(paths: [path]) let loader = FileSystemLoader(paths: [path])
let environment = Environment(loader: loader) var environment = Environment(loader: loader)
var template: Template!
var includedTemplate: Template!
$0.before {
environment = Environment(loader: loader)
template = nil
includedTemplate = nil
}
func expectError(reason: String, token: String, includedToken: String) throws {
var expectedError = expectedSyntaxError(token: token, template: template, description: reason)
expectedError.parentError = expectedSyntaxError(token: includedToken, template: includedTemplate, description: reason)
let error = try expect(environment.render(template: template, context: ["target": "World"]))
.toThrow(expectedError)
try expect(environment.errorReporter.renderError(error)) == environment.errorReporter.renderError(expectedError)
}
$0.it("reports syntax error in included template") { $0.it("reports syntax error in included template") {
let template: Template = "{% include \"invalid-include.html\" %}" template = Template(templateString: "{% include \"invalid-include.html\" %}", environment: environment)
let includedTemplate = try environment.loadTemplate(name: "invalid-include.html") includedTemplate = try environment.loadTemplate(name: "invalid-include.html")
let parentError = expectedSyntaxError(token: "target|unknown", template: includedTemplate, description: "Unknown filter 'unknown'") try expectError(reason: "Unknown filter 'unknown'",
var error = expectedSyntaxError(token: "include \"invalid-include.html\"", template: template, description: "Unknown filter 'unknown'") token: "include \"invalid-include.html\"",
error.parentError = parentError includedToken: "target|unknown")
try expect(environment.renderTemplate(string: template.templateString, context: ["target": "World"])).toThrow(error)
} }
$0.it("reports runtime error in included template") { $0.it("reports runtime error in included template") {
var environment = environment
let filterExtension = Extension() let filterExtension = Extension()
filterExtension.registerFilter("unknown", filter: { (_: Any?) in filterExtension.registerFilter("unknown", filter: { (_: Any?) in
throw TemplateSyntaxError("filter error") throw TemplateSyntaxError("filter error")
}) })
environment.extensions += [filterExtension] environment.extensions += [filterExtension]
let template: Template = "{% include \"invalid-include.html\" %}" template = Template(templateString: "{% include \"invalid-include.html\" %}", environment: environment)
let includedTemplate = try environment.loadTemplate(name: "invalid-include.html") includedTemplate = try environment.loadTemplate(name: "invalid-include.html")
let parentError = expectedSyntaxError(token: "target|unknown", template: includedTemplate, description: "filter error") try expectError(reason: "filter error",
var error = expectedSyntaxError(token: "include \"invalid-include.html\"", template: template, description: "filter error") token: "include \"invalid-include.html\"",
error.parentError = parentError includedToken: "target|unknown")
}
try expect(environment.renderTemplate(string: template.templateString, context: ["target": "World"])).toThrow(error) }
$0.context("given base and child templates") {
let path = Path(#file) + ".." + "fixtures"
let loader = FileSystemLoader(paths: [path])
var environment: Environment!
var childTemplate: Template!
var baseTemplate: Template!
$0.before {
environment = Environment(loader: loader)
childTemplate = nil
baseTemplate = nil
}
func expectError(reason: String, childToken: String, baseToken: String?) throws {
var expectedError = expectedSyntaxError(token: childToken, template: childTemplate, description: reason)
if let baseToken = baseToken {
expectedError.parentError = expectedSyntaxError(token: baseToken, template: baseTemplate, description: reason)
}
let error = try expect(environment.render(template: childTemplate, context: ["target": "World"]))
.toThrow(expectedError)
try expect(environment.errorReporter.renderError(error)) == environment.errorReporter.renderError(expectedError)
} }
$0.it("reports syntax error in base template") { $0.it("reports syntax error in base template") {
let template = try environment.loadTemplate(name: "invalid-child-super.html") childTemplate = try environment.loadTemplate(name: "invalid-child-super.html")
let baseTemplate = try environment.loadTemplate(name: "invalid-base.html") baseTemplate = try environment.loadTemplate(name: "invalid-base.html")
let parentError = expectedSyntaxError(token: "target|unknown", template: baseTemplate, description: "Unknown filter 'unknown'") try expectError(reason: "Unknown filter 'unknown'",
var error = expectedSyntaxError(token: "extends \"invalid-base.html\"", template: template, description: "Unknown filter 'unknown'") childToken: "extends \"invalid-base.html\"",
error.parentError = parentError baseToken: "target|unknown")
try expect(environment.render(template: template, context: ["target": "World"])).toThrow(error)
} }
$0.it("reports runtime error in base template") { $0.it("reports runtime error in base template") {
var environment = environment
let filterExtension = Extension() let filterExtension = Extension()
filterExtension.registerFilter("unknown", filter: { (_: Any?) in filterExtension.registerFilter("unknown", filter: { (_: Any?) in
throw TemplateSyntaxError("filter error") throw TemplateSyntaxError("filter error")
}) })
environment.extensions += [filterExtension] environment.extensions += [filterExtension]
let template = try environment.loadTemplate(name: "invalid-child-super.html") childTemplate = try environment.loadTemplate(name: "invalid-child-super.html")
let baseTemplate = try environment.loadTemplate(name: "invalid-base.html") baseTemplate = try environment.loadTemplate(name: "invalid-base.html")
let parentError = expectedSyntaxError(token: "target|unknown", template: baseTemplate, description: "filter error") try expectError(reason: "filter error",
var error = expectedSyntaxError(token: "block.super", template: template, description: "filter error") childToken: "block.super",
error.parentError = parentError baseToken: "target|unknown")
try expect(environment.render(template: template, context: ["target": "World"])).toThrow(error)
} }
$0.it("reports syntax error in child template") { $0.it("reports syntax error in child template") {
let template = Template.init(templateString: "{% extends \"base.html\" %}\n" + childTemplate = Template(templateString: "{% extends \"base.html\" %}\n" +
"{% block body %}Child {{ target|unknown }}{% endblock %}", environment: environment, name: nil) "{% block body %}Child {{ target|unknown }}{% endblock %}", environment: environment, name: nil)
let error = expectedSyntaxError(token: "target|unknown", template: template, description: "Unknown filter 'unknown'")
try expect(environment.render(template: template, context: ["target": "World"])).toThrow(error) try expectError(reason: "Unknown filter 'unknown'",
childToken: "target|unknown",
baseToken: nil)
} }
$0.it("reports runtime error in child template") { $0.it("reports runtime error in child template") {
var environment = environment
let filterExtension = Extension() let filterExtension = Extension()
filterExtension.registerFilter("unknown", filter: { (_: Any?) in filterExtension.registerFilter("unknown", filter: { (_: Any?) in
throw TemplateSyntaxError("filter error") throw TemplateSyntaxError("filter error")
}) })
environment.extensions += [filterExtension] environment.extensions += [filterExtension]
let template = Template.init(templateString: "{% extends \"base.html\" %}\n" + childTemplate = Template(templateString: "{% extends \"base.html\" %}\n" +
"{% block body %}Child {{ target|unknown }}{% endblock %}", environment: environment, name: nil) "{% block body %}Child {{ target|unknown }}{% endblock %}", environment: environment, name: nil)
let error = expectedSyntaxError(token: "target|unknown", template: template, description: "filter error")
try expect(environment.render(template: template, context: ["target": "World"])).toThrow(error) try expectError(reason: "filter error",
childToken: "target|unknown",
baseToken: nil)
} }
} }
@@ -290,6 +310,31 @@ func testEnvironment() {
} }
} }
private extension Expectation {
@discardableResult
func toThrow<T: Error & Equatable>(_ error: T) throws -> T {
var thrownError: Error? = nil
do {
_ = try expression()
} catch {
thrownError = error
}
if let thrownError = thrownError {
if let thrownError = thrownError as? T {
if error != thrownError {
throw failure("\(thrownError) is not \(error)")
}
return thrownError
} else {
throw failure("\(thrownError) is not \(error)")
}
} else {
throw failure("expression did not throw an error")
}
}
}
fileprivate class ExampleLoader: Loader { fileprivate class ExampleLoader: Loader {
func loadTemplate(name: String, environment: Environment) throws -> Template { func loadTemplate(name: String, environment: Environment) throws -> Template {