true ] ); $newDOM = ContentUtils::ppToDOM( $mockEnv, $b, [ 'markNew' => true ] ); $domDiff = new DOMDiff( $mockEnv ); $domDiff->diff( $oldDOM, $newDOM ); return [ 'body' => $newDOM, 'env' => $mockEnv ]; } /** * @covers ::doDOMDiff * @dataProvider provideDiff * @param array $test */ public function testDOMDiff( $test ) { $result = $this->parseAndDiff( $test['orig'], $test['edit'] ); $body = $result['body']; if ( count( $test['specs'] ) === 0 ) { // Verify that body has no diff markers // Dump DOM *with* diff marker attributes to ensure diff markers show up! $opts = [ 'env' => $result['env'], 'keepTmp' => true, 'storeDiffMark' => true, 'tunnelFosteredContent' => true, 'quiet' => true ]; DOMDataUtils::visitAndStoreDataAttribs( $body, $opts ); $this->assertEquals( DOMCompat::getInnerHTML( $body ), $test['edit'] ); return; } foreach ( $test['specs'] as $spec ) { if ( $spec['selector'] === 'body' ) { // Hmm .. why is this? $node = $body; } else { $nodes = DOMCompat::querySelectorAll( $body, $spec['selector'] ); $this->assertSame( 1, count( $nodes ) ); $node = $nodes[0]; } if ( isset( $spec['diff'] ) ) { $this->assertTrue( DOMUtils::isDiffMarker( $node, $spec['diff'] ) ); } elseif ( isset( $spec['markers'] ) ) { // NOTE: Not using DiffUtils.getDiffMark because that // tests for page id and we may not be mocking that // precisely here. And, we need to revisit whether that // page id comparison is still needed / useful. $data = DOMDataUtils::getNodeData( $node ); $markers = $data->parsoid_diff->diff; $this->assertEquals( count( $spec['markers'] ), count( $markers ), 'number of markers does not match' ); foreach ( $markers as $k => $m ) { $this->assertEquals( $spec['markers'][$k], $m, 'markers do not match' ); } } } } // FIXME: The subtree-changed marker seems to be applied inconsistently. // Check if that marker is still needed / used by serialization code and // update code accordingly. If possible, simplify / reduce the different // markers being used. public function provideDiff() { return [ [ [ 'desc' => 'ignore attribute order in a node', 'orig' => 'foo', 'edit' => 'foo', 'specs' => [] ] ], [ [ 'desc' => 'changing text in a node', 'orig' => '

a

b

', 'edit' => '

A

b

', 'specs' => [ [ 'selector' => 'body > p:first-child', 'markers' => [ 'children-changed', 'subtree-changed' ] ], [ 'selector' => 'body > p:first-child > meta:first-child', 'diff' => 'deleted' ] ] ] ], [ [ 'desc' => 'deleting a node', 'orig' => '

a

b

', 'edit' => '

a

', 'specs' => [ [ 'selector' => 'body', 'markers' => [ 'children-changed' ] ], [ 'selector' => 'body > p + meta', 'diff' => 'deleted' ] ] ] ], [ [ 'desc' => 'adding multiple nodes', 'orig' => '

a

', 'edit' => '

x

a

y

', 'specs' => [ [ 'selector' => 'body', 'markers' => [ 'children-changed' ] ], [ 'selector' => 'body > p:nth-child(1)', 'markers' => [ 'children-changed', 'subtree-changed' ] ], [ 'selector' => 'body > p:nth-child(1) > meta', 'diff' => 'deleted' ], [ 'selector' => 'body > p:nth-child(2)', 'markers' => [ 'inserted' ] ], [ 'selector' => 'body > p:nth-child(3)', 'markers' => [ 'inserted' ] ] ] ] ], [ [ 'desc' => 'reordering nodes', 'orig' => '

a

b

', 'edit' => '

b

a

', 'specs' => [ [ 'selector' => 'body > p:nth-child(1)', 'markers' => [ 'children-changed', 'subtree-changed' ] ], [ 'selector' => 'body > p:nth-child(1) > meta', 'diff' => 'deleted' ], [ 'selector' => 'body > p:nth-child(2)', 'markers' => [ 'children-changed', 'subtree-changed' ] ], [ 'selector' => 'body > p:nth-child(2) > meta', 'diff' => 'deleted' ] ] ] ], [ [ 'desc' => 'adding and deleting nodes', 'orig' => '

a

b

c

', 'edit' => '

x

b

', 'specs' => [ [ 'selector' => 'body', 'markers' => [ 'children-changed' ] ], [ 'selector' => 'body > p:nth-child(1)', 'markers' => [ 'children-changed', 'subtree-changed' ] ], [ 'selector' => 'body > p:nth-child(1) > meta', 'diff' => 'deleted' ], [ 'selector' => 'body > meta:nth-child(3)', 'diff' => 'deleted' ] ] ] ], [ [ 'desc' => 'changing an attribute', 'orig' => '

a

b

', 'edit' => '

a

b

', 'specs' => [ [ 'selector' => 'body', 'markers' => [ 'children-changed' ] ], [ 'selector' => 'body > p:nth-child(1)', 'markers' => [ 'modified-wrapper' ] ] ] ] ], [ [ 'desc' => 'changing data-mw for a template', 'orig' => '

a

', 'edit' => '

foo

', 'specs' => [ [ 'selector' => 'body', 'markers' => [ 'children-changed' ] ], [ 'selector' => 'body > p:nth-child(1)', 'markers' => [ 'modified-wrapper' ] ], ] ] ], // The additional subtrees added to the template's content should simply be ignored [ [ 'desc' => 'adding additional DOM trees to templated content', 'orig' => '

a

', 'edit' => '

foo

bar

baz

', 'specs' => [ [ 'selector' => 'body', 'markers' => [ 'children-changed' ] ], [ 'selector' => 'body > p:nth-child(1)', 'markers' => [ 'modified-wrapper' ] ], ] ] ] ]; } }