| <!DOCTYPE html> |
| <meta charset=utf-8> |
| <title>AnimationNode replace() method tests</title> |
| <meta name="assert" content="Replaces this AnimationNode with the passed in nodes parameter"> |
| <link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-replace"> |
| <link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node"> |
| <link rel="help" href="http://w3c.github.io/web-animations/#insert-children"> |
| <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> |
| <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="../testcommon.js"></script> |
| <link rel="stylesheet" href="/resources/testharness.css"> |
| <body> |
| <div id="log"></div> |
| <script> |
| // Step 1. If there is no parent animation group, terminate these steps. |
| test(function() { |
| var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node) { |
| try { |
| node.replace(null); |
| } catch(e) { |
| assert_unreached(type(node) + '.replace(null) throws unexpected exception: ' + e); |
| } |
| }); |
| }, 'AnimationNode.replace(null) does nothing if node has no parent animation group'); |
| |
| test(function() { |
| var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node) { |
| try { |
| node.replace(node); |
| } catch(e) { |
| assert_unreached(type(node) + '.replace(node) throws unexpected exception: ' + e); |
| } |
| }); |
| }, 'AnimationNode.replace() does nothing if node has no parent animation group. ' + |
| 'HierarchyRequestError is not thrown if the node is replacing itself'); |
| |
| test(function() { |
| var test = this; |
| var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node1) { |
| var node2 = newAnimation(createDiv(test)); |
| |
| try { |
| node1.replace(node2); |
| } catch(e) { |
| assert_unreached(type(node1) + '.replace() throws unexpected exception: ' + e); |
| } |
| }); |
| }, 'AnimationNode.replace() does nothing if node has no parent animation group'); |
| |
| // Step 2. If any of the animation nodes in nodes is an inclusive ancestor |
| // of the parent animation group throw a HierarchyRequestError exception and terminate these steps. |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node) { |
| var parent = new parentCtor([node]); |
| |
| assert_throws('HierarchyRequestError', function() { |
| node.replace(node); |
| }, 'HierarchyRequestError should be thrown if ' + type(node) + |
| ' replaces itself'); |
| assert_equals(node.parent, parent, type(node) + '.replace() should not change ' + |
| 'parent attribute before throwing HierarchyRequestError'); |
| assert_array_equals(parent.children, [node], type(node) + '.replace() ' + |
| 'should not change parent children before throwing HierarchyRequestError'); |
| }); |
| }); |
| }, 'HierarchyRequestError is thrown if the node replaces itself'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node) { |
| var parent = new parentCtor([node]); |
| |
| assert_throws('HierarchyRequestError', function() { |
| node.replace(parent); |
| }, 'HierarchyRequestError should be thrown if ' + type(node) + |
| ' is replaced by its parent ' + parentCtor.name); |
| assert_equals(node.parent, parent, type(node) + '.replace() should not change ' + |
| 'parent attribute before throwing HierarchyRequestError'); |
| assert_array_equals(parent.children, [node], type(node) + '.replace() ' + |
| 'should not change parent children before throwing HierarchyRequestError'); |
| }); |
| }); |
| }, 'HierarchyRequestError is thrown if the node is replaced by its parent'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node) { |
| var parent1 = new parentCtor([node]); |
| var parent2 = new parentCtor([parent1]); |
| var parent3 = new parentCtor([parent2]); |
| var parent4 = new parentCtor([parent3]); |
| |
| assert_throws('HierarchyRequestError', function() { |
| node.replace(parent3); |
| }, 'HierarchyRequestError should be thrown if ' + type(node) + |
| ' is replaced by its inclusive ancestor' + parentCtor.name); |
| assert_equals(node.parent, parent1, type(node) + '.replace() should not change ' + |
| 'parent attribute before throwing HierarchyRequestError'); |
| assert_array_equals(parent1.children, [node], type(node) + '.replace() ' + |
| 'should not change parent children before throwing HierarchyRequestError'); |
| assert_equals(parent3.parent, parent4, type(node) + '.replace() should not change ' + |
| 'parent attribute of replacement node before throwing HierarchyRequestError'); |
| assert_array_equals(parent4.children, [parent3], type(node) + '.replace() ' + |
| 'should not change replacement node parent children before throwing HierarchyRequestError'); |
| }); |
| }); |
| }, 'HierarchyRequestError is thrown if the node is replaced by its inclusive ancestor'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node1) { |
| var parent1 = new parentCtor([node1]); |
| var parent2 = new parentCtor([parent1]); |
| var parent3 = new parentCtor([parent2]); |
| var parent4 = new parentCtor([parent3]); |
| var node2 = newAnimation(createDiv(test)); |
| var parent5 = new parentCtor([node2]); |
| |
| assert_throws('HierarchyRequestError', function() { |
| node1.replace(node2, parent3); |
| }, 'HierarchyRequestError should be thrown if ' + type(node1) + |
| ' is replaced by its inclusive ancestor' + parentCtor.name); |
| assert_equals(node1.parent, parent1, type(node1) + '.replace() should not change ' + |
| 'parent attribute before throwing HierarchyRequestError'); |
| assert_array_equals(parent1.children, [node1], type(node1) + '.replace() ' + |
| 'should not change parent children before throwing HierarchyRequestError'); |
| assert_equals(parent3.parent, parent4, type(node1) + '.replace() should not change ' + |
| 'parent attribute of replacement node before throwing HierarchyRequestError'); |
| assert_array_equals(parent4.children, [parent3], type(node1) + '.replace() ' + |
| 'should not change replacement node parent children before throwing HierarchyRequestError'); |
| assert_equals(node2.parent, parent5, type(node1) + '.replace() should not change ' + |
| 'parent attribute of replacement node before throwing HierarchyRequestError'); |
| assert_array_equals(parent5.children, [node2], type(node1) + '.replace() ' + |
| 'should not change replacement node parent children before throwing HierarchyRequestError'); |
| }); |
| }); |
| }, 'HierarchyRequestError is thrown if node is replaced by its inclusive ancestor. ' + |
| 'Test several arguments in replace() call'); |
| |
| // Step 3. Let reference child be the next sibling of this animation node not in nodes. |
| // Step 4. Remove this animation node from its parent animation group. |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node) { |
| var parent = new parentCtor([node]); |
| |
| node.replace(); |
| |
| assert_array_equals(parent.children, [], type(node) + |
| ' node should be removed from parent ' + parentCtor.name); |
| assert_equals(node.parent, null, type(node) + |
| ' node parent attribute should be updated'); |
| }); |
| }); |
| }, 'AnimationNode.replace() without arguments removes the node from the parent ' + |
| 'animation group'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node1) { |
| var node2 = newAnimation(createDiv(test)); |
| var parent = new parentCtor([node1]); |
| |
| node1.replace(node2); |
| |
| assert_array_equals(parent.children, [node2], type(node1) + |
| ' node should be removed its parent group'); |
| assert_equals(node1.parent, null, type(node1) + |
| ' node should be removed from its parent group'); |
| assert_equals(node1.previousSibling, null, type(node1) + |
| ' node previousSibling attribute should be updated'); |
| assert_equals(node1.nextSibling, null, type(node1) + |
| ' node nextSibling attribute should be updated'); |
| }); |
| }); |
| }, 'AnimationNode.replace() removes the node from its parent animation group'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node2) { |
| var node1 = newAnimation(createDiv(test)); |
| var node3 = newAnimation(createDiv(test)); |
| var parent = new parentCtor([node1, node2, node3]); |
| |
| node2.replace(node3); |
| |
| assert_array_equals(parent.children, [node1,node3], type(node2) + |
| ' node should be removed from parent ' + parentCtor.name); |
| assert_equals(node2.parent, null, type(node2) + |
| ' node parent attribute should be updated'); |
| assert_equals(node2.nextSibling, null, type(node2) + |
| ' node nextSibling attribute should be updated'); |
| assert_equals(node2.previousSibling, null, type(node2) + |
| ' node previousSibling attribute should be updated'); |
| assert_equals(node1.nextSibling, node3, |
| 'Sibling node nextSibling attribute should be updated'); |
| assert_equals(node3.previousSibling, node1, |
| 'Sibling node previousSibling attribute should be updated'); |
| }); |
| }); |
| }, 'AnimationNode.replace(next sibling) removes the node from its parent ' + |
| 'animation group'); |
| |
| // Step 5. Insert nodes before reference child. |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node1) { |
| var node2 = newAnimation(createDiv(test)); |
| var parent = new parentCtor([node1]); |
| |
| node1.replace(node2); |
| |
| assert_array_equals(parent.children, [node2], type(node1) + |
| ' node should be replaced'); |
| assert_equals(node2.parent, parent, |
| 'Replacement node should be assigned to a parent group'); |
| }); |
| }); |
| }, 'AnimationNode.replace() replaces node in the parent animation group'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node4) { |
| var node1 = newAnimation(createDiv(test)); |
| var node2 = newAnimation(createDiv(test)); |
| var node3 = newAnimation(createDiv(test)); |
| var parent1 = new parentCtor([node1, node2]); |
| var parent2 = new parentCtor([node3, parent1, node4]); |
| |
| node4.replace(node1); |
| |
| assert_array_equals(parent1.children, [node2], |
| 'Replacement node should be removed from its previous position in the tree'); |
| assert_array_equals(parent2.children, [node3, parent1, node1], |
| 'Replacement node should be inserted into the new position'); |
| assert_equals(node1.parent, parent2, 'Inserted node parent group should be assigned'); |
| assert_equals(node1.previousSibling, parent1, |
| 'Inserted node previousSibling attribute should be updated'); |
| assert_equals(node1.nextSibling, null, |
| 'Inserted node nextSibling attribute should be updated'); |
| |
| assert_equals(node4.parent, null, 'Node should be removed from its parent group'); |
| assert_equals(node4.previousSibling, null, |
| 'Replaced node previousSibling attribute should be updated'); |
| assert_equals(node4.nextSibling, null, |
| 'Replaced node nextSibling attribute should be updated'); |
| }); |
| }); |
| }, 'Test AnimationNode.replace() replaces given node. The previous position ' + |
| 'of the replacement node is deeper in the tree than the current node'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node2) { |
| var node1 = newAnimation(createDiv(test)); |
| var node3 = newAnimation(createDiv(test)); |
| var node4 = newAnimation(createDiv(test)); |
| var parent1 = new parentCtor([node1, node2]); |
| var parent2 = new parentCtor([node3, parent1, node4]); |
| |
| node2.replace(node4); |
| |
| assert_array_equals(parent1.children, [node1, node4], |
| 'Replacement node should be inserted to the new position'); |
| assert_array_equals(parent2.children, [node3, parent1], |
| 'Replacement node should be removed from its previous position in the tree'); |
| assert_equals(node4.parent, parent1, 'Inserted node parent group should be changed'); |
| assert_equals(node4.previousSibling, node1, |
| 'Inserted node previousSibling attribute should be updated'); |
| assert_equals(node1.nextSibling, node4, |
| 'Inserted node sibling nextSibling attribute should be updated'); |
| |
| assert_equals(node2.parent, null, 'Replaced node parent group should be changed'); |
| assert_equals(node2.previousSibling, null, |
| 'Replaced node previousSibling attribute should be updated'); |
| assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' + |
| 'should be updated'); |
| }); |
| }); |
| }, 'Test AnimationNode.replace() replaces given node. The previous position ' + |
| 'of the replacement node is shallower in the tree than current node, but is not an ancestor'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node2) { |
| var node1 = newAnimation(createDiv(test)); |
| var node3 = newAnimation(createDiv(test)); |
| var node4 = newAnimation(createDiv(test)); |
| var parent = new parentCtor([node1, node2]); |
| |
| node2.replace(node3, node4); |
| |
| assert_array_equals(parent.children, [node1, node3, node4], type(node2) + '.replace() ' + |
| 'should replace the current node by ones passed in arguments'); |
| assert_equals(node1.nextSibling, node3, 'nextSibling attribute should be updated'); |
| assert_equals(node3.previousSibling, node1, 'Inserted node previousSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node3.nextSibling, node4, 'Inserted node nextSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed'); |
| assert_equals(node4.previousSibling, node3, 'Inserted node previousSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node4.nextSibling, null, 'Inserted node nextSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node4.parent, parent, 'Parent group of the second inserted node ' + |
| 'should be changed'); |
| assert_equals(node2.parent, null, 'Replaced node parent group should be changed'); |
| assert_equals(node2.previousSibling, null, |
| 'Replaced node previousSibling attribute should be updated'); |
| assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' + |
| 'should be updated'); |
| }); |
| }); |
| }, 'Test AnimationNode.replace() replaces given node. Test several arguments'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node2) { |
| var node1 = newAnimation(createDiv(test)); |
| var node3 = newAnimation(createDiv(test)); |
| var node4 = newAnimation(createDiv(test)); |
| var parent = new parentCtor([node1, node2]); |
| |
| node2.replace(node3, node4, node3, node4); |
| |
| assert_array_equals(parent.children, [node1, node3, node4], type(node2) + '.replace() ' + |
| 'should replace the current node by ones passed in arguments'); |
| assert_equals(node1.nextSibling, node3, 'nextSibling attribute should be updated'); |
| assert_equals(node3.previousSibling, node1, 'Inserted node previousSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node3.nextSibling, node4, 'Inserted node nextSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed'); |
| assert_equals(node4.previousSibling, node3, 'Inserted node previousSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node4.nextSibling, null, 'Inserted node nextSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node4.parent, parent, 'Parent group of the second inserted node ' + |
| 'should be changed'); |
| assert_equals(node2.parent, null, 'Replaced node parent group should be changed'); |
| assert_equals(node2.previousSibling, null, |
| 'Replaced node previousSibling attribute should be updated'); |
| assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' + |
| 'should be updated'); |
| }); |
| }); |
| }, 'Test AnimationNode.replace() replaces given node by several nodes, duplicate nodes are ignored'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node2) { |
| var node1 = newAnimation(createDiv(test)); |
| var node3 = newAnimation(createDiv(test)); |
| var node4 = newAnimation(createDiv(test)); |
| var parent = new parentCtor([node1, node2]); |
| |
| node2.replace(node3, node4, node3); |
| |
| assert_array_equals(parent.children, [node1, node4, node3], type(node2) + '.replace() ' + |
| 'should replace the current node by ones passed in arguments'); |
| assert_equals(node1.nextSibling, node4, 'nextSibling attribute should be updated'); |
| assert_equals(node4.previousSibling, node1, 'Inserted node previousSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node4.nextSibling, node3, 'Inserted node nextSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed'); |
| assert_equals(node3.previousSibling, node4, 'Inserted node previousSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node3.nextSibling, null, 'Inserted node nextSibling attribute ' + |
| 'should be updated'); |
| assert_equals(node3.parent, parent, 'Parent group of the second inserted node ' + |
| 'should be changed'); |
| assert_equals(node2.parent, null, 'Replaced node parent group should be changed'); |
| assert_equals(node2.previousSibling, null, |
| 'Replaced node previousSibling attribute should be updated'); |
| assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' + |
| 'should be updated'); |
| }); |
| }); |
| }, 'Test AnimationNode.replace() replaces given node by several nodes, check replacement order'); |
| |
| test(function() { |
| var test = this; |
| var parents = [AnimationGroup, AnimationSequence]; |
| parents.forEach(function(parentCtor) { |
| var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])]; |
| nodes.forEach(function(node1) { |
| var node2 = newAnimation(createDiv(test)); |
| var parent = new parentCtor([node1]); |
| var player = document.timeline.play(node2); |
| |
| assert_equals(player.source, node2, 'The node should be associated with its player'); |
| node1.replace(node2); |
| assert_equals(player.source, null, 'The node should be disassociated from its player'); |
| }); |
| }); |
| }, 'Test AnimationNode.replace() disassociates the inserted node from the player, ' + |
| 'if node is directly associated with a player'); |
| </script> |
| </body> |