test("changing dynamic scope derived from another keyword from the outer scope", assert => { let template = compile("{{view.name}} {{#with-keywords view=view.innerView}}{{view.name}}{{/with-keywords}} {{view.name}}"); let innerView = { name: 'Yehuda' }; let view = { name: 'Godfrey', innerView }; let viewRef = new UpdatableReference(view); render(template, { innerView }, viewRef); equalTokens(root, 'Godfrey Yehuda Godfrey', "Initial render"); rerender(); equalTokens(root, 'Godfrey Yehuda Godfrey', "Noop rerender"); innerView.name = 'Tom'; rerender(); equalTokens(root, 'Godfrey Tom Godfrey', "Update with mutation"); view.name = 'Godhuda'; rerender(); equalTokens(root, 'Godhuda Tom Godhuda', "Update with mutation"); viewRef.update({ name: 'Godfrey', innerView: { name: 'Yehuda' } }); rerender(); equalTokens(root, 'Godfrey Yehuda Godfrey', "Reset with replacement"); });
test("helper calls follow the normal dirtying rules", function() { env.registerHelper('capitalize', function(params) { return params[0].toUpperCase(); }); let template = compile("<div>{{capitalize value}}</div>"); let object = { value: "hello" }; render(template, object); let textNode = result.firstNode().firstChild; equal(textNode.nodeValue, "HELLO"); object.value = "goodbye"; rerender(); equalTokens(root, '<div>GOODBYE</div>'); rerender(); equalTokens(root, '<div>GOODBYE</div>'); // Checks normalized value, not raw value object.value = "GoOdByE"; rerender(); textNode = root.firstChild.firstChild; equal(textNode.nodeValue, "GOODBYE"); });
test("HTML namespace is created in child templates", function() { let isTrue = true; let context = { isTrue }; let template = compile('{{#if isTrue}}<svg></svg>{{else}}<div><svg></svg></div>{{/if}}'); render(template, context); equalTokens(root, `<svg></svg>`); equal(root.firstChild.namespaceURI, SVG_NAMESPACE); rerender(); equalTokens(root, `<svg></svg>`); equal(root.firstChild.namespaceURI, SVG_NAMESPACE); context.isTrue = false; rerender(); equalTokens(root, `<div><svg></svg></div>`); equal(root.firstChild.namespaceURI, XHTML_NAMESPACE); equal(root.firstChild.firstChild.namespaceURI, SVG_NAMESPACE); rerender({isTrue}); equalTokens(root, `<svg></svg>`); equal(root.firstChild.namespaceURI, SVG_NAMESPACE); });
test("HTML namespace is continued to child templates", function() { let isTrue = true; let context = { isTrue }; let getDiv = () => root.firstChild; let getSvg = () => getDiv().firstChild; let template = compile('<div><svg>{{#if isTrue}}<circle />{{/if}}</svg></div>'); render(template, context); equalTokens(root, `<div><svg><circle /></svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getSvg().firstChild.namespaceURI, SVG_NAMESPACE); rerender(); equalTokens(root, `<div><svg><circle /></svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getSvg().firstChild.namespaceURI, SVG_NAMESPACE); context.isTrue = false; rerender(); equalTokens(root, `<div><svg><!----></svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); rerender({isTrue}); equalTokens(root, `<div><svg><circle /></svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getSvg().firstChild.namespaceURI, SVG_NAMESPACE); });
test("expression nested inside a namespace", function() { let content = 'Milly'; let context = { content }; let getDiv = () => root.firstChild; let getSvg = () => getDiv().firstChild; let template = compile('<div><svg>{{content}}</svg></div>'); render(template, context); equalTokens(root, `<div><svg>${content}</svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); rerender(); equalTokens(root, `<div><svg>${content}</svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); context.content = 'Moe'; rerender(); equalTokens(root, `<div><svg>${context.content}</svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); rerender({content}); equalTokens(root, `<div><svg>${content}</svg></div>`); equal(getDiv().namespaceURI, XHTML_NAMESPACE); equal(getSvg().namespaceURI, SVG_NAMESPACE); });
test("expression nested inside a namespaced root element", function() { let content = 'Maurice'; let context = { content }; let getSvg = () => root.firstChild as Element; let template = compile('<svg>{{content}}</svg>'); render(template, context); equalTokens(root, `<svg>${content}</svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); rerender(); equalTokens(root, `<svg>${content}</svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); context.content = null; rerender(); equal(getSvg().tagName, 'svg'); ok(getSvg().firstChild.textContent === ''); equal(getSvg().namespaceURI, SVG_NAMESPACE); rerender({content}); equalTokens(root, `<svg>${content}</svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); });
test("<svg> tag and expression as sibling", function() { let name = 'svg-title'; let context = { name }; let getSvg = () => root.firstChild; let template = compile('<svg></svg>{{name}}'); render(template, context); equalTokens(root, `<svg></svg>${name}`); equal(getSvg().namespaceURI, SVG_NAMESPACE); rerender(); equalTokens(root, `<svg></svg>${name}`); equal(getSvg().namespaceURI, SVG_NAMESPACE); context.name = null; rerender(); equalTokens(root, `<svg></svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); rerender({name}); equalTokens(root, `<svg></svg>${name}`); equal(getSvg().namespaceURI, SVG_NAMESPACE); });
test("non-standard namespaced attribute nodes w/ concat follow the normal dirtying rules", function() { let template = compile("<div epub:type='dedication {{type}}'>hello</div>"); let object = { type: "backmatter" }; render(template, object); equalTokens(root, "<div epub:type='dedication backmatter'>hello</div>", "Initial render"); rerender(); equalTokens(root, "<div epub:type='dedication backmatter'>hello</div>", "No-op rerender"); object.type = "index"; rerender(); equalTokens(root, "<div epub:type='dedication index'>hello</div>", "After update"); object.type = null; rerender(); equalTokens(root, "<div epub:type='dedication '>hello</div>", "After updating to null"); object.type = "backmatter"; rerender(); equalTokens(root, "<div epub:type='dedication backmatter'>hello</div>", "After reset"); });
test("elements nested inside <foreignObject> have an XHTML namespace", function() { let object = { hasDiv: true }; let getSvg = () => root.firstChild; let getForeignObject = () => getSvg().firstChild; let getDiv = () => getForeignObject().firstChild; let template = compile('<svg><foreignObject>{{#if hasDiv}}<div></div>{{/if}}</foreignObject></svg>'); render(template, object); equalTokens(root, "<svg><foreignObject><div></div></foreignObject></svg>"); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getForeignObject().namespaceURI, SVG_NAMESPACE); equal(getDiv().namespaceURI, XHTML_NAMESPACE); rerender(); equalTokens(root, "<svg><foreignObject><div></div></foreignObject></svg>"); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getForeignObject().namespaceURI, SVG_NAMESPACE); equal(getDiv().namespaceURI, XHTML_NAMESPACE); object.hasDiv = false; rerender(); equalTokens(root, "<svg><foreignObject><!----></foreignObject></svg>"); rerender({ hasDiv: true }); equalTokens(root, "<svg><foreignObject><div></div></foreignObject></svg>"); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getForeignObject().namespaceURI, SVG_NAMESPACE); equal(getDiv().namespaceURI, XHTML_NAMESPACE); });
test("Namespaced attribute with a quoted expression", function() { let title = 'svg-title'; let context = { title }; let getSvg = () => root.firstChild; let getXlinkAttr = () => getSvg().attributes[0]; let template = compile('<svg xlink:title="{{title}}">content</svg>'); render(template, context); equalTokens(root, `<svg xlink:title="${title}">content</svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getXlinkAttr().namespaceURI, XLINK_NAMESPACE); rerender(); equalTokens(root, `<svg xlink:title="${title}">content</svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getXlinkAttr().namespaceURI, XLINK_NAMESPACE); context.title = 'mmun'; rerender(); equalTokens(root, `<svg xlink:title="${context.title}">content</svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getXlinkAttr().namespaceURI, XLINK_NAMESPACE); rerender({ title }); equalTokens(root, `<svg xlink:title="${title}">content</svg>`); equal(getSvg().namespaceURI, SVG_NAMESPACE); equal(getXlinkAttr().namespaceURI, XLINK_NAMESPACE); });