diff --git a/src/mutation-summary.js b/src/mutation-summary.js index c5eaea1..f1c786e 100644 --- a/src/mutation-summary.js +++ b/src/mutation-summary.js @@ -35,7 +35,7 @@ var NodeMap = (function () { this.values = []; } NodeMap.prototype.isIndex = function (s) { - return +s === s >>> 0; + return +s === +s >>> 0; }; NodeMap.prototype.nodeId = function (node) { @@ -301,7 +301,7 @@ var TreeChanges = (function (_super) { })(NodeMap); var MutationProjection = (function () { - // TOOD(any) + // TODO(any) function MutationProjection(rootNode, mutations, selectors, calcReordered, calcOldPreviousSibling) { this.rootNode = rootNode; this.mutations = mutations; @@ -847,8 +847,19 @@ function escapeQuotes(value) { return '"' + value.replace(/"/, '\\\"') + '"'; } +var Modifier; +(function (Modifier) { + Modifier[Modifier["none"] = 0] = "none"; + Modifier[Modifier["containsToken"] = 1] = "containsToken"; + Modifier[Modifier["startsWith"] = 2] = "startsWith"; + Modifier[Modifier["endsWith"] = 3] = "endsWith"; + Modifier[Modifier["containsAny"] = 4] = "containsAny"; + Modifier[Modifier["startsHyphen"] = 5] = "startsHyphen"; +})(Modifier || (Modifier = {})); + var Qualifier = (function () { function Qualifier() { + this.modifier = 0 /* none */; } Qualifier.prototype.matches = function (oldValue) { if (oldValue === null) @@ -857,9 +868,21 @@ var Qualifier = (function () { if (this.attrValue === undefined) return true; - if (!this.contains) + if (this.modifier == 0 /* none */) return this.attrValue == oldValue; + if (this.modifier == 2 /* startsWith */) + return this.attrValue == oldValue.slice(0, this.attrValue.length); + + if (this.modifier == 3 /* endsWith */) + return this.attrValue == oldValue.slice(-this.attrValue.length); + + if (this.modifier == 4 /* containsAny */) + return oldValue.indexOf(this.attrValue) != -1; + + if (this.modifier == 5 /* startsHyphen */) + return this.attrValue == oldValue || (this.attrValue + '-') == oldValue.slice(0, this.attrValue.length + 1); + var tokens = oldValue.split(' '); for (var i = 0; i < tokens.length; i++) { if (this.attrValue === tokens[i]) @@ -870,15 +893,27 @@ var Qualifier = (function () { }; Qualifier.prototype.toString = function () { - if (this.attrName === 'class' && this.contains) + if (this.attrName === 'class' && this.modifier == 1 /* containsToken */) return '.' + this.attrValue; - if (this.attrName === 'id' && !this.contains) + if (this.attrName === 'id' && this.modifier == 0 /* none */) return '#' + this.attrValue; - if (this.contains) + if (this.modifier == 1 /* containsToken */) return '[' + this.attrName + '~=' + escapeQuotes(this.attrValue) + ']'; + if (this.modifier == 2 /* startsWith */) + return '[' + this.attrName + '^=' + escapeQuotes(this.attrValue) + ']'; + + if (this.modifier == 3 /* endsWith */) + return '[' + this.attrName + '$=' + escapeQuotes(this.attrValue) + ']'; + + if (this.modifier == 4 /* containsAny */) + return '[' + this.attrName + '*=' + escapeQuotes(this.attrValue) + ']'; + + if (this.modifier == 5 /* startsHyphen */) + return '[' + this.attrName + '|=' + escapeQuotes(this.attrValue) + ']'; + if ('attrValue' in this) return '[' + this.attrName + '=' + escapeQuotes(this.attrValue) + ']'; @@ -1021,7 +1056,7 @@ var Selector = (function () { newQualifier(); currentSelector.tagName = '*'; currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = 1 /* containsToken */; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1056,7 +1091,7 @@ var Selector = (function () { if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = 1 /* containsToken */; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1089,7 +1124,7 @@ var Selector = (function () { if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = 1 /* containsToken */; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1136,7 +1171,7 @@ var Selector = (function () { if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = 1 /* containsToken */; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1187,7 +1222,31 @@ var Selector = (function () { } if (c == '~') { - currentQualifier.contains = true; + currentQualifier.modifier = 1 /* containsToken */; + state = EQUAL; + break; + } + + if (c == '^') { + currentQualifier.modifier = 2 /* startsWith */; + state = EQUAL; + break; + } + + if (c == '$') { + currentQualifier.modifier = 3 /* endsWith */; + state = EQUAL; + break; + } + + if (c == '*') { + currentQualifier.modifier = 4 /* containsAny */; + state = EQUAL; + break; + } + + if (c == '|') { + currentQualifier.modifier = 5 /* startsHyphen */; state = EQUAL; break; } @@ -1207,7 +1266,31 @@ var Selector = (function () { case EQUIV_OR_ATTR_QUAL_END: if (c == '~') { - currentQualifier.contains = true; + currentQualifier.modifier = 1 /* containsToken */; + state = EQUAL; + break; + } + + if (c == '^') { + currentQualifier.modifier = 2 /* startsWith */; + state = EQUAL; + break; + } + + if (c == '$') { + currentQualifier.modifier = 3 /* endsWith */; + state = EQUAL; + break; + } + + if (c == '*') { + currentQualifier.modifier = 4 /* containsAny */; + state = EQUAL; + break; + } + + if (c == '|') { + currentQualifier.modifier = 5 /* startsHyphen */; state = EQUAL; break; } diff --git a/src/mutation-summary.ts b/src/mutation-summary.ts index 56bfd63..d351056 100644 --- a/src/mutation-summary.ts +++ b/src/mutation-summary.ts @@ -46,7 +46,7 @@ class NodeMap { } private isIndex(s:string):boolean { - return +s === s >>> 0; + return +s === +s >>> 0; } private nodeId(node:Node) { @@ -335,7 +335,7 @@ class MutationProjection { private characterDataOnly:boolean; private matchCache:NumberMap>; - // TOOD(any) + // TODO(any) constructor(public rootNode:Node, public mutations:MutationRecord[], public selectors:Selector[], @@ -901,10 +901,12 @@ function escapeQuotes(value:string):string { return '"' + value.replace(/"/, '\\\"') + '"'; } +enum Modifier { none, containsToken, startsWith, endsWith, containsAny, startsHyphen } + class Qualifier { public attrName:string; public attrValue:string; - public contains:boolean; + public modifier:Modifier = Modifier.none; constructor() {} @@ -915,9 +917,21 @@ class Qualifier { if (this.attrValue === undefined) return true; - if (!this.contains) + if (this.modifier == Modifier.none) return this.attrValue == oldValue; + if (this.modifier == Modifier.startsWith) + return this.attrValue == oldValue.slice(0, this.attrValue.length); + + if (this.modifier == Modifier.endsWith) + return this.attrValue == oldValue.slice(-this.attrValue.length); + + if (this.modifier == Modifier.containsAny) + return oldValue.indexOf(this.attrValue) != -1; + + if (this.modifier == Modifier.startsHyphen) + return this.attrValue == oldValue || (this.attrValue + '-') == oldValue.slice(0, this.attrValue.length + 1); + var tokens = oldValue.split(' '); for (var i = 0; i < tokens.length; i++) { if (this.attrValue === tokens[i]) @@ -928,15 +942,27 @@ class Qualifier { } public toString():string { - if (this.attrName === 'class' && this.contains) + if (this.attrName === 'class' && this.modifier == Modifier.containsToken) return '.' + this.attrValue; - if (this.attrName === 'id' && !this.contains) + if (this.attrName === 'id' && this.modifier == Modifier.none) return '#' + this.attrValue; - if (this.contains) + if (this.modifier == Modifier.containsToken) return '[' + this.attrName + '~=' + escapeQuotes(this.attrValue) + ']'; + if (this.modifier == Modifier.startsWith) + return '[' + this.attrName + '^=' + escapeQuotes(this.attrValue) + ']'; + + if (this.modifier == Modifier.endsWith) + return '[' + this.attrName + '$=' + escapeQuotes(this.attrValue) + ']'; + + if (this.modifier == Modifier.containsAny) + return '[' + this.attrName + '*=' + escapeQuotes(this.attrValue) + ']'; + + if (this.modifier == Modifier.startsHyphen) + return '[' + this.attrName + '|=' + escapeQuotes(this.attrValue) + ']'; + if ('attrValue' in this) return '[' + this.attrName + '=' + escapeQuotes(this.attrValue) + ']'; @@ -1088,7 +1114,7 @@ class Selector { newQualifier(); currentSelector.tagName = '*'; currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = Modifier.containsToken; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1123,7 +1149,7 @@ class Selector { if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = Modifier.containsToken; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1156,7 +1182,7 @@ class Selector { if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = Modifier.containsToken; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1203,7 +1229,7 @@ class Selector { if (c == '.') { newQualifier(); currentQualifier.attrName = 'class'; - currentQualifier.contains = true; + currentQualifier.modifier = Modifier.containsToken; state = QUALIFIER_NAME_FIRST_CHAR; break; } @@ -1254,7 +1280,31 @@ class Selector { } if (c == '~') { - currentQualifier.contains = true; + currentQualifier.modifier = Modifier.containsToken; + state = EQUAL; + break; + } + + if (c == '^') { + currentQualifier.modifier = Modifier.startsWith; + state = EQUAL; + break; + } + + if (c == '$') { + currentQualifier.modifier = Modifier.endsWith; + state = EQUAL; + break; + } + + if (c == '*') { + currentQualifier.modifier = Modifier.containsAny; + state = EQUAL; + break; + } + + if (c == '|') { + currentQualifier.modifier = Modifier.startsHyphen; state = EQUAL; break; } @@ -1274,7 +1324,31 @@ class Selector { case EQUIV_OR_ATTR_QUAL_END: if (c == '~') { - currentQualifier.contains = true; + currentQualifier.modifier = Modifier.containsToken; + state = EQUAL; + break; + } + + if (c == '^') { + currentQualifier.modifier = Modifier.startsWith; + state = EQUAL; + break; + } + + if (c == '$') { + currentQualifier.modifier = Modifier.endsWith; + state = EQUAL; + break; + } + + if (c == '*') { + currentQualifier.modifier = Modifier.containsAny; + state = EQUAL; + break; + } + + if (c == '|') { + currentQualifier.modifier = Modifier.startsHyphen; state = EQUAL; break; } diff --git a/tests/setup.js b/tests/setup.js index ea4c4c5..4953428 100644 --- a/tests/setup.js +++ b/tests/setup.js @@ -13,9 +13,9 @@ // limitations under the License. function assertSelectorNames(selectors, expectSelectorStrings) { - assert.strictEqual(expectSelectorStrings.length, selectors.length); + assert.strictEqual(selectors.length, expectSelectorStrings.length); expectSelectorStrings.forEach(function(expectSelectorString, i) { - assert.strictEqual(expectSelectorString, selectors[i].selectorString); + assert.strictEqual(selectors[i].selectorString, expectSelectorString); }); } @@ -256,10 +256,6 @@ suite('Setup', function() { MutationSummary.parseElementFilter('div[foo=bar baz]'); }); - assert.throws(function() { - MutationSummary.parseElementFilter('div[foo|=bar]'); - }); - assertSelectorNames( MutationSummary.parseElementFilter('div[foo~=bar]'), ['div[foo~="bar"]'] @@ -278,6 +274,78 @@ suite('Setup', function() { MutationSummary.parseElementFilter('div[foo~ =bar]'); }); + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo^=bar]'), + ['div[foo^="bar"]'] + ); + + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo^="bar "]'), + ['div[foo^="bar "]'] + ); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo^=]'); + }); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo^ =bar]'); + }); + + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo$=bar]'), + ['div[foo$="bar"]'] + ); + + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo$="bar "]'), + ['div[foo$="bar "]'] + ); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo$=]'); + }); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo$ =bar]'); + }); + + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo*=bar]'), + ['div[foo*="bar"]'] + ); + + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo*="bar "]'), + ['div[foo*="bar "]'] + ); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo*=]'); + }); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo* =bar]'); + }); + + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo|=bar]'), + ['div[foo|="bar"]'] + ); + + assertSelectorNames( + MutationSummary.parseElementFilter('div[foo|="bar "]'), + ['div[foo|="bar "]'] + ); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo|=]'); + }); + + assert.throws(function() { + MutationSummary.parseElementFilter('div[foo| =bar]'); + }); + assertSelectorNames( MutationSummary.parseElementFilter('div[foo][bar]'), ['div[foo][bar]'] @@ -317,7 +385,7 @@ suite('Setup', function() { // queries is required. assert.throws(function() { new MutationSummary({ - callback: function() {}, + callback: function() {} }); }); @@ -434,7 +502,7 @@ suite('Setup', function() { assert.throws(function() { new MutationSummary({ callback: function() {}, - queries: [{ element: 'div[noTrailingBracket', }] + queries: [{ element: 'div[noTrailingBracket' }] }); }); diff --git a/tests/test-validator.js b/tests/test-validator.js index 9ade2b7..95743ad 100644 --- a/tests/test-validator.js +++ b/tests/test-validator.js @@ -37,7 +37,7 @@ MutationSummary.createQueryValidator = function(root, query) { function allValidator(summary, stayed, old, current) { summary.reordered.forEach(function(node) { var oldPreviousSiblingMap = old.get(summary.getOldParentNode(node)); - assert.strictEqual(oldPreviousSiblingMap.get(node), summary.getOldPreviousSibling(node)); + assert.strictEqual(summary.getOldPreviousSibling(node), oldPreviousSiblingMap.get(node)); }); } @@ -61,7 +61,7 @@ MutationSummary.createQueryValidator = function(root, query) { compareNodeArrayIgnoreOrder(changed, summary.valueChanged); changed.forEach(function(node) { - assert.strictEqual(old.get(node), summary.getOldCharacterData(node)); + assert.strictEqual(summary.getOldCharacterData(node), old.get(node)); }); } @@ -85,7 +85,7 @@ MutationSummary.createQueryValidator = function(root, query) { compareNodeArrayIgnoreOrder(changed, summary.valueChanged); changed.forEach(function(node) { - assert.strictEqual(old.get(node), summary.getOldAttribute(node, query.attribute)); + assert.strictEqual(summary.getOldAttribute(node, query.attribute), old.get(node)); }); } @@ -160,7 +160,7 @@ MutationSummary.createQueryValidator = function(root, query) { }); function checkOldParentNode(node) { - assert.strictEqual(old.get(node).parentNode, summary.getOldParentNode(node)); + assert.strictEqual(summary.getOldParentNode(node), old.get(node).parentNode); } summary.removed.forEach(checkOldParentNode); diff --git a/tests/test.js b/tests/test.js index 61acdbf..c2a2051 100644 --- a/tests/test.js +++ b/tests/test.js @@ -3,7 +3,7 @@ /// function compareNodeArrayIgnoreOrder(expected, actual) { - assert.strictEqual(expected.length, actual.length); + assert.strictEqual(actual.length, expected.length); var map = new MutationSummary.NodeMap(); expected.forEach(function (node) { @@ -77,7 +77,7 @@ suite('Mutation Summary', function () { if (options.oldPreviousSibling) { expect.removed.forEach(function (node, index) { - assert.strictEqual(expect.removedOldPreviousSibling[index], changed.getOldPreviousSibling(node)); + assert.strictEqual(changed.getOldPreviousSibling(node), expect.removedOldPreviousSibling[index]); }); } @@ -88,7 +88,7 @@ suite('Mutation Summary', function () { if (options.oldPreviousSibling) { expect.reparented.forEach(function (node, index) { - assert.strictEqual(expect.reparentedOldPreviousSibling[index], changed.getOldPreviousSibling(node)); + assert.strictEqual(changed.getOldPreviousSibling(node), expect.reparentedOldPreviousSibling[index]); }); } } else { @@ -101,7 +101,7 @@ suite('Mutation Summary', function () { compareNodeArrayIgnoreOrder(expect.reordered, changed.reordered); expect.reordered.forEach(function (node, index) { - assert.strictEqual(expect.reorderedOldPreviousSibling[index], changed.getOldPreviousSibling(node)); + assert.strictEqual(changed.getOldPreviousSibling(node), expect.reorderedOldPreviousSibling[index]); }); } else { assert.isUndefined(changed.reordered); @@ -114,7 +114,7 @@ suite('Mutation Summary', function () { var getOldFunction = query.attribute ? 'getOldAttribute' : 'getOldCharacterData'; expect.valueChanged.forEach(function (node, index) { - assert.strictEqual(expect.oldValues[index], changed[getOldFunction](node, query.attribute)); + assert.strictEqual(changed[getOldFunction](node, query.attribute), expect.oldValues[index]); }); } else { assert.isUndefined(changed.valueChanged); @@ -123,12 +123,12 @@ suite('Mutation Summary', function () { // attributeChanged if (query.all || query.elementAttributes) { assert(typeof expect.attributeChanged == typeof changed.attributeChanged); - assert.strictEqual(Object.keys(expect.attributeChanged).length, Object.keys(changed.attributeChanged).length); + assert.strictEqual(Object.keys(changed.attributeChanged).length, Object.keys(expect.attributeChanged).length); Object.keys(expect.attributeChanged).forEach(function (attrName) { compareNodeArrayIgnoreOrder(expect.attributeChanged[attrName], changed.attributeChanged[attrName]); expect.attributeOldValue[attrName].forEach(function (attrOldValue, index) { - assert.strictEqual(expect.attributeOldValue[attrName][index], changed.getOldAttribute(expect.attributeChanged[attrName][index], attrName)); + assert.strictEqual(changed.getOldAttribute(expect.attributeChanged[attrName][index], attrName), expect.attributeOldValue[attrName][index]); }); }); } else { @@ -354,7 +354,7 @@ suite('Mutation Summary', function () { test('Element Attribute Specified', function () { startObserving({ - element: 'div[foo], A, *[bar], div[ baz = "bat"], span#foo[blow~=blarg]' + element: 'div[foo], A, *[bar], div[ baz = "bat"], span#foo[blow~=blarg], span[some^=thing], span[another$=.html], ' + 'span[splat*=atat], div[lang|=en]' }); var div = document.createElement('div'); @@ -372,6 +372,18 @@ suite('Mutation Summary', function () { var p = document.createElement('P'); testDiv.appendChild(p); p.setAttribute('baz', 'baz'); + var span2 = document.createElement('span'); + span2.setAttribute('some', 'not a thing'); + div2.appendChild(span2); + var span3 = document.createElement('span'); + span3.setAttribute('another', '.html at the front'); + div3.appendChild(span3); + var span4 = document.createElement('span'); + span4.setAttribute('splat', 'no at at'); + p.appendChild(span4); + var div4 = document.createElement('div'); + testDiv.appendChild(div4); + div4.setAttribute('lang', 'not-en-matching'); assertSummary({ added: [div] }); @@ -382,13 +394,18 @@ suite('Mutation Summary', function () { div3.setAttribute('baz', 'bat'); span.id = 'foo'; span.setAttribute('blow', 'blarg bloog'); + span2.setAttribute('some', 'thinggood'); + span3.setAttribute('another', 'this one ends in.html'); + span4.setAttribute('splat', 'some-atat-thing'); + div4.setAttribute('lang', 'en-yes'); assertSummary({ - added: [p, div3, span], + added: [p, div3, span, span2, span3, span4, div4], removed: [div] }); div3.removeAttribute('baz'); div3.setAttribute('baz', 'bat'); + div4.setAttribute('lang', 'en'); assertNothingReported(); }); @@ -1002,14 +1019,14 @@ suite('Mutation Summary', function () { count++; if (count == 1) { - assert.strictEqual(1, summary.added.length); + assert.strictEqual(summary.added.length, 1); div = testDiv.appendChild(document.createElement('div')); } else if (count == 2) { - assert.strictEqual(2, summary.added.length); + assert.strictEqual(summary.added.length, 2); div = testDiv.appendChild(document.createElement('div')); summary1.disconnect(); } else if (count == 3) { - assert.strictEqual(1, summary.added.length); + assert.strictEqual(summary.added.length, 1); summary1.disconnect(); async(); } @@ -1024,14 +1041,14 @@ suite('Mutation Summary', function () { count++; if (count == 1) { - assert.strictEqual(1, summary.added.length); + assert.strictEqual(summary.added.length, 1); div = testDiv.appendChild(document.createElement('div')); } else if (count == 2) { - assert.strictEqual(2, summary.added.length); + assert.strictEqual(summary.added.length, 2); div = testDiv.appendChild(document.createElement('div')); summary2.disconnect(); } else if (count == 3) { - assert.strictEqual(1, summary.added.length); + assert.strictEqual(summary.added.length, 1); summary2.disconnect(); async(); } @@ -1057,7 +1074,7 @@ suite('Mutation Summary', function () { setTimeout(function () { div.setAttribute('bar', 'baz'); setTimeout(function () { - assert.strictEqual(1, callbackCount); + assert.strictEqual(callbackCount, 1); async(); }); }, 0); @@ -1148,21 +1165,21 @@ suite('TreeMirror Fuzzer', function () { } function assertTreesEqual(node, copy) { - assert.strictEqual(node.tagName, copy.tagName); - assert.strictEqual(node.id, copy.id); + assert.strictEqual(copy.tagName, node.tagName); + assert.strictEqual(copy.id, node.id); - assert.strictEqual(node.nodeType, copy.nodeType); + assert.strictEqual(copy.nodeType, node.nodeType); if (node.nodeType == Node.ELEMENT_NODE) { - assert.strictEqual(node.attributes.length, copy.attributes.length); + assert.strictEqual(copy.attributes.length, node.attributes.length); for (var i = 0; i < node.attributes.length; i++) { var attr = node.attributes[i]; - assert.strictEqual(attr.value, copy.getAttribute(attr.name)); + assert.strictEqual(copy.getAttribute(attr.name), attr.value); } } else { - assert.strictEqual(node.textContent, copy.textContent); + assert.strictEqual(copy.textContent, node.textContent); } - assert.strictEqual(node.childNodes.length, copy.childNodes.length); + assert.strictEqual(copy.childNodes.length, node.childNodes.length); var copyChild = copy.firstChild; for (var child = node.firstChild; child; child = child.nextSibling) { diff --git a/tests/test.ts b/tests/test.ts index e4b6596..18d8ccc 100644 --- a/tests/test.ts +++ b/tests/test.ts @@ -8,7 +8,7 @@ declare var setup:(a:any)=>any; declare var teardown:(a:any)=>any; function compareNodeArrayIgnoreOrder(expected:Node[], actual:Node[]) { - assert.strictEqual(expected.length, actual.length); + assert.strictEqual(actual.length, expected.length); var map = new MutationSummary.NodeMap(); expected.forEach(function(node) { @@ -83,7 +83,7 @@ suite('Mutation Summary', function() { if (options.oldPreviousSibling) { expect.removed.forEach(function(node:Node, index:number) { - assert.strictEqual(expect.removedOldPreviousSibling[index], changed.getOldPreviousSibling(node)); + assert.strictEqual(changed.getOldPreviousSibling(node), expect.removedOldPreviousSibling[index]); }); } @@ -94,7 +94,7 @@ suite('Mutation Summary', function() { if (options.oldPreviousSibling) { expect.reparented.forEach(function(node:Node, index:number) { - assert.strictEqual(expect.reparentedOldPreviousSibling[index], changed.getOldPreviousSibling(node)); + assert.strictEqual(changed.getOldPreviousSibling(node), expect.reparentedOldPreviousSibling[index]); }); } } else { @@ -107,7 +107,7 @@ suite('Mutation Summary', function() { compareNodeArrayIgnoreOrder(expect.reordered, changed.reordered); expect.reordered.forEach(function(node:Node, index:number) { - assert.strictEqual(expect.reorderedOldPreviousSibling[index], changed.getOldPreviousSibling(node)); + assert.strictEqual(changed.getOldPreviousSibling(node), expect.reorderedOldPreviousSibling[index]); }); } else { assert.isUndefined(changed.reordered); @@ -120,7 +120,7 @@ suite('Mutation Summary', function() { var getOldFunction = query.attribute ? 'getOldAttribute' : 'getOldCharacterData'; expect.valueChanged.forEach(function(node:Node, index:number) { - assert.strictEqual(expect.oldValues[index], changed[getOldFunction](node, query.attribute)); + assert.strictEqual(changed[getOldFunction](node, query.attribute), expect.oldValues[index]); }); } else { assert.isUndefined(changed.valueChanged); @@ -129,12 +129,12 @@ suite('Mutation Summary', function() { // attributeChanged if (query.all || query.elementAttributes) { assert(typeof expect.attributeChanged == typeof changed.attributeChanged); - assert.strictEqual(Object.keys(expect.attributeChanged).length, Object.keys(changed.attributeChanged).length); + assert.strictEqual(Object.keys(changed.attributeChanged).length, Object.keys(expect.attributeChanged).length); Object.keys(expect.attributeChanged).forEach(function(attrName) { compareNodeArrayIgnoreOrder(expect.attributeChanged[attrName], changed.attributeChanged[attrName]); expect.attributeOldValue[attrName].forEach(function(attrOldValue:string, index:number) { - assert.strictEqual(expect.attributeOldValue[attrName][index], changed.getOldAttribute(expect.attributeChanged[attrName][index], attrName)); + assert.strictEqual(changed.getOldAttribute(expect.attributeChanged[attrName][index], attrName), expect.attributeOldValue[attrName][index]); }); }); } else { @@ -359,7 +359,8 @@ suite('Mutation Summary', function() { test('Element Attribute Specified', function() { startObserving({ - element: 'div[foo], A, *[bar], div[ baz = "bat"], span#foo[blow~=blarg]' + element: 'div[foo], A, *[bar], div[ baz = "bat"], span#foo[blow~=blarg], span[some^=thing], span[another$=.html], ' + + 'span[splat*=atat], div[lang|=en]' }); var div = document.createElement('div'); @@ -377,6 +378,18 @@ suite('Mutation Summary', function() { var p = document.createElement('P'); testDiv.appendChild(p); p.setAttribute('baz', 'baz'); + var span2 = document.createElement('span'); + span2.setAttribute('some', 'not a thing'); + div2.appendChild(span2); + var span3 = document.createElement('span'); + span3.setAttribute('another', '.html at the front'); + div3.appendChild(span3); + var span4 = document.createElement('span'); + span4.setAttribute('splat', 'no at at'); + p.appendChild(span4); + var div4 = document.createElement('div'); + testDiv.appendChild(div4); + div4.setAttribute('lang', 'not-en-matching'); assertSummary({ added: [div] }); @@ -387,13 +400,18 @@ suite('Mutation Summary', function() { div3.setAttribute('baz', 'bat'); span.id = 'foo'; span.setAttribute('blow', 'blarg bloog'); + span2.setAttribute('some', 'thinggood'); + span3.setAttribute('another', 'this one ends in.html'); + span4.setAttribute('splat', 'some-atat-thing'); + div4.setAttribute('lang', 'en-yes'); assertSummary({ - added: [p, div3, span], + added: [p, div3, span, span2, span3, span4, div4], removed: [div] }); div3.removeAttribute('baz'); div3.setAttribute('baz', 'bat'); + div4.setAttribute('lang', 'en'); assertNothingReported(); }); @@ -1005,14 +1023,14 @@ suite('Mutation Summary', function() { count++; if (count == 1) { - assert.strictEqual(1, summary.added.length) + assert.strictEqual(summary.added.length, 1) div = testDiv.appendChild(document.createElement('div')); } else if (count == 2) { - assert.strictEqual(2, summary.added.length); + assert.strictEqual(summary.added.length, 2); div = testDiv.appendChild(document.createElement('div')); summary1.disconnect(); } else if (count == 3) { - assert.strictEqual(1, summary.added.length); + assert.strictEqual(summary.added.length, 1); summary1.disconnect(); async(); } @@ -1027,14 +1045,14 @@ suite('Mutation Summary', function() { count++; if (count == 1) { - assert.strictEqual(1, summary.added.length) + assert.strictEqual(summary.added.length, 1) div = testDiv.appendChild(document.createElement('div')); } else if (count == 2) { - assert.strictEqual(2, summary.added.length); + assert.strictEqual(summary.added.length, 2); div = testDiv.appendChild(document.createElement('div')); summary2.disconnect(); } else if (count == 3) { - assert.strictEqual(1, summary.added.length); + assert.strictEqual(summary.added.length, 1); summary2.disconnect(); async(); } @@ -1061,7 +1079,7 @@ suite('Mutation Summary', function() { setTimeout(function() { div.setAttribute('bar', 'baz'); setTimeout(function() { - assert.strictEqual(1, callbackCount); + assert.strictEqual(callbackCount, 1); async(); }); }, 0); @@ -1155,21 +1173,21 @@ suite('TreeMirror Fuzzer', function() { } function assertTreesEqual(node:Node, copy:Node) { - assert.strictEqual(node.tagName, copy.tagName); - assert.strictEqual(node.id, copy.id); + assert.strictEqual(copy.tagName, node.tagName); + assert.strictEqual(copy.id, node.id); - assert.strictEqual(node.nodeType, copy.nodeType); + assert.strictEqual(copy.nodeType, node.nodeType); if (node.nodeType == Node.ELEMENT_NODE) { - assert.strictEqual(node.attributes.length, copy.attributes.length); + assert.strictEqual(copy.attributes.length, node.attributes.length); for (var i = 0; i < node.attributes.length; i++) { var attr = node.attributes[i]; - assert.strictEqual(attr.value, (copy).getAttribute(attr.name)); + assert.strictEqual((copy).getAttribute(attr.name), attr.value); } } else { - assert.strictEqual(node.textContent, copy.textContent); + assert.strictEqual(copy.textContent, node.textContent); } - assert.strictEqual(node.childNodes.length, copy.childNodes.length); + assert.strictEqual(copy.childNodes.length, node.childNodes.length); var copyChild = copy.firstChild; for (var child = node.firstChild; child; child = child.nextSibling) {