From ed885f462a3865c28f167f138ce444cfe63c8cfe Mon Sep 17 00:00:00 2001 From: Ilya Puchka Date: Tue, 26 Dec 2017 20:48:43 +0100 Subject: [PATCH] refactored environment tests --- Tests/StencilTests/EnvironmentSpec.swift | 299 +++++++++++++---------- 1 file changed, 172 insertions(+), 127 deletions(-) diff --git a/Tests/StencilTests/EnvironmentSpec.swift b/Tests/StencilTests/EnvironmentSpec.swift index 0e20e76..24f2136 100644 --- a/Tests/StencilTests/EnvironmentSpec.swift +++ b/Tests/StencilTests/EnvironmentSpec.swift @@ -5,7 +5,13 @@ import PathKit func testEnvironment() { 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") { let template = try environment.loadTemplate(name: "example.html") @@ -33,256 +39,270 @@ func testEnvironment() { try expect(result) == "here" } - + func expectedSyntaxError(token: String, template: Template, description: String) -> TemplateSyntaxError { let token = Token.block(value: token, at: template.templateString.range(of: token)!) return TemplateSyntaxError(reason: description, token: token, template: template, parentError: nil) } - - $0.it("reports syntax error on invalid for tag syntax") { - let template: Template = "Hello {% for name in %}{{ name }}, {% endfor %}!" - 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) + + func expectError(reason: String, token: String) throws { + let expectedError = expectedSyntaxError(token: token, template: template, description: reason) + + 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") { - let template: Template = "{% for name in names %}{{ name }}" - let error = expectedSyntaxError(token: "for name in names", template: template, description: "`endfor` was not found.") - try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error) - } - - $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 syntax error") { + + $0.it("reports syntax error on invalid for tag syntax") { + 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.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") { - let template: Template = "{% for name in names|unknown %}{{ name }}{% endfor %}" - let error = expectedFilterError(token: "names|unknown", template: template) - try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error) + template = "{% for name in names|unknown %}{{ name }}{% endfor %}" + try expectError(reason: "Unknown filter 'unknown'", token: "names|unknown") } $0.it("reports syntax error in for-where tag") { - let template: Template = "{% for name in names where name|unknown %}{{ name }}{% endfor %}" - let error = expectedFilterError(token: "name|unknown", template: template) - try expect(try environment.renderTemplate(string: template.templateString, context: ["names": ["Bob", "Alice"]])).toThrow(error) + template = "{% for name in names where name|unknown %}{{ name }}{% endfor %}" + try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown") } $0.it("reports syntax error in if tag") { - let template: Template = "{% if name|unknown %}{{ name }}{% endif %}" - let error = expectedFilterError(token: "name|unknown", template: template) - try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error) + template = "{% if name|unknown %}{{ name }}{% endif %}" + try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown") } $0.it("reports syntax error in elif tag") { - let template: Template = "{% if name %}{{ name }}{% elif name|unknown %}{% endif %}" - let error = expectedFilterError(token: "name|unknown", template: template) - try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error) + template = "{% if name %}{{ name }}{% elif name|unknown %}{% endif %}" + try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown") } $0.it("reports syntax error in ifnot tag") { - let template: Template = "{% ifnot name|unknown %}{{ name }}{% endif %}" - let error = expectedFilterError(token: "name|unknown", template: template) - try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error) + template = "{% ifnot name|unknown %}{{ name }}{% endif %}" + try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown") } $0.it("reports syntax error in filter tag") { - let template: Template = "{% filter unknown %}Text{% endfilter %}" - let error = expectedFilterError(token: "filter unknown", template: template) - try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error) + template = "{% filter unknown %}Text{% endfilter %}" + try expectError(reason: "Unknown filter 'unknown'", token: "filter unknown") } $0.it("reports syntax error in variable tag") { - let template: Template = "{{ name|unknown }}" - let error = expectedFilterError(token: "name|unknown", template: template) - try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error) + template = "{{ name|unknown }}" + try expectError(reason: "Unknown filter 'unknown'", token: "name|unknown") } } $0.context("given rendering error") { + $0.it("reports rendering error in variable filter") { - let template: Template = "{{ name|throw }}" - - var environment = environment let filterExtension = Extension() filterExtension.registerFilter("throw") { (value: Any?) in - throw TemplateSyntaxError("Filter rendering error") + throw TemplateSyntaxError("filter error") } environment.extensions += [filterExtension] - - let error = expectedSyntaxError(token: "name|throw", template: template, description: "Filter rendering error") - try expect(try environment.renderTemplate(string: template.templateString, context: ["name": "Bob"])).toThrow(error) + + template = Template(templateString: "{{ name|throw }}", environment: environment) + try expectError(reason: "filter error", token: "name|throw") } $0.it("reports rendering error in filter tag") { - let template: Template = "{% filter throw %}Test{% endfilter %}" - - var environment = environment let filterExtension = Extension() filterExtension.registerFilter("throw") { (value: Any?) in - throw TemplateSyntaxError("Filter rendering error") + throw TemplateSyntaxError("filter error") } environment.extensions += [filterExtension] - - let error = expectedSyntaxError(token: "filter throw", template: template, description: "Filter rendering error") - try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error) + + template = Template(templateString: "{% filter throw %}Test{% endfilter %}", environment: environment) + try expectError(reason: "filter error", token: "filter throw") } $0.it("reports rendering error in simple tag") { - let template: Template = "{% simpletag %}" - - var environment = environment let tagExtension = Extension() tagExtension.registerSimpleTag("simpletag") { context in throw TemplateSyntaxError("simpletag error") } environment.extensions += [tagExtension] - - let error = expectedSyntaxError(token: "simpletag", template: template, description: "simpletag error") - try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error) + + template = Template(templateString: "{% simpletag %}", environment: environment) + try expectError(reason: "simpletag error", token: "simpletag") } $0.it("reporsts passing argument to simple filter") { - let template: Template = "{{ 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) + template = "{{ name|uppercase:5 }}" + try expectError(reason: "cannot invoke filter with an argument", token: "name|uppercase:5") } $0.it("reports rendering error in custom tag") { - let template: Template = "{% customtag %}" - - var environment = environment let tagExtension = Extension() tagExtension.registerTag("customtag") { parser, token in return ErrorNode(token: token) } environment.extensions += [tagExtension] - let error = expectedSyntaxError(token: "customtag", template: template, description: "Custom Error") - try expect(try environment.renderTemplate(string: template.templateString, context: [:])).toThrow(error) + template = Template(templateString: "{% customtag %}", environment: environment) + try expectError(reason: "Custom Error", token: "customtag") } $0.it("reports rendering error in for body") { - let template: Template = "{% for item in array %}{% customtag %}{% endfor %}" - - var environment = environment let tagExtension = Extension() tagExtension.registerTag("customtag") { parser, token in return ErrorNode(token: token) } environment.extensions += [tagExtension] - - let error = expectedSyntaxError(token: "customtag", template: template, description: "Custom Error") - try expect(try environment.renderTemplate(string: template.templateString, context: ["array": ["a"]])).toThrow(error) + + template = Template(templateString: "{% for name in names %}{% customtag %}{% endfor %}", environment: environment) + try expectError(reason: "Custom Error", token: "customtag") } $0.it("reports rendering error in block") { - let template: Template = "{% block some %}{% customtag %}{% endblock %}" - - var environment = environment let tagExtension = Extension() tagExtension.registerTag("customtag") { parser, token in return ErrorNode(token: token) } environment.extensions += [tagExtension] - - let error = expectedSyntaxError(token: "customtag", template: template, description: "Custom Error") - try expect(try environment.renderTemplate(string: template.templateString, context: ["array": ["a"]])).toThrow(error) + + template = Template(templateString: "{% block some %}{% customtag %}{% endblock %}", environment: environment) + try expectError(reason: "Custom Error", token: "customtag") } } - $0.context("given related templates") { + $0.context("given included template") { let path = Path(#file) + ".." + "fixtures" 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") { - let template: Template = "{% include \"invalid-include.html\" %}" - let includedTemplate = try environment.loadTemplate(name: "invalid-include.html") - - let parentError = expectedSyntaxError(token: "target|unknown", template: includedTemplate, description: "Unknown filter 'unknown'") - var error = expectedSyntaxError(token: "include \"invalid-include.html\"", template: template, description: "Unknown filter 'unknown'") - error.parentError = parentError - - try expect(environment.renderTemplate(string: template.templateString, context: ["target": "World"])).toThrow(error) + template = Template(templateString: "{% include \"invalid-include.html\" %}", environment: environment) + includedTemplate = try environment.loadTemplate(name: "invalid-include.html") + + try expectError(reason: "Unknown filter 'unknown'", + token: "include \"invalid-include.html\"", + includedToken: "target|unknown") } $0.it("reports runtime error in included template") { - var environment = environment let filterExtension = Extension() filterExtension.registerFilter("unknown", filter: { (_: Any?) in throw TemplateSyntaxError("filter error") }) environment.extensions += [filterExtension] - let template: Template = "{% include \"invalid-include.html\" %}" - let includedTemplate = try environment.loadTemplate(name: "invalid-include.html") + template = Template(templateString: "{% include \"invalid-include.html\" %}", environment: environment) + includedTemplate = try environment.loadTemplate(name: "invalid-include.html") + + try expectError(reason: "filter error", + token: "include \"invalid-include.html\"", + includedToken: "target|unknown") + } + + } + + $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 parentError = expectedSyntaxError(token: "target|unknown", template: includedTemplate, description: "filter error") - var error = expectedSyntaxError(token: "include \"invalid-include.html\"", template: template, description: "filter error") - error.parentError = parentError - - try expect(environment.renderTemplate(string: template.templateString, context: ["target": "World"])).toThrow(error) + 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") { - let template = try environment.loadTemplate(name: "invalid-child-super.html") - let baseTemplate = try environment.loadTemplate(name: "invalid-base.html") - - let parentError = expectedSyntaxError(token: "target|unknown", template: baseTemplate, description: "Unknown filter 'unknown'") - var error = expectedSyntaxError(token: "extends \"invalid-base.html\"", template: template, description: "Unknown filter 'unknown'") - error.parentError = parentError - - try expect(environment.render(template: template, context: ["target": "World"])).toThrow(error) + childTemplate = try environment.loadTemplate(name: "invalid-child-super.html") + baseTemplate = try environment.loadTemplate(name: "invalid-base.html") + + try expectError(reason: "Unknown filter 'unknown'", + childToken: "extends \"invalid-base.html\"", + baseToken: "target|unknown") } - + $0.it("reports runtime error in base template") { - var environment = environment let filterExtension = Extension() filterExtension.registerFilter("unknown", filter: { (_: Any?) in throw TemplateSyntaxError("filter error") }) environment.extensions += [filterExtension] - let template = try environment.loadTemplate(name: "invalid-child-super.html") - let baseTemplate = try environment.loadTemplate(name: "invalid-base.html") + childTemplate = try environment.loadTemplate(name: "invalid-child-super.html") + baseTemplate = try environment.loadTemplate(name: "invalid-base.html") - let parentError = expectedSyntaxError(token: "target|unknown", template: baseTemplate, description: "filter error") - var error = expectedSyntaxError(token: "block.super", template: template, description: "filter error") - error.parentError = parentError - - try expect(environment.render(template: template, context: ["target": "World"])).toThrow(error) + try expectError(reason: "filter error", + childToken: "block.super", + baseToken: "target|unknown") } $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) - 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") { - var environment = environment let filterExtension = Extension() filterExtension.registerFilter("unknown", filter: { (_: Any?) in throw TemplateSyntaxError("filter error") }) 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) - 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(_ 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 { func loadTemplate(name: String, environment: Environment) throws -> Template {