This is an Important paragraph
" @"" @""; HTMLDocument *document = [HTMLDocument documentWithString:htmlString]; return document; } #pragma mark - Test Iterator - (void)testNodeIteratorInit { HTMLElement *tree = self.simpleTree; HTMLNodeIterator *iterator = tree.nodeIterator; XCTAssertEqualObjects(iterator.root, tree); XCTAssertEqualObjects(iterator.referenceNode, tree); XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES); XCTAssertEqualObjects(iterator.filter, nil); XCTAssertEqual(iterator.whatToShow, HTMLNodeFilterShowAll); } - (void)testNewIteratorNextNodeShouldBeRoot { HTMLElement *tree = self.simpleTree; HTMLNodeIterator *iterator = tree.nodeIterator; XCTAssertEqualObjects(iterator.nextNode, tree); XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO); } - (void)testNewIteratorPreviousNodeShouldBeNil { HTMLElement *tree = self.simpleTree; HTMLNodeIterator *iterator = tree.nodeIterator; XCTAssertEqualObjects(iterator.previousNode, nil); XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES); } - (void)testNewIteratorPreviousNodeShouldBeNextNode { HTMLElement *tree = self.simpleTree; HTMLNodeIterator *iterator = tree.nodeIterator; HTMLNode *node = iterator.nextNode; XCTAssertEqualObjects(iterator.previousNode, node); XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES); } - (void)testNextPreviousIteration { HTMLElement *tree = self.simpleTree; HTMLNodeIterator *iterator = tree.nodeIterator; XCTAssertEqualObjects(iterator.previousNode, nil); XCTAssertEqualObjects(iterator.nextNode.name, @"div"); XCTAssertEqualObjects(iterator.nextNode.name, @"a"); XCTAssertEqualObjects(iterator.previousNode.name, @"a"); XCTAssertEqualObjects(iterator.previousNode.name, @"div"); XCTAssertEqualObjects(iterator.nextNode.name, @"div"); XCTAssertEqualObjects(iterator.nextNode.name, @"a"); XCTAssertEqualObjects(iterator.nextNode.name, @"b"); XCTAssertEqualObjects(iterator.nextNode.name, @"c"); XCTAssertEqualObjects(iterator.previousNode.name, @"c"); XCTAssertEqualObjects(iterator.previousNode.name, @"b"); XCTAssertEqualObjects(iterator.previousNode.name, @"a"); XCTAssertEqualObjects(iterator.previousNode.name, @"div"); } - (void)testSingleNodeIteration { HTMLElement *div = self.div; NSArray *result = div.nodeIterator.allObjects; NSArray *expected = @[@"div"]; XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testSimpleTreeIteration { HTMLElement *tree = self.simpleTree; NSArray *result = tree.nodeIterator.allObjects; NSArray *expected = @[@"div", @"a", @"b", @"c"]; XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testNestedSimpleTreeIteration { HTMLElement *tree = self.nestedSimpleTree; NSArray *result = tree.nodeIterator.allObjects; NSArray *expected = @[@"div", @"div", @"a", @"b", @"c", @"div", @"a", @"b", @"c"]; XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testComplexTreeIteration { HTMLElement *tree = self.complexTree; NSArray *result = tree.nodeIterator.allObjects; NSArray *expected = @[@"div", @"div",@"div", @"a", @"b", @"c", @"e", @"f", @"div", @"a", @"b", @"c"]; XCTAssertEqualObjects([result valueForKey:@"name"], expected); } #pragma mark - Test Iterator ShowOptions (WhatToShow) - (void)testShowDocument { HTMLDocument *document = self.mixedTree; HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowDocument filter:nil]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"#document"]; XCTAssertEqual(result.count, 1); XCTAssertEqual([result.firstObject class], [HTMLDocument class]); XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testShowDocumentType { HTMLDocument *document = self.mixedTree; HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowDocumentType filter:nil]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"html"]; XCTAssertEqual(result.count, 1); XCTAssertEqual([result.firstObject class], [HTMLDocumentType class]); XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testShowComment { HTMLDocument *document = self.mixedTree; HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowComment filter:nil]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"#comment", @"#comment"]; XCTAssertEqual(result.count, 2); XCTAssertEqual([result[0] class], [HTMLComment class]); XCTAssertEqual([result[1] class], [HTMLComment class]); XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testShowText { HTMLDocument *document = self.mixedTree; HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowText filter:nil]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"#text"]; XCTAssertEqual(result.count, 1); XCTAssertEqual([result.firstObject class], [HTMLText class]); XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testShowElement { HTMLDocument *document = self.mixedTree; HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"html", @"div"]; XCTAssertEqual(result.count, 2); XCTAssertEqual([result.firstObject class], [HTMLElement class]); XCTAssertEqualObjects([result valueForKey:@"name"], expected); } - (void)testShowBitmask { HTMLDocument *document = self.mixedTree; HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowElement | HTMLNodeFilterShowText filter:nil]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"html", @"#text", @"div"]; XCTAssertEqual(result.count, 3); XCTAssertEqualObjects([result valueForKey:@"name"], expected); } #pragma mark - Test Iterator Filter - (void)testNodeFilter { HTMLDocument *document = self.mixedTree; HTMLNodeIterator *iterator = [document nodeIteratorWithShowOptions:HTMLNodeFilterShowAll filterBlock:^HTMLNodeFilterValue(HTMLNode *node) { if (node.nodeType == HTMLNodeComment) { if ([[(HTMLComment *)node data] rangeOfString:@"second"].location != NSNotFound) { return HTMLNodeFilterAccept; } } return HTMLNodeFilterSkip; }]; NSArray *result = iterator.allObjects; NSArray *expected = @[@"#comment"]; XCTAssertEqual(result.count, 1); XCTAssertEqualObjects([result[0] data], @"This is a second Comment"); XCTAssertEqualObjects([result valueForKey:@"name"], expected); } #pragma mark - Test Removing Steps /* Test cases for the Removing Steps https://dom.spec.whatwg.org/#interface-nodeiterator Following DOM is used: | | |
| "This is an "
|
| "Important"
| " paragraph"
*/
static void (^ RemoveThenInsertNode)(HTMLNode *) = ^ (HTMLNode *node) {
HTMLNode *parent = node.parentNode;
HTMLNode *nextSibling = node.nextSibling;
[parent removeChildNode:node];
[parent insertNode:node beforeChildNode:nextSibling];
};
static void (^ IterateUpToNode)(HTMLNodeIterator *, HTMLNode *) = ^ (HTMLNodeIterator *iterator, HTMLNode *target) {
for(HTMLNode *node = iterator.referenceNode; node && (node != target); node = iterator.nextNode);
};
static HTMLNode * (^ LastDescendant)(HTMLNode *) = ^ HTMLNode * (HTMLNode *node) {
while (node.lastChild) {
node = node.lastChild;
}
return node;
};
- (void)testThatRemovingRootNodeShouldNotAffectIterator
{
HTMLDocument *document = self.document;
HTMLNode *node = document.body.firstChild; //
HTMLNodeIterator *iterator = node.nodeIterator;
[document.body removeChildNode:node];
XCTAssertEqualObjects(iterator.root, node);
XCTAssertEqualObjects(iterator.referenceNode, node);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
XCTAssertEqualObjects(iterator.referenceNode.parentNode, nil);
}
- (void)testThatRemovingANonInclusiveAnscestorOfReferenceShouldNotAffectIterator
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
HTMLNodeIterator *iterator = body.nodeIterator;
[iterator nextNode]; // Reference node:
[iterator nextNode]; // Reference node:
RemoveThenInsertNode(iterator.root.childNodes[1]); // Remove
XCTAssertEqualObjects(iterator.root, body);
XCTAssertEqualObjects(iterator.referenceNode, body.firstChild);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
}
- (void)testThatRemovingReferenceNodeShouldUpdateIterator_NilOldPreviousSibling
{
HTMLDocument *document = self.document;
HTMLNodeIterator *iterator = document.body.nodeIterator;
[iterator nextNode]; // Reference node:
IterateUpToNode(iterator, node); // Reference node: , pointer-before-reference: NO
RemoveThenInsertNode(node); // Remove with old previos sibling being
XCTAssertEqualObjects(iterator.referenceNode, LastDescendant(body.firstChild));
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
}
- (void)testThatRemovingReferenceNodeShouldUpdateIterator_NonNilOldPreviousSibling_BeforeReference
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
HTMLNodeIterator *iterator = body.nodeIterator;
HTMLNode *node = iterator.root.childNodes[1]; //
IterateUpToNode(iterator, node); // Reference node: , pointer-before-reference: NO
[iterator previousNode]; // pointer-before-reference: YES
RemoveThenInsertNode(node); // Remove with old previos sibling being
XCTAssertEqualObjects(iterator.referenceNode, body.firstChild);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
}
- (void)testThatRemovingThenReinsertingReferenceNodeAfterNextShouldReturnItAgain
{
HTMLDocument *document = self.document;
HTMLNodeIterator *iterator = document.body.nodeIterator;
[iterator nextNode]; // Reference node:
HTMLNode *node = iterator.nextNode; //
RemoveThenInsertNode(node);
XCTAssertEqualObjects(iterator.referenceNode, iterator.root);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
HTMLNode *next = iterator.nextNode;
XCTAssertEqualObjects(next, node);
}
- (void)testThatRemovingThenReinsertingReferenceNodeAfterPreviousShouldReturnItAgain
{
HTMLDocument *document = self.document;
HTMLNodeIterator *iterator = document.body.nodeIterator;
[iterator nextNode]; // Reference node:
[iterator nextNode]; // Reference node:
HTMLNode *node = iterator.previousNode; // Reference node: , pointer-before-reference: YES
HTMLNode *next = node.nextSibling; //
RemoveThenInsertNode(node);
XCTAssertEqualObjects(iterator.referenceNode, next);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
HTMLNode *previous = iterator.previousNode;
XCTAssertEqualObjects(previous, LastDescendant(node));
}
- (void)testThatRemovingParentOfReferenceNodeShouldUpdateIterator_NotBeforeReference
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
HTMLNodeIterator *iterator = body.nodeIterator;
HTMLNode *parent = body.childNodes[1];
IterateUpToNode(iterator, parent); // Reference node: , pointer-before-reference: NO
[iterator nextNode]; // Reference node: "This is an "
RemoveThenInsertNode(parent);
XCTAssertEqualObjects(iterator.referenceNode, LastDescendant(body.firstChild));
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
}
- (void)testThatRemovingParentOfReferenceNodeShouldUpdateIterator_BeforeReference
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
HTMLNodeIterator *iterator = body.nodeIterator;
HTMLNode *parent = body.childNodes[1];
IterateUpToNode(iterator, parent); // Reference node: , pointer-before-reference: NO
[iterator nextNode]; // Reference node: "This is an "
[iterator previousNode]; // pointer-before-reference: YES
RemoveThenInsertNode(parent);
XCTAssertEqualObjects(iterator.referenceNode, body.firstChild);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
}
- (void)testRemoveReferenceNode_NilPreviousSibling_NonNilParentFirstChild
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
HTMLNodeIterator *iterator = body.nodeIterator;
[iterator nextNode]; // Reference node:
RemoveThenInsertNode(node);
XCTAssertEqualObjects(iterator.referenceNode, nextSibling);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
HTMLNode *next = iterator.nextNode; //
XCTAssertNotEqualObjects(next, node);
XCTAssertEqualObjects(next, nextSibling);
}
- (void)testRemoveReferenceNode_NodeAfterOldParentIsOutsideRoot_BeforeReference
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
body.innerHTML = @"