Skip to content

Commit

Permalink
Correctly report Rendering Errors within loops
Browse files Browse the repository at this point in the history
  • Loading branch information
edi9999 committed Jun 11, 2020
1 parent f797de0 commit 9e3e298
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 8 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,11 @@
### 3.17.7

When using docxtemplater in async mode, inside loops, rejections would be ignored.

With this version, if one or more tags turn into a rejected Promise,
`doc.resolveData(data)` will also reject (with a multi error containing all
suberrors)

### 3.17.6

Add support for dotx and dotm file formats
Expand Down
19 changes: 15 additions & 4 deletions es6/modules/loop.js
Expand Up @@ -281,13 +281,24 @@ class LoopModule {
})
);
}
const errorList = [];
return promisedValue.then(function (value) {
sm.loopOverValue(value, loopOver, part.inverted);
return Promise.all(promises).then(function (r) {
return r.map(function ({ resolved }) {
return resolved;
return Promise.all(promises)
.then(function (r) {
return r.map(function ({ resolved, errors }) {
if (errors.length > 0) {
errorList.push(...errors);
}
return resolved;
});
})
.then(function (value) {
if (errorList.length > 0) {
throw errorList;
}
return value;
});
});
});
}
}
Expand Down
6 changes: 5 additions & 1 deletion es6/resolve.js
Expand Up @@ -50,7 +50,11 @@ function resolve(options) {
return;
})
.catch(function (e) {
errors.push(e);
if (e.length > 1) {
errors.push(...e);
} else {
errors.push(e);
}
});
})
.filter((a) => {
Expand Down
72 changes: 72 additions & 0 deletions es6/tests/errors.js
Expand Up @@ -1286,6 +1286,7 @@ describe("Async errors", function () {
name: "ScopeParserError",
message: "Scope parser execution failed",
properties: {
file: "word/document.xml",
id: "scopeparser_execution_failed",
tag: "user",
scope: {
Expand All @@ -1308,6 +1309,72 @@ describe("Async errors", function () {
);
});

it("should show error when having async reject within loop", function () {
const content = "<w:t>{#users}{user}{/}</w:t>";
const expectedError = {
name: "TemplateError",
message: "Multi error",
properties: {
errors: [
{
name: "ScopeParserError",
message: "Scope parser execution failed",
properties: {
file: "word/document.xml",
id: "scopeparser_execution_failed",
scope: 1,
tag: "user",
rootError: { message: "foo 1" },
},
},
{
name: "ScopeParserError",
message: "Scope parser execution failed",
properties: {
file: "word/document.xml",
id: "scopeparser_execution_failed",
scope: 2,
tag: "user",
rootError: { message: "foo 2" },
},
},
{
name: "ScopeParserError",
message: "Scope parser execution failed",
properties: {
file: "word/document.xml",
id: "scopeparser_execution_failed",
scope: 3,
tag: "user",
rootError: { message: "foo 3" },
},
},
],
id: "multi_error",
},
};
let count = 0;
function errorParser(tag) {
return {
get() {
if (tag === "users") {
return [1, 2, 3];
}
count++;
throw new Error(`foo ${count}`);
},
};
}
const doc = createXmlTemplaterDocxNoRender(content, {
parser: errorParser,
});
doc.compile();
function create() {
return doc.resolveData({});
}
return expectToThrowAsync(create, Errors.XTTemplateError, expectedError);
});

it("should fail when customparser fails to execute on multiple tags", function () {
const content =
"<w:t>{#name|istrue}Name{/} {name|upper} {othername|upper}</w:t>";
Expand All @@ -1330,6 +1397,7 @@ describe("Async errors", function () {
message: "Scope parser execution failed",
properties: {
id: "scopeparser_execution_failed",
file: "word/document.xml",
scope: {},
tag: "name|istrue",
rootError: { message: "foo 1" },
Expand All @@ -1341,6 +1409,7 @@ describe("Async errors", function () {
message: "Scope parser execution failed",
properties: {
id: "scopeparser_execution_failed",
file: "word/document.xml",
scope: {},
tag: "name|upper",
rootError: { message: "foo 2" },
Expand All @@ -1352,6 +1421,7 @@ describe("Async errors", function () {
message: "Scope parser execution failed",
properties: {
id: "scopeparser_execution_failed",
file: "word/document.xml",
scope: {},
tag: "othername|upper",
rootError: { message: "foo 3" },
Expand Down Expand Up @@ -1398,6 +1468,7 @@ describe("Async errors", function () {
message: "Scope parser execution failed",
properties: {
id: "scopeparser_execution_failed",
file: "word/document.xml",
scope: {},
tag: "raw|isfalse",
rootError: { message: "foo 1" },
Expand All @@ -1409,6 +1480,7 @@ describe("Async errors", function () {
message: "Scope parser execution failed",
properties: {
id: "scopeparser_execution_failed",
file: "word/document.xml",
scope: {},
tag: "raw|istrue",
rootError: { message: "foo 2" },
Expand Down
6 changes: 3 additions & 3 deletions es6/tests/utils.js
Expand Up @@ -243,7 +243,7 @@ function cleanError(e, expectedError) {
const message = e.message;
e = omit(e, ["line", "sourceURL", "stack"]);
e.message = message;
if (expectedError.properties || e.properties) {
if (expectedError.properties && e.properties) {
if (expectedError.properties.offset != null) {
const o1 = e.properties.offset;
const o2 = expectedError.properties.offset;
Expand Down Expand Up @@ -361,8 +361,8 @@ function errorVerifier(e, type, expectedError) {
`Expected to have the same amount of e.properties.errors ${l1} !== ${l2} ` +
msg
);
e.properties.errors = e.properties.errors.map(function (e, i) {
const cleaned = cleanError(e, expectedError.properties.errors[i]);
e.properties.errors = e.properties.errors.map(function (suberror, i) {
const cleaned = cleanError(suberror, expectedError.properties.errors[i]);
const jsonified = jsonifyError(cleaned);
return jsonified;
});
Expand Down
7 changes: 7 additions & 0 deletions es6/xml-templater.js
Expand Up @@ -47,6 +47,13 @@ module.exports = class XmlTemplater {
options.scopeManager = createScope(options);
options.resolve = resolve;
return resolve(options).then(({ resolved, errors }) => {
errors.forEach((error) => {
// error properties might not be defined if some foreign
// (unhandled error not throw by docxtemplater willingly) is
// thrown.
error.properties = error.properties || {};
error.properties.file = this.filePath;
});
if (errors.length !== 0) {
throw errors;
}
Expand Down

0 comments on commit 9e3e298

Please sign in to comment.