UNPKG

docxtemplater

Version:

.docx generator working with templates and data (like Mustache)

306 lines (292 loc) 9.01 kB
"use strict"; var testUtils = require("./utils"); var expect = testUtils.expect; var _ = require("lodash"); var expressions = require("angular-expressions"); function angularParser(tag) { var expr = expressions.compile(tag); return { get: function get(scope) { return expr(scope); } }; } var Errors = require("../errors.js"); function expectToThrow(fn, type, expectedError) { var e = null; try { fn(); } catch (error) { e = error; } expect(e, "No error has been thrown").not.to.be.equal(null); var toShowOnFail = e.stack; expect(e, toShowOnFail).to.be.instanceOf(Error); expect(e, toShowOnFail).to.be.instanceOf(type); expect(e, toShowOnFail).to.be.an("object"); expect(e, toShowOnFail).to.have.property("properties"); expect(e.properties, toShowOnFail).to.be.an("object"); expect(e.properties, toShowOnFail).to.have.property("explanation"); expect(e.properties.explanation, toShowOnFail).to.be.a("string"); expect(e.properties, toShowOnFail).to.have.property("id"); expect(e.properties.id, toShowOnFail).to.be.a("string"); expect(e.properties.explanation, toShowOnFail).to.be.a("string"); delete e.properties.explanation; e = _.omit(e, ["line", "sourceURL", "stack"]); if (e.properties.rootError) { expect(e.properties.rootError.message).to.equal(expectedError.properties.rootError.message); delete e.properties.rootError; delete expectedError.properties.rootError; } if (e.properties.paragraphParts) { expect(e.properties.paragraphParts.length).to.equal(expectedError.properties.paragraphPartsLength); delete e.properties.paragraphParts; delete expectedError.properties.paragraphPartsLength; } if (e.stack) { expect(e.stack).to.contain("Error: " + expectedError.message); delete e.stack; } expect(JSON.parse(JSON.stringify(e))).to.be.deep.equal(expectedError); } describe("errors", function () { it("should be thrown when unclosedtag", function () { var content = "<w:t>{unclosedtag my text</w:t>"; var tags = {}; var expectedError = { name: "TemplateError", message: "Unclosed tag", properties: { context: "{unclosedtag my text", id: "unclosed_tag", xtag: "unclosedtag" } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content, { tags: tags }); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should not be possible to close {#users} with {/foo}", function () { var content = "<w:t>{#users}User {name}{/foo}</w:t>"; var tags = { users: [{ name: "John" }] }; var expectedError = { name: "TemplateError", message: "Closing tag does not match opening tag", properties: { id: "closing_tag_does_not_match_opening_tag", openingtag: "users", closingtag: "foo" } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content, { tags: tags }); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should be thrown when unopenedloop", function () { var content = "<w:t>{/loop} {foobar}</w:t>"; var scope = {}; var expectedError = { name: "TemplateError", message: "Unopened loop", properties: { id: "unopened_loop", xtag: "loop" } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content, { tags: scope }); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should be thrown when unclosedloop", function () { var content = "<w:t>{#loop} {foobar}</w:t>"; var scope = {}; var expectedError = { name: "TemplateError", message: "Unclosed loop", properties: { id: "unclosed_loop", xtag: "loop" } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content, { tags: scope }); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should fail when rawtag not in paragraph", function () { var content = "<w:t>{@myrawtag}</w:t>"; var scope = { myrawtag: "<w:p><w:t>foobar</w:t></w:p>" }; var expectedError = { name: "TemplateError", message: "Raw tag not in paragraph", properties: { expandTo: "w:p", id: "raw_tag_outerxml_invalid", index: 1, postparsed: [{ position: "start", text: true, type: "tag", value: "<w:t>" }, { module: "rawxml", type: "placeholder", value: "myrawtag" }, { position: "end", text: true, type: "tag", value: "</w:t>" }], xtag: "myrawtag", rootError: { message: "No tag 'w:p' was found at the right" } } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content, { tags: scope }); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should fail when rawtag not in paragraph (in table)", function () { var content = "<w:table><w:t>{@myrawtag}</w:t></w:p></w:table>"; var scope = { myrawtag: "<w:p><w:t>foobar</w:t></w:p>" }; var expectedError = { name: "TemplateError", message: "Raw tag not in paragraph", properties: { id: "raw_tag_outerxml_invalid", xtag: "myrawtag", postparsed: [{ type: "tag", position: "start", text: false, value: "<w:table>" }, { type: "tag", position: "start", text: true, value: "<w:t>" }, { type: "placeholder", value: "myrawtag", module: "rawxml" }, { type: "tag", position: "end", text: true, value: "</w:t>" }, { type: "tag", position: "end", text: false, value: "</w:p>" }, { type: "tag", position: "end", text: false, value: "</w:table>" }], rootError: { message: "No tag 'w:p' was found at the left" }, expandTo: "w:p", index: 2 } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content, { tags: scope }); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should fail when tag already opened", function () { var content = "<w:t>{user {name}</w:t>"; var expectedError = { name: "TemplateError", message: "Unclosed tag", properties: { id: "unclosed_tag", context: "{user ", xtag: "user" } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should fail when tag already closed", function () { var content = "<w:t>foobar}age</w:t>"; var expectedError = { name: "TemplateError", message: "Unopened tag", properties: { id: "unopened_tag", context: "foobar", xtag: "foobar" } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content); expectToThrow(create, Errors.XTTemplateError, expectedError); }); it("should fail when customparser fails to compile", function () { var content = "<w:t>{name++}</w:t>"; var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: { name: 3 }, parser: angularParser }); var expectedError = { name: "ScopeParserError", message: "Scope parser compilation failed", properties: { id: "scopeparser_compilation_failed", tag: "name++", rootError: { message: "Syntax Error: Token 'undefined' not a primary expression at column NaN of the expression [name++] starting at [name++]." } } }; var create = xmlTemplater.render.bind(xmlTemplater); expectToThrow(create, Errors.XTScopeParserError, expectedError); }); it("should fail when customparser fails to execute", function () { var content = "<w:t>{name|upper}</w:t>"; function errorParser() { return { get: function get() { throw new Error("foo bar"); } }; } var xmlTemplater = testUtils.createXmlTemplaterDocx(content, { tags: { name: 3 }, parser: errorParser }); var expectedError = { name: "ScopeParserError", message: "Scope parser execution failed", properties: { id: "scopeparser_execution_failed", tag: "name|upper", scope: { name: 3 }, rootError: { message: "foo bar" } } }; var create = xmlTemplater.render.bind(xmlTemplater); expectToThrow(create, Errors.XTScopeParserError, expectedError); }); it("should fail when rawtag is not only text in paragraph", function () { var content = "<w:p><w:t>{@myrawtag}</w:t><w:t>foobar</w:t></w:p>"; var scope = { myrawtag: "<w:p><w:t>foobar</w:t></w:p>" }; var expectedError = { name: "TemplateError", message: "Raw tag should be the only text in paragraph", properties: { id: "raw_xml_tag_should_be_only_text_in_paragraph", xtag: "myrawtag", paragraphPartsLength: 6 } }; var create = testUtils.createXmlTemplaterDocx.bind(null, content, { tags: scope }); expectToThrow(create, Errors.XTTemplateError, expectedError); }); describe("internal errors", function () { it("should fail", function () { var expectedError = { name: "InternalError", message: "Content must be a string", properties: { id: "xmltemplater_content_must_be_string" } }; function test() { testUtils.createXmlTemplaterDocx(1); } expectToThrow(test, Errors.XTInternalError, expectedError); }); }); });