Skip to content

Commit c1b548a

Browse files
authored
Merge pull request #73 from botandrose/hook-tests
Add tests to cover hooks, and fix extraneous hook call
2 parents 4d3ef0c + 350bda2 commit c1b548a

File tree

2 files changed

+181
-3
lines changed

2 files changed

+181
-3
lines changed

src/idiomorph.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,10 +439,10 @@ var Idiomorph = (function () {
439439
// iterate backwards to avoid skipping over items when a delete occurs
440440
for (let i = toAttributes.length - 1; 0 <= i; i--) {
441441
const toAttribute = toAttributes[i];
442-
if (ignoreAttribute(toAttribute.name, toEl, 'remove', ctx)) {
443-
continue;
444-
}
445442
if (!fromEl.hasAttribute(toAttribute.name)) {
443+
if (ignoreAttribute(toAttribute.name, toEl, 'remove', ctx)) {
444+
continue;
445+
}
446446
toEl.removeAttribute(toAttribute.name);
447447
}
448448
}

test/hooks.js

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
describe("lifecycle hooks", function(){
2+
beforeEach(function() {
3+
clearWorkArea();
4+
});
5+
6+
it('calls beforeNodeAdded before a new node is added to the DOM', function(){
7+
let calls = [];
8+
let initial = make("<ul><li>A</li></ul>");
9+
Idiomorph.morph(initial, "<ul><li>A</li><li>B</li></ul>", { callbacks: {
10+
beforeNodeAdded: node => {
11+
calls.push(node.outerHTML);
12+
}
13+
} });
14+
initial.outerHTML.should.equal("<ul><li>A</li><li>B</li></ul>");
15+
calls.should.eql(["<li>B</li>"]);
16+
});
17+
18+
it('returning false to beforeNodeAdded prevents adding the node', function(){
19+
let initial = make("<ul><li>A</li></ul>");
20+
Idiomorph.morph(initial, "<ul><li>A</li><li>B</li></ul>", { callbacks: {
21+
beforeNodeAdded: node => false,
22+
} });
23+
initial.outerHTML.should.equal("<ul><li>A</li></ul>");
24+
});
25+
26+
it('calls afterNodeAdded after a new node is added to the DOM', function(){
27+
let calls = [];
28+
let initial = make("<ul><li>A</li></ul>");
29+
Idiomorph.morph(initial, "<ul><li>A</li><li>B</li></ul>", { callbacks: {
30+
afterNodeAdded: node => {
31+
calls.push(node.outerHTML);
32+
}
33+
} });
34+
initial.outerHTML.should.equal("<ul><li>A</li><li>B</li></ul>");
35+
calls.should.eql(["<li>B</li>"]);
36+
});
37+
38+
it('calls beforeNodeMorphed before a node is morphed', function(){
39+
let calls = [];
40+
let initial = make(`<ul><li id="a">A</li></ul>`);
41+
Idiomorph.morph(initial, `<ul><li id="a">B</li></ul>`, { callbacks: {
42+
beforeNodeMorphed: (oldNode, newNode) => {
43+
calls.push([
44+
oldNode.outerHTML || oldNode.textContent,
45+
newNode.outerHTML || newNode.textContent,
46+
]);
47+
}
48+
} });
49+
initial.outerHTML.should.equal(`<ul><li id="a">B</li></ul>`);
50+
calls.should.eql([
51+
[`<ul><li id="a">A</li></ul>`, `<ul><li id="a">B</li></ul>`],
52+
[`<li id="a">A</li>`, `<li id="a">B</li>`],
53+
[`A`, `B`],
54+
]);
55+
});
56+
57+
it('returning false to beforeNodeMorphed prevents morphing the node', function(){
58+
let initial = make(`<ul name="a"><li name="a" id="a">A</li></ul>`);
59+
Idiomorph.morph(initial, `<ul name="b"><li name="b" id="a">B</li></ul>`, { callbacks: {
60+
beforeNodeMorphed: node => {
61+
if(node.nodeType === Node.TEXT_NODE) return false
62+
}
63+
} })
64+
initial.outerHTML.should.equal(`<ul name="b"><li name="b" id="a">A</li></ul>`);
65+
});
66+
67+
it('calls afterNodeMorphed before a node is morphed', function(){
68+
let calls = [];
69+
let initial = make(`<ul><li id="a">A</li></ul>`);
70+
Idiomorph.morph(initial, `<ul><li id="a">B</li></ul>`, { callbacks: {
71+
afterNodeMorphed: (oldNode, newNode) => {
72+
calls.push([
73+
oldNode.outerHTML || oldNode.textContent,
74+
newNode.outerHTML || newNode.textContent,
75+
]);
76+
}
77+
} });
78+
initial.outerHTML.should.equal(`<ul><li id="a">B</li></ul>`);
79+
calls.should.eql([
80+
[`B`, `B`],
81+
[`<li id="a">B</li>`, `<li id="a">B</li>`],
82+
[`<ul><li id="a">B</li></ul>`, `<ul><li id="a">B</li></ul>`],
83+
]);
84+
});
85+
86+
it('calls beforeNodeRemoved before a node is removed from the DOM', function(){
87+
let calls = [];
88+
let initial = make("<ul><li>A</li><li>B</li></ul>");
89+
Idiomorph.morph(initial, "<ul><li>A</li></ul>", { callbacks: {
90+
beforeNodeRemoved: node => {
91+
calls.push(node.outerHTML);
92+
}
93+
} });
94+
initial.outerHTML.should.equal("<ul><li>A</li></ul>");
95+
calls.should.eql(["<li>B</li>"]);
96+
});
97+
98+
it('returning false to beforeNodeRemoved prevents removing the node', function(){
99+
let initial = make("<ul><li>A</li><li>B</li></ul>");
100+
Idiomorph.morph(initial, "<ul><li>A</li></ul>", { callbacks: {
101+
beforeNodeRemoved: node => false,
102+
} });
103+
initial.outerHTML.should.equal("<ul><li>A</li><li>B</li></ul>");
104+
});
105+
106+
it('calls afterNodeRemoved after a node is removed from the DOM', function(){
107+
let calls = [];
108+
let initial = make("<ul><li>A</li><li>B</li></ul>");
109+
Idiomorph.morph(initial, "<ul><li>A</li></ul>", { callbacks: {
110+
afterNodeRemoved: node => {
111+
calls.push(node.outerHTML);
112+
}
113+
} });
114+
initial.outerHTML.should.equal("<ul><li>A</li></ul>");
115+
calls.should.eql(["<li>B</li>"]);
116+
});
117+
118+
it('calls beforeAttributeUpdated when an attribute is added', function(){
119+
let calls = [];
120+
let initial = make("<a></a>");
121+
Idiomorph.morph(initial, `<a href="#"></a>`, { callbacks: {
122+
beforeAttributeUpdated: (attributeName, node, mutationType) => {
123+
calls.push([attributeName, node.outerHTML, mutationType]);
124+
}
125+
} });
126+
initial.outerHTML.should.equal(`<a href="#"></a>`);
127+
calls.should.eql([["href", `<a></a>`, "update"]]);
128+
});
129+
130+
it('calls beforeAttributeUpdated when an attribute is updated', function(){
131+
let calls = [];
132+
let initial = make(`<a href="a"></a>`);
133+
Idiomorph.morph(initial, `<a href="b"></a>`, { callbacks: {
134+
beforeAttributeUpdated: (attributeName, node, mutationType) => {
135+
calls.push([attributeName, node.outerHTML, mutationType]);
136+
}
137+
} });
138+
initial.outerHTML.should.equal(`<a href="b"></a>`);
139+
calls.should.eql([["href", `<a href="a"></a>`, "update"]]);
140+
});
141+
142+
it('calls beforeAttributeUpdated when an attribute is removed', function(){
143+
let calls = [];
144+
let initial = make(`<a href="#"></a>`);
145+
Idiomorph.morph(initial, `<a></a>`, { callbacks: {
146+
beforeAttributeUpdated: (attributeName, node, mutationType) => {
147+
calls.push([attributeName, node.outerHTML, mutationType]);
148+
}
149+
} });
150+
initial.outerHTML.should.equal(`<a></a>`);
151+
calls.should.eql([["href", `<a href="#"></a>`, "remove"]]);
152+
});
153+
154+
it('returning false to beforeAttributeUpdated prevents the attribute addition', function(){
155+
let initial = make("<a></a>");
156+
Idiomorph.morph(initial, `<a href="#"></a>`, { callbacks: {
157+
beforeAttributeUpdated: () => false,
158+
} });
159+
initial.outerHTML.should.equal(`<a></a>`);
160+
});
161+
162+
it('returning false to beforeAttributeUpdated prevents the attribute update', function(){
163+
let initial = make(`<a href="a"></a>`);
164+
Idiomorph.morph(initial, `<a href="b"></a>`, { callbacks: {
165+
beforeAttributeUpdated: () => false,
166+
} });
167+
initial.outerHTML.should.equal(`<a href="a"></a>`);
168+
});
169+
170+
it('returning false to beforeAttributeUpdated prevents the attribute removal', function(){
171+
let initial = make(`<a href="#"></a>`);
172+
Idiomorph.morph(initial, `<a></a>`, { callbacks: {
173+
beforeAttributeUpdated: () => false,
174+
} });
175+
initial.outerHTML.should.equal(`<a href="#"></a>`);
176+
});
177+
});
178+

0 commit comments

Comments
 (0)