summaryrefslogtreecommitdiff
path: root/addons/website/static/lib/MutationObservers/test
diff options
context:
space:
mode:
Diffstat (limited to 'addons/website/static/lib/MutationObservers/test')
-rw-r--r--addons/website/static/lib/MutationObservers/test/attributes.js276
-rw-r--r--addons/website/static/lib/MutationObservers/test/callback.js72
-rw-r--r--addons/website/static/lib/MutationObservers/test/characterData.js106
-rw-r--r--addons/website/static/lib/MutationObservers/test/childList.js377
-rw-r--r--addons/website/static/lib/MutationObservers/test/index.html81
-rw-r--r--addons/website/static/lib/MutationObservers/test/mixed.js36
-rw-r--r--addons/website/static/lib/MutationObservers/test/sidetable.js35
-rw-r--r--addons/website/static/lib/MutationObservers/test/transient.js283
8 files changed, 1266 insertions, 0 deletions
diff --git a/addons/website/static/lib/MutationObservers/test/attributes.js b/addons/website/static/lib/MutationObservers/test/attributes.js
new file mode 100644
index 00000000000..73d697beede
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/attributes.js
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+suite('JsMutationObserver attributes', function() {
+
+ test('attr', function() {
+ var div = document.createElement('div');
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true
+ });
+ div.setAttribute('a', 'A');
+ div.setAttribute('a', 'B');
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+ expectRecord(records[1], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+ });
+
+ test('attr with oldValue', function() {
+ var div = document.createElement('div');
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true,
+ attributeOldValue: true
+ });
+ div.setAttribute('a', 'A');
+ div.setAttribute('a', 'B');
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null,
+ oldValue: null
+ });
+ expectRecord(records[1], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null,
+ oldValue: 'A'
+ });
+ });
+
+ test('attr change in subtree should not genereate a record', function() {
+ var div = document.createElement('div');
+ var child = div.appendChild(document.createElement('div'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true
+ });
+ child.setAttribute('a', 'A');
+ child.setAttribute('a', 'B');
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 0);
+ });
+
+ test('attr change, subtree', function() {
+ var div = document.createElement('div');
+ var child = div.appendChild(document.createElement('div'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true,
+ subtree: true
+ });
+ child.setAttribute('a', 'A');
+ child.setAttribute('a', 'B');
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'a'
+ });
+ expectRecord(records[1], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'a'
+ });
+ });
+
+
+ test('multiple observers on same target', function() {
+ var div = document.createElement('div');
+ var observer1 = new JsMutationObserver(function() {});
+ observer1.observe(div, {
+ attributes: true,
+ attributeOldValue: true
+ });
+ var observer2 = new JsMutationObserver(function() {});
+ observer2.observe(div, {
+ attributes: true,
+ attributeFilter: ['b']
+ });
+
+ div.setAttribute('a', 'A');
+ div.setAttribute('a', 'A2');
+ div.setAttribute('b', 'B');
+
+ var records = observer1.takeRecords();
+ assert.strictEqual(records.length, 3);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a'
+ });
+ expectRecord(records[1], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ oldValue: 'A'
+ });
+ expectRecord(records[2], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'b'
+ });
+
+ records = observer2.takeRecords();
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'b'
+ });
+ });
+
+ test('observer observes on different target', function() {
+ var div = document.createElement('div');
+ var child = div.appendChild(document.createElement('div'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(child, {
+ attributes: true
+ });
+ observer.observe(div, {
+ attributes: true,
+ subtree: true,
+ attributeOldValue: true
+ });
+
+ child.setAttribute('a', 'A');
+ child.setAttribute('a', 'A2');
+ child.setAttribute('b', 'B');
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 3);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'a'
+ });
+ expectRecord(records[1], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'a',
+ oldValue: 'A'
+ });
+ expectRecord(records[2], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'b'
+ });
+ });
+
+ test('observing on the same node should update the options', function() {
+ var div = document.createElement('div');
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true,
+ attributeFilter: ['a']
+ });
+ observer.observe(div, {
+ attributes: true,
+ attributeFilter: ['b']
+ });
+
+ div.setAttribute('a', 'A');
+ div.setAttribute('b', 'B');
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'b'
+ });
+ });
+
+ test('disconnect should stop all events and empty the records', function() {
+ var div = document.createElement('div');
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true,
+ });
+
+ div.setAttribute('a', 'A');
+
+ observer.disconnect();
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 0);
+
+ div.setAttribute('b', 'B');
+
+ records = observer.takeRecords();
+ assert.strictEqual(records.length, 0);
+ });
+
+ test('disconnect should not affect other observers', function() {
+ var div = document.createElement('div');
+ var observer1 = new JsMutationObserver(function() {});
+ observer1.observe(div, {
+ attributes: true,
+ });
+ var observer2 = new JsMutationObserver(function() {});
+ observer2.observe(div, {
+ attributes: true,
+ });
+
+ div.setAttribute('a', 'A');
+
+ observer1.disconnect();
+ var records1 = observer1.takeRecords();
+ assert.strictEqual(records1.length, 0);
+
+ var records2 = observer2.takeRecords();
+ assert.strictEqual(records2.length, 1);
+ expectRecord(records2[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a'
+ });
+
+ div.setAttribute('b', 'B');
+
+ records1 = observer1.takeRecords();
+ assert.strictEqual(records1.length, 0);
+
+ records2 = observer2.takeRecords();
+ assert.strictEqual(records2.length, 1);
+ expectRecord(records2[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'b'
+ });
+ });
+
+}); \ No newline at end of file
diff --git a/addons/website/static/lib/MutationObservers/test/callback.js b/addons/website/static/lib/MutationObservers/test/callback.js
new file mode 100644
index 00000000000..b3083c7bec3
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/callback.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+suite('JsMutationObserver callback', function() {
+
+ test('One observer, two attribute changes', function(cont) {
+ var div = document.createElement('div');
+ var observer = new JsMutationObserver(function(records) {
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+ expectRecord(records[1], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+
+ cont();
+ });
+
+ observer.observe(div, {
+ attributes: true
+ });
+
+ div.setAttribute('a', 'A');
+ div.setAttribute('a', 'B');
+ });
+
+ test('nested changes', function(cont) {
+ var div = document.createElement('div');
+ var i = 0;
+ var observer = new JsMutationObserver(function(records) {
+ assert.strictEqual(records.length, 1);
+
+ if (i === 0) {
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+ div.setAttribute('b', 'B');
+ i++;
+ } else {
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'b',
+ attributeNamespace: null
+ });
+
+ cont();
+ }
+ });
+
+ observer.observe(div, {
+ attributes: true
+ });
+
+ div.setAttribute('a', 'A');
+ });
+
+}); \ No newline at end of file
diff --git a/addons/website/static/lib/MutationObservers/test/characterData.js b/addons/website/static/lib/MutationObservers/test/characterData.js
new file mode 100644
index 00000000000..498dc053e6e
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/characterData.js
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+suite('JsMutationObserver characterData', function() {
+
+ var testDiv;
+
+ setup(function() {
+ testDiv = document.body.appendChild(document.createElement('div'));
+ });
+
+ teardown(function() {
+ document.body.removeChild(testDiv);
+ });
+
+ test('characterData', function() {
+ var text = document.createTextNode('abc');
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(text, {
+ characterData: true
+ });
+ text.data = 'def';
+ text.data = 'ghi';
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'characterData',
+ target: text
+ });
+ expectRecord(records[1], {
+ type: 'characterData',
+ target: text
+ });
+ });
+
+ test('characterData with old value', function() {
+ var text = testDiv.appendChild(document.createTextNode('abc'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(text, {
+ characterData: true,
+ characterDataOldValue: true
+ });
+ text.data = 'def';
+ text.data = 'ghi';
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'characterData',
+ target: text,
+ oldValue: 'abc'
+ });
+ expectRecord(records[1], {
+ type: 'characterData',
+ target: text,
+ oldValue: 'def'
+ });
+ });
+
+ test('characterData change in subtree should not generate a record',
+ function() {
+ var div = document.createElement('div');
+ var text = div.appendChild(document.createTextNode('abc'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ characterData: true
+ });
+ text.data = 'def';
+ text.data = 'ghi';
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 0);
+ });
+
+ test('characterData change in subtree',
+ function() {
+ var div = document.createElement('div');
+ var text = div.appendChild(document.createTextNode('abc'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ characterData: true,
+ subtree: true
+ });
+ text.data = 'def';
+ text.data = 'ghi';
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'characterData',
+ target: text
+ });
+ expectRecord(records[1], {
+ type: 'characterData',
+ target: text
+ });
+ });
+
+}); \ No newline at end of file
diff --git a/addons/website/static/lib/MutationObservers/test/childList.js b/addons/website/static/lib/MutationObservers/test/childList.js
new file mode 100644
index 00000000000..8ff4e4f2718
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/childList.js
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+suite('JsMutationObserver childList', function() {
+
+ var testDiv;
+
+ teardown(function() {
+ document.body.removeChild(testDiv);
+ });
+
+ var addedNodes, removedNodes;
+
+ setup(function() {
+ testDiv = document.body.appendChild(document.createElement('div'));
+ addedNodes = [];
+ removedNodes = [];
+ });
+
+ function mergeRecords(records) {
+ records.forEach(function(record) {
+ if (record.addedNodes)
+ addedNodes.push.apply(addedNodes, record.addedNodes);
+ if (record.removedNodes)
+ removedNodes.push.apply(removedNodes, record.removedNodes);
+ });
+ }
+
+ function assertAll(records, expectedProperties) {
+ records.forEach(function(record) {
+ for (var propertyName in expectedProperties) {
+ assert.strictEqual(record[propertyName], expectedProperties[propertyName]);
+ }
+ });
+ }
+
+ test('appendChild', function() {
+ var div = document.createElement('div');
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+ var a = document.createElement('a');
+ var b = document.createElement('b');
+
+ div.appendChild(a);
+ div.appendChild(b);
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: div,
+ addedNodes: [a]
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: div,
+ addedNodes: [b],
+ previousSibling: a
+ });
+ });
+
+ test('insertBefore', function() {
+ var div = document.createElement('div');
+ var a = document.createElement('a');
+ var b = document.createElement('b');
+ var c = document.createElement('c');
+ div.appendChild(a);
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+
+ div.insertBefore(b, a);
+ div.insertBefore(c, a);
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: div,
+ addedNodes: [b],
+ nextSibling: a
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: div,
+ addedNodes: [c],
+ nextSibling: a,
+ previousSibling: b
+ });
+ });
+
+
+ test('removeChild', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var a = div.appendChild(document.createElement('a'));
+ var b = div.appendChild(document.createElement('b'));
+ var c = div.appendChild(document.createElement('c'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+
+ div.removeChild(b);
+ div.removeChild(a);
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: div,
+ removedNodes: [b],
+ nextSibling: c,
+ previousSibling: a
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: div,
+ removedNodes: [a],
+ nextSibling: c
+ });
+ });
+
+ test('Direct children', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+ var a = document.createElement('a');
+ var b = document.createElement('b');
+
+ div.appendChild(a);
+ div.insertBefore(b, a);
+ div.removeChild(b);
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 3);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: div,
+ addedNodes: [a]
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: div,
+ nextSibling: a,
+ addedNodes: [b]
+ });
+
+ expectRecord(records[2], {
+ type: 'childList',
+ target: div,
+ nextSibling: a,
+ removedNodes: [b]
+ });
+ });
+
+ test('subtree', function() {
+ var div = document.createElement('div');
+ var child = div.appendChild(document.createElement('div'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(child, {
+ childList: true
+ });
+ var a = document.createTextNode('a');
+ var b = document.createTextNode('b');
+
+ child.appendChild(a);
+ child.insertBefore(b, a);
+ child.removeChild(b);
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 3);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: child,
+ addedNodes: [a]
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: child,
+ nextSibling: a,
+ addedNodes: [b]
+ });
+
+ expectRecord(records[2], {
+ type: 'childList',
+ target: child,
+ nextSibling: a,
+ removedNodes: [b]
+ });
+ });
+
+ test('both direct and subtree', function() {
+ var div = document.createElement('div');
+ var child = div.appendChild(document.createElement('div'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true,
+ subtree: true
+ });
+ observer.observe(child, {
+ childList: true
+ });
+
+ var a = document.createTextNode('a');
+ var b = document.createTextNode('b');
+
+ child.appendChild(a);
+ div.appendChild(b);
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: child,
+ addedNodes: [a]
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: div,
+ addedNodes: [b],
+ previousSibling: child
+ });
+ });
+
+ test('Append multiple at once at the end', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var a = div.appendChild(document.createTextNode('a'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+
+ var df = document.createDocumentFragment();
+ var b = df.appendChild(document.createTextNode('b'));
+ var c = df.appendChild(document.createTextNode('c'));
+ var d = df.appendChild(document.createTextNode('d'));
+
+ div.appendChild(df);
+
+ var records = observer.takeRecords();
+ mergeRecords(records);
+
+ assertArrayEqual(addedNodes, [b, c, d]);
+ assertArrayEqual(removedNodes, []);
+ assertAll(records, {
+ type: 'childList',
+ target: div
+ });
+ });
+
+ test('Append multiple at once at the front', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var a = div.appendChild(document.createTextNode('a'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+
+ var df = document.createDocumentFragment();
+ var b = df.appendChild(document.createTextNode('b'));
+ var c = df.appendChild(document.createTextNode('c'));
+ var d = df.appendChild(document.createTextNode('d'));
+
+ div.insertBefore(df, a);
+
+ var records = observer.takeRecords();
+ mergeRecords(records);
+
+ assertArrayEqual(addedNodes, [b, c, d]);
+ assertArrayEqual(removedNodes, []);
+ assertAll(records, {
+ type: 'childList',
+ target: div
+ });
+ });
+
+ test('Append multiple at once in the middle', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var a = div.appendChild(document.createTextNode('a'));
+ var b = div.appendChild(document.createTextNode('b'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+
+ var df = document.createDocumentFragment();
+ var c = df.appendChild(document.createTextNode('c'));
+ var d = df.appendChild(document.createTextNode('d'));
+
+ div.insertBefore(df, b);
+
+ var records = observer.takeRecords();
+ mergeRecords(records);
+
+ assertArrayEqual(addedNodes, [c, d]);
+ assertArrayEqual(removedNodes, []);
+ assertAll(records, {
+ type: 'childList',
+ target: div
+ });
+ });
+
+ test('Remove all children', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var a = div.appendChild(document.createTextNode('a'));
+ var b = div.appendChild(document.createTextNode('b'));
+ var c = div.appendChild(document.createTextNode('c'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+
+ div.innerHTML = '';
+
+ var records = observer.takeRecords();
+ mergeRecords(records);
+
+ assertArrayEqual(addedNodes, []);
+ assertArrayEqual(removedNodes, [a, b, c]);
+ assertAll(records, {
+ type: 'childList',
+ target: div
+ });
+ });
+
+ test('Replace all children using innerHTML', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var a = div.appendChild(document.createTextNode('a'));
+ var b = div.appendChild(document.createTextNode('b'));
+
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true
+ });
+
+ div.innerHTML = '<c></c><d></d>';
+ var c = div.firstChild;
+ var d = div.lastChild;
+
+ var records = observer.takeRecords();
+ mergeRecords(records);
+
+ assertArrayEqual(addedNodes, [c, d]);
+ assertArrayEqual(removedNodes, [a, b]);
+ assertAll(records, {
+ type: 'childList',
+ target: div
+ });
+ });
+
+}); \ No newline at end of file
diff --git a/addons/website/static/lib/MutationObservers/test/index.html b/addons/website/static/lib/MutationObservers/test/index.html
new file mode 100644
index 00000000000..fcedaf4e3fe
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/index.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!--
+Copyright 2012 The Polymer Authors. All rights reserved.
+Use of this source code is governed by a BSD-style
+license that can be found in the LICENSE file.
+-->
+<meta charset="utf-8">
+<link rel="stylesheet" href="../node_modules/mocha/mocha.css">
+<script src="../node_modules/chai/chai.js"></script>
+<script src="../node_modules/mocha/mocha.js"></script>
+<script src="sidetable.js"></script>
+<script src="../MutationObserver.js"></script>
+<script>
+
+mocha.setup({
+ ui: 'tdd',
+ ignoreLeaks: true
+});
+
+var assert = chai.assert;
+
+function assertArrayEqual(a, b, msg) {
+ assert.equal(a.length, b.length, msg);
+ for (var i = 0; i < a.length; i++) {
+ assert.equal(a[i], b[i], msg);
+ }
+}
+
+var expectRecord = (function() {
+ var useNative = /native/.test(location.search);
+ var isWebKit = /WebKit/.test(navigator.userAgent);
+ var slice = Array.prototype.slice.call.bind(Array.prototype.slice);
+
+ if (useNative) {
+ JsMutationObserver =
+ window.MutationObserver || window.WebKitMutationObserver;
+ }
+
+ // addedNodes/removedNodes are broken in WebKit.
+ // https://bugs.webkit.org/show_bug.cgi?id=98921
+ function fixWebKitNodes(nodes) {
+ if (nodes === null && useNative && isWebKit)
+ return [];
+ return nodes;
+ }
+
+ return function expectRecord(record, expected) {
+ assert.strictEqual(record.type,
+ expected.type === undefined ? null : expected.type);
+ assert.strictEqual(record.target,
+ expected.target === undefined ? null : expected.target);
+ assertArrayEqual(fixWebKitNodes(record.addedNodes),
+ expected.addedNodes === undefined ? [] : expected.addedNodes);
+ assertArrayEqual(fixWebKitNodes(record.removedNodes),
+ expected.removedNodes === undefined ? [] : expected.removedNodes);
+ assert.strictEqual(record.previousSibling,
+ expected.previousSibling === undefined ?
+ null : expected.previousSibling);
+ assert.strictEqual(record.nextSibling,
+ expected.nextSibling === undefined ? null : expected.nextSibling);
+ assert.strictEqual(record.attributeName,
+ expected.attributeName === undefined ? null : expected.attributeName);
+ assert.strictEqual(record.attributeNamespace,
+ expected.attributeNamespace === undefined ?
+ null : expected.attributeNamespace);
+ assert.strictEqual(record.oldValue,
+ expected.oldValue === undefined ? null : expected.oldValue);
+ };
+})();
+
+</script>
+<script src="attributes.js"></script>
+<script src="characterData.js"></script>
+<script src="childList.js"></script>
+<script src="mixed.js"></script>
+<script src="callback.js"></script>
+<script src="transient.js"></script>
+<div id="mocha"></div>
+<script>
+mocha.run();
+</script>
diff --git a/addons/website/static/lib/MutationObservers/test/mixed.js b/addons/website/static/lib/MutationObservers/test/mixed.js
new file mode 100644
index 00000000000..eae6a60604c
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/mixed.js
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+suite('JsMutationObserver mixed types', function() {
+
+ test('attr and characterData', function() {
+ var div = document.createElement('div');
+ var text = div.appendChild(document.createTextNode('text'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true,
+ characterData: true,
+ subtree: true
+ });
+ div.setAttribute('a', 'A');
+ div.firstChild.data = 'changed';
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: div,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+ expectRecord(records[1], {
+ type: 'characterData',
+ target: div.firstChild
+ });
+ });
+
+}); \ No newline at end of file
diff --git a/addons/website/static/lib/MutationObservers/test/sidetable.js b/addons/website/static/lib/MutationObservers/test/sidetable.js
new file mode 100644
index 00000000000..cae31e6c012
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/sidetable.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is goverened by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+// SideTable is a weak map where possible. If WeakMap is not available the
+// association is stored as an expando property.
+var SideTable;
+// TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox
+if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') < 0) {
+ SideTable = WeakMap;
+} else {
+ (function() {
+ var defineProperty = Object.defineProperty;
+ var hasOwnProperty = Object.hasOwnProperty;
+ var counter = new Date().getTime() % 1e9;
+
+ SideTable = function() {
+ this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
+ };
+
+ SideTable.prototype = {
+ set: function(key, value) {
+ defineProperty(key, this.name, {value: value, writable: true});
+ },
+ get: function(key) {
+ return hasOwnProperty.call(key, this.name) ? key[this.name] : undefined;
+ },
+ delete: function(key) {
+ this.set(key, undefined);
+ }
+ }
+ })();
+}
diff --git a/addons/website/static/lib/MutationObservers/test/transient.js b/addons/website/static/lib/MutationObservers/test/transient.js
new file mode 100644
index 00000000000..7dda83e27d9
--- /dev/null
+++ b/addons/website/static/lib/MutationObservers/test/transient.js
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2012 The Polymer Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+suite('JsMutationObserver transient', function() {
+
+ var testDiv;
+
+ setup(function() {
+ testDiv = document.body.appendChild(document.createElement('div'));
+ });
+
+ teardown(function() {
+ document.body.removeChild(testDiv);
+ });
+
+ test('attr', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var child = div.appendChild(document.createElement('div'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ attributes: true,
+ subtree: true
+ });
+ div.removeChild(child);
+ child.setAttribute('a', 'A');
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+
+ child.setAttribute('b', 'B');
+
+ records = observer.takeRecords();
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'b',
+ attributeNamespace: null
+ });
+ });
+
+ test('attr callback', function(cont) {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var child = div.appendChild(document.createElement('div'));
+ var i = 0;
+ var observer = new JsMutationObserver(function(records) {
+ i++;
+ if (i > 1)
+ expect().fail();
+
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+
+ // The transient observers are removed before the callback is called.
+ child.setAttribute('b', 'B');
+ records = observer.takeRecords();
+ assert.strictEqual(records.length, 0);
+
+ cont();
+ });
+
+ observer.observe(div, {
+ attributes: true,
+ subtree: true
+ });
+
+ div.removeChild(child);
+ child.setAttribute('a', 'A');
+ });
+
+ test('attr, make sure transient gets removed', function(cont) {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var child = div.appendChild(document.createElement('div'));
+ var i = 0;
+ var observer = new JsMutationObserver(function(records) {
+ i++;
+ if (i > 1)
+ expect().fail();
+
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'a',
+ attributeNamespace: null
+ });
+
+ step2();
+ });
+
+ observer.observe(div, {
+ attributes: true,
+ subtree: true
+ });
+
+ div.removeChild(child);
+ child.setAttribute('a', 'A');
+
+ function step2() {
+ var div2 = document.createElement('div');
+ var observer2 = new JsMutationObserver(function(records) {
+ i++;
+ if (i > 2)
+ expect().fail();
+
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'attributes',
+ target: child,
+ attributeName: 'b',
+ attributeNamespace: null
+ });
+
+ cont();
+ });
+
+ observer2.observe(div2, {
+ attributes: true,
+ subtree: true,
+ });
+
+ div2.appendChild(child);
+ child.setAttribute('b', 'B');
+ }
+ });
+
+ test('characterData', function() {
+ var div = document.createElement('div');
+ var child = div.appendChild(document.createTextNode('text'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ characterData: true,
+ subtree: true
+ });
+ div.removeChild(child);
+ child.data = 'changed';
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'characterData',
+ target: child
+ });
+
+ child.data += ' again';
+
+ records = observer.takeRecords();
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'characterData',
+ target: child
+ });
+ });
+
+ test('characterData callback', function(cont) {
+ var div = document.createElement('div');
+ var child = div.appendChild(document.createTextNode('text'));
+ var i = 0;
+ var observer = new JsMutationObserver(function(records) {
+ i++;
+ if (i > 1)
+ expect().fail();
+
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'characterData',
+ target: child
+ });
+
+ // The transient observers are removed before the callback is called.
+ child.data += ' again';
+ records = observer.takeRecords();
+ assert.strictEqual(records.length, 0);
+
+ cont();
+ });
+ observer.observe(div, {
+ characterData: true,
+ subtree: true
+ });
+ div.removeChild(child);
+ child.data = 'changed';
+ });
+
+ test('childList', function() {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var child = div.appendChild(document.createElement('div'));
+ var observer = new JsMutationObserver(function() {});
+ observer.observe(div, {
+ childList: true,
+ subtree: true
+ });
+ div.removeChild(child);
+ var grandChild = child.appendChild(document.createElement('span'));
+
+ var records = observer.takeRecords();
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: div,
+ removedNodes: [child]
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: child,
+ addedNodes: [grandChild]
+ });
+
+ child.removeChild(grandChild);
+
+ records = observer.takeRecords();
+ assert.strictEqual(records.length, 1);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: child,
+ removedNodes: [grandChild]
+ });
+ });
+
+ test('childList callback', function(cont) {
+ var div = testDiv.appendChild(document.createElement('div'));
+ var child = div.appendChild(document.createElement('div'));
+ var i = 0;
+ var observer = new JsMutationObserver(function(records) {
+ i++;
+ if (i > 1)
+ expect().fail();
+
+ assert.strictEqual(records.length, 2);
+
+ expectRecord(records[0], {
+ type: 'childList',
+ target: div,
+ removedNodes: [child]
+ });
+
+ expectRecord(records[1], {
+ type: 'childList',
+ target: child,
+ addedNodes: [grandChild]
+ });
+
+ // The transient observers are removed before the callback is called.
+ child.removeChild(grandChild);
+
+ records = observer.takeRecords();
+ assert.strictEqual(records.length, 0);
+
+ cont();
+ });
+ observer.observe(div, {
+ childList: true,
+ subtree: true
+ });
+ div.removeChild(child);
+ var grandChild = child.appendChild(document.createElement('span'));
+ });
+});