Merge branch 'develop' into feature/css_selectors

Conflicts:
	HTMLKit.xcodeproj/project.pbxproj
	HTMLKit/HTMLNodeFilter.h
This commit is contained in:
iska
2015-06-06 20:20:27 +02:00
30 changed files with 2178 additions and 390 deletions
+2 -3
View File
@@ -13,7 +13,6 @@
#import "HTMLElement.h"
#import "HTMLText.h"
#import "HTMLComment.h"
#import "HTMLNodeTreeEnumerator.h"
static NSString * const HTML5LibTests = @"html5lib-tests";
static NSString * const TreeConstruction = @"tree-construction";
@@ -111,7 +110,7 @@ static NSString * const TreeConstruction = @"tree-construction";
fragment = [fragment substringFromIndex:@"svg ".length];
namespace = HTMLNamespaceSVG;
}
test.documentFragment = [[HTMLElement alloc] initWithTagName:fragment attributes:nil namespace:namespace];
test.documentFragment = [[HTMLElement alloc] initWithTagName:fragment namespace:namespace attributes:nil];
} else if ([match hasPrefix:@"#document\n"]) {
NSArray *parts = [[match substringFromIndex:@"#document\n".length] componentsSeparatedByString:@"| "];
NSArray *nodes = [HTML5LibTreeConstructionTest parseDocument:parts];
@@ -245,7 +244,7 @@ NS_INLINE HTMLElement * parseTag(NSString *str)
NSString *tagName = parts.count == 2 ? parts[1] : parts[0];
HTMLNamespace namespace = parts.count == 1 ? HTMLNamespaceHTML : ([parts[0] isEqualToString:@"math"] ? HTMLNamespaceMathML : HTMLNamespaceSVG);
HTMLElement *element = [[HTMLElement alloc] initWithTagName:tagName attributes:nil namespace:namespace];
HTMLElement *element = [[HTMLElement alloc] initWithTagName:tagName namespace:namespace attributes:nil];
return element;
}
@@ -7,7 +7,7 @@
//
#import <XCTest/XCTest.h>
#import "HTMLNodes.h"
#import "HTMLDOM.h"
#import "NSString+HTMLKit.h"
extern uint64_t dispatch_benchmark(size_t count, void (^block)(void));
+568
View File
@@ -0,0 +1,568 @@
//
// HTMLKitNodeTreeEnumratorTests.m
// HTMLKit
//
// Created by Iska on 28/03/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "HTMLDOM.h"
@interface HTMLKitNodeIteratorTests : XCTestCase
@end
@implementation HTMLKitNodeIteratorTests
#pragma mark - Test DOM
- (HTMLElement *)div
{
return [[HTMLElement alloc] initWithTagName:@"div"];
}
- (HTMLElement *)simpleTree
{
/*
| div
| a
| b
| c
*/
HTMLElement *div = self.div;
[div appendNode:[[HTMLElement alloc] initWithTagName:@"a"]];
[div appendNode:[[HTMLElement alloc] initWithTagName:@"b"]];
[div appendNode:[[HTMLElement alloc] initWithTagName:@"c"]];
return div;
}
- (HTMLElement *)nestedSimpleTree
{
/*
| div
| div
| a
| b
| c
| div
| a
| b
| c
*/
HTMLElement *div = self.div;
[div appendNode:self.simpleTree];
[div appendNode:self.simpleTree];
return div;
}
- (HTMLElement *)complexTree
{
/*
| div
| div
| div
| a
| b
| c
| e
| f
| div
| a
| b
| c
*/
HTMLElement *root = self.div;
HTMLElement *div = self.div;
[div appendNode:self.simpleTree];
[root appendNode:div];
HTMLElement *e = [[HTMLElement alloc] initWithTagName:@"e"];
[e appendNode:[[HTMLElement alloc] initWithTagName:@"f"]];
[root appendNode:e];
[root appendNode:self.simpleTree];
return root;
}
- (HTMLDocument *)mixedTree
{
/*
| doctype
| #comment <!-- This is a Comment -->
| #comment <!-- This is a second Comment -->
| html
| #text "This is a Text"
| div
*/
HTMLDocument *document = [HTMLDocument new];
document.documentType = [HTMLDocumentType new];;
HTMLComment *comment = [[HTMLComment alloc] initWithData:@"This is a Comment"];
[document appendNode:comment];
HTMLComment *secondCommnet = [[HTMLComment alloc] initWithData:@"This is a second Comment"];
[document appendNode:secondCommnet];
HTMLElement *root = [[HTMLElement alloc] initWithTagName:@"html"];
[document appendNode:root];
[root appendNode:[[HTMLText alloc] initWithData:@"This is a Text"]];
[root appendNode:[[HTMLElement alloc] initWithTagName:@"div"]];
return document;
}
- (HTMLDocument *)document
{
NSString *htmlString =
@"<!DOCTYPE html>"
@"<html>"
@"<head>"
@"<title>Title</title>"
@"</head>"
@"<body>"
@"<span>Hello<strong>World!</strong><strong>HTML <!-- This is a Comment! --> Kit</strong></span>"
@"<p>This is an <em>Important</em> paragraph</p>"
@"</body>"
@"</html>";
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:
| <html>
| <head>
| <title>
| "Title"
| <body>
| <span>
| "Hello"
| <strong>
| "World!"
| <strong>
| "HTML "
| <!-- This is a Comment! -->
| " Kit"
| <p>
| "This is an "
| <em>
| "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; // <span>
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: <body>
[iterator nextNode]; // Reference node: <span>
RemoveThenInsertNode(iterator.root.childNodes[1]); // Remove <p>
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: <body>
HTMLNode *node = iterator.nextNode; // Reference node: <span>
RemoveThenInsertNode(node); // Remove <span> with old previos sibling being nil
XCTAssertEqualObjects(iterator.referenceNode, iterator.root);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
HTMLNode *next = iterator.nextNode; // "Hello"
XCTAssertEqualObjects(next, iterator.root.firstChild);
}
- (void)testThatRemovingReferenceNodeShouldUpdateIterator_NonNilOldPreviousSibling_NotBeforeReference
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
HTMLNodeIterator *iterator = body.nodeIterator;
HTMLNode *node = iterator.root.childNodes[1]; // <p>
IterateUpToNode(iterator, node); // Reference node: <p>, pointer-before-reference: NO
RemoveThenInsertNode(node); // Remove <p> with old previos sibling being <span>
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]; // <p>
IterateUpToNode(iterator, node); // Reference node: <p>, pointer-before-reference: NO
[iterator previousNode]; // pointer-before-reference: YES
RemoveThenInsertNode(node); // Remove <p> with old previos sibling being <span>
XCTAssertEqualObjects(iterator.referenceNode, body.firstChild);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
}
- (void)testThatRemovingThenReinsertingReferenceNodeAfterNextShouldReturnItAgain
{
HTMLDocument *document = self.document;
HTMLNodeIterator *iterator = document.body.nodeIterator;
[iterator nextNode]; // Reference node: <body>
HTMLNode *node = iterator.nextNode; // <span>
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: <body>
[iterator nextNode]; // Reference node: <span>
HTMLNode *node = iterator.previousNode; // Reference node: <span>, pointer-before-reference: YES
HTMLNode *next = node.nextSibling; // <p>
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: <p>, 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: <p>, 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: <body>
[iterator nextNode]; // Reference node: <span>
HTMLNode *node = iterator.previousNode; // Reference node: <span>, pointer-before-reference: YES
XCTAssertNil(node.previousSibling);
XCTAssertNotNil(node.nextSibling);
HTMLNode *nextSibling = node.nextSibling; // <p>
RemoveThenInsertNode(node);
XCTAssertEqualObjects(iterator.referenceNode, nextSibling);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, YES);
HTMLNode *next = iterator.nextNode; // <p>
XCTAssertNotEqualObjects(next, node);
XCTAssertEqualObjects(next, nextSibling);
}
- (void)testRemoveReferenceNode_NodeAfterOldParentIsOutsideRoot_BeforeReference
{
HTMLDocument *document = self.document;
HTMLNode *body = document.body;
body.innerHTML = @"<div><p><a></a></p></div><div></div>";
HTMLNodeIterator *iterator = body.firstChild.nodeIterator;
IterateUpToNode(iterator, LastDescendant(body.firstChild)); // Referecne node: <a>
HTMLNode *node = [iterator previousNode]; // pointer-before-reference: YES
RemoveThenInsertNode(node);
XCTAssertEqualObjects(iterator.referenceNode, iterator.root.firstChild);
XCTAssertEqual(iterator.pointerBeforeReferenceNode, NO);
}
@end
@@ -1,148 +0,0 @@
//
// HTMLKitNodeTreeEnumratorTests.m
// HTMLKit
//
// Created by Iska on 28/03/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "HTMLNodes.h"
@interface HTMLKitNodeTreeEnumratorTests : XCTestCase
@end
@implementation HTMLKitNodeTreeEnumratorTests
#pragma mark - Elements
- (HTMLElement *)div
{
return [[HTMLElement alloc] initWithTagName:@"div"];
}
- (HTMLElement *)simpleTree
{
/*
| div
| a
| b
| c
*/
HTMLElement *div = self.div;
[div appendNode:[[HTMLElement alloc] initWithTagName:@"a"]];
[div appendNode:[[HTMLElement alloc] initWithTagName:@"b"]];
[div appendNode:[[HTMLElement alloc] initWithTagName:@"c"]];
return div;
}
- (HTMLElement *)nestedSimpleTree
{
/*
| div
| div
| a
| b
| c
| div
| a
| b
| c
*/
HTMLElement *div = self.div;
[div appendNode:self.simpleTree];
[div appendNode:self.simpleTree];
return div;
}
- (HTMLElement *)complexTree
{
/*
| div
| div
| div
| a
| b
| c
| e
| f
| div
| a
| b
| c
*/
HTMLElement *root = self.div;
HTMLElement *div = self.div;
[div appendNode:self.simpleTree];
[root appendNode:div];
HTMLElement *e = [[HTMLElement alloc] initWithTagName:@"e"];
[e appendNode:[[HTMLElement alloc] initWithTagName:@"f"]];
[root appendNode:e];
[root appendNode:self.simpleTree];
return root;
}
#pragma mark - Tests
- (void)testSingle
{
HTMLElement *div = self.div;
NSArray *result = div.treeEnumerator.allObjects;
NSArray *expected = @[@"div"];
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
}
- (void)testSimpleTree
{
HTMLElement *tree = self.simpleTree;
NSArray *result = tree.treeEnumerator.allObjects;
NSArray *expected = @[@"div", @"a", @"b", @"c"];
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
}
- (void)testSimpleTreeReversed
{
HTMLElement *tree = self.simpleTree;
NSArray *result = tree.reverseTreeEnumerator.allObjects;
NSArray *expected = @[@"div", @"c", @"b", @"a"];
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
}
- (void)testNestedSimpleTree
{
HTMLElement *tree = self.nestedSimpleTree;
NSArray *result = tree.treeEnumerator.allObjects;
NSArray *expected = @[@"div", @"div", @"a", @"b", @"c", @"div", @"a", @"b", @"c"];
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
}
- (void)testNestedSimpleTreeReversed
{
HTMLElement *tree = self.nestedSimpleTree;
NSArray *result = tree.reverseTreeEnumerator.allObjects;
NSArray *expected = @[@"div", @"div", @"c", @"b", @"a", @"div", @"c", @"b", @"a"];
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
}
- (void)testComplexSimpleTree
{
HTMLElement *tree = self.complexTree;
NSArray *result = tree.treeEnumerator.allObjects;
NSArray *expected = @[@"div", @"div",@"div", @"a", @"b", @"c", @"e", @"f", @"div", @"a", @"b", @"c"];
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
}
- (void)testComplexSimpleTreeReversed
{
HTMLElement *tree = self.complexTree;
NSArray *result = tree.reverseTreeEnumerator.allObjects;
NSArray *expected = @[@"div", @"div", @"c", @"b", @"a", @"e", @"f", @"div", @"div", @"c", @"b", @"a"];
XCTAssertEqualObjects([result valueForKey:@"name"], expected);
}
@end
+34 -22
View File
@@ -7,7 +7,7 @@
//
#import <XCTest/XCTest.h>
#import "HTMLNodes.h"
#import "HTMLDOM.h"
@interface HTMLKitNodesTests : XCTestCase
@@ -30,18 +30,17 @@
HTMLNode *node = [[HTMLNode alloc] initWithName:@"name" type:HTMLNodeElement];
XCTAssertNotNil(node);
XCTAssertEqualObjects(node.name, @"name");
XCTAssertEqual(node.type, HTMLNodeElement);
XCTAssertEqual(node.nodeType, HTMLNodeElement);
XCTAssertNotNil(node.childNodes);
XCTAssertEqual(node.childNodes.count, 0);
XCTAssertNil(node.ownerDocument);
XCTAssertNil(node.baseURI);
XCTAssertNil(node.parentNode);
XCTAssertNil(node.parentElement);
XCTAssertNil(node.firstChiledNode);
XCTAssertNil(node.lastChildNode);
XCTAssertNil(node.firstChild);
XCTAssertNil(node.lastChild);
XCTAssertNil(node.previousSibling);
XCTAssertNil(node.lastChildNode);
XCTAssertNil(node.lastChild);
}
- (void)testAppendNode
@@ -51,7 +50,7 @@
[element appendNode:comment];
XCTAssertEqual(element.childNodesCount, 1);
XCTAssertEqual(element.firstChiledNode, comment);
XCTAssertEqual(element.firstChild, comment);
HTMLElement *firstElement = [HTMLElement new];
HTMLElement *secondElement = [HTMLElement new];
@@ -60,8 +59,8 @@
[element appendNodes:nodes];
XCTAssertEqual(element.childNodesCount, 3);
XCTAssertEqual(element.firstChiledNode, comment);
XCTAssertEqual(element.lastChildNode, secondElement);
XCTAssertEqual(element.firstChild, comment);
XCTAssertEqual(element.lastChild, secondElement);
}
- (void)testPrependNode
@@ -74,7 +73,7 @@
[element prependNode:comment];
XCTAssertEqual(element.childNodesCount, 2);
XCTAssertEqual(element.firstChiledNode, comment);
XCTAssertEqual(element.firstChild, comment);
HTMLElement *firstElement = [HTMLElement new];
HTMLElement *secondElement = [HTMLElement new];
@@ -83,8 +82,8 @@
[element prependNodes:nodes];
XCTAssertEqual(element.childNodesCount, 4);
XCTAssertEqual(element.firstChiledNode, firstElement);
XCTAssertEqual(element.lastChildNode, text);
XCTAssertEqual(element.firstChild, firstElement);
XCTAssertEqual(element.lastChild, text);
}
- (void)testAppendDocumentFragment
@@ -105,10 +104,10 @@
XCTAssertEqualObjects(firstChild.parentNode, element);
XCTAssertEqualObjects(secondChild.parentNode, element);
XCTAssertEqualObjects(element.firstChiledNode, comment);
XCTAssertEqualObjects(element.firstChiledNode.nextSibling, firstChild);
XCTAssertEqualObjects(element.lastChildNode.previousSibling, firstChild);
XCTAssertEqualObjects(element.lastChildNode, secondChild);
XCTAssertEqualObjects(element.firstChild, comment);
XCTAssertEqualObjects(element.firstChild.nextSibling, firstChild);
XCTAssertEqualObjects(element.lastChild.previousSibling, firstChild);
XCTAssertEqualObjects(element.lastChild, secondChild);
}
- (void)testParentNode
@@ -171,20 +170,20 @@
HTMLNode *firstChild = [[HTMLNode alloc] initWithName:@"first" type:HTMLNodeElement];
[node appendNode:firstChild];
XCTAssertEqualObjects(node.firstChiledNode, firstChild);
XCTAssertEqualObjects(node.lastChildNode, firstChild);
XCTAssertEqualObjects(node.firstChild, firstChild);
XCTAssertEqualObjects(node.lastChild, firstChild);
HTMLNode *secondChild = [[HTMLNode alloc] initWithName:@"second" type:HTMLNodeElement];
[node appendNode:secondChild];
XCTAssertEqualObjects(node.firstChiledNode, firstChild);
XCTAssertEqualObjects(node.lastChildNode, secondChild);
XCTAssertEqualObjects(node.firstChild, firstChild);
XCTAssertEqualObjects(node.lastChild, secondChild);
HTMLNode *thirdChild = [[HTMLNode alloc] initWithName:@"third" type:HTMLNodeElement];
[node appendNode:thirdChild];
XCTAssertEqualObjects(node.firstChiledNode, firstChild);
XCTAssertEqualObjects(node.lastChildNode, thirdChild);
XCTAssertEqualObjects(node.firstChild, firstChild);
XCTAssertEqualObjects(node.lastChild, thirdChild);
}
- (void)testNextAndPreviousSiblingNodes
@@ -470,4 +469,17 @@
XCTAssertEqualObjects(thirdChild.parentNode, newParent);
}
- (void)testElementSetInnerHTML
{
HTMLElement *element = [[HTMLElement alloc] initWithTagName:@"div"];
[element appendNode:[[HTMLElement alloc] initWithTagName:@"img"]];
[element setInnerHTML:@"<p></p><p></p>"];
XCTAssertEqual(element.childNodesCount, 2);
XCTAssertEqualObjects(element.firstChild.asElement.tagName, @"p");
XCTAssertEqualObjects([element childNodeAtIndex:1].asElement.tagName, @"p");
}
@end
+4
View File
@@ -15,6 +15,8 @@
@implementation HTMLKitParserPerformance
#define HTMLKIT_NO_DOM_CHECKS
- (void)testParserPerformance
{
NSString *path = [[NSBundle bundleForClass:self.class] resourcePath];
@@ -28,4 +30,6 @@
}];
}
#undef HTMLKIT_NO_DOM_CHECKS
@end
+5 -5
View File
@@ -9,7 +9,7 @@
#import <XCTest/XCTest.h>
#import "HTML5LibTreeConstructionTest.h"
#import "HTMLNodes.h"
#import "HTMLDOM.h"
#import "HTMLParser.h"
@@ -121,14 +121,14 @@
{
XCTAssertEqualObjects(actual.name, expected.name, @"Node name mismatch [%@ should be %@]:\n%@",
actual.name, expected.name, message);
XCTAssert(actual.type == expected.type, @"Node type mismatch [%hd should be %hd]:\n%@",
actual.type, expected.type, message);
XCTAssert(actual.nodeType == expected.nodeType, @"Node type mismatch [%hd should be %hd]:\n%@",
actual.nodeType, expected.nodeType, message);
if (actual.type != expected.type) {
if (actual.nodeType != expected.nodeType) {
return;
}
switch (actual.type) {
switch (actual.nodeType) {
case HTMLNodeDocumentType:
XCTAssertEqualObjects([(HTMLDocumentType *)actual publicIdentifier], [(HTMLDocumentType *)expected publicIdentifier], @"%@", message);
XCTAssertEqualObjects([(HTMLDocumentType *)actual systemIdentifier], [(HTMLDocumentType *)expected systemIdentifier], @"%@", message);
+503
View File
@@ -0,0 +1,503 @@
//
// HTMLTreeWalkerTests.m
// HTMLKit
//
// Created by Iska on 05/06/15.
// Copyright (c) 2015 BrainCookie. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "HTMLTreeWalker.h"
#import "HTMLDOM.h"
@interface HTMLTreeWalkerTests : XCTestCase
@end
@implementation HTMLTreeWalkerTests
#pragma mark - Asserts
#define AssertElementWithId(input, id) \
do { \
HTMLNode *node = input;\
XCTAssertEqual(node.nodeType, HTMLNodeElement);\
XCTAssertEqualObjects(node.asElement[@"id"], id);\
} while(0)
#define AssertTextWithValue(input, value) \
do { \
HTMLNode *node = input;\
XCTAssertEqual(node.nodeType, HTMLNodeText);\
XCTAssertEqualObjects(node.textContent, value);\
} while(0)
#define AssertCommentWithValue(input, value) \
do { \
HTMLNode *node = input;\
XCTAssertEqual(node.nodeType, HTMLNodeComment);\
XCTAssertEqualObjects(node.textContent, value);\
} while(0)
#pragma mark - Tests
- (void)testTreeWalkerInit
{
HTMLNode *root = self.basicWalkingDOM;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root];
XCTAssertNotNil(walker);
XCTAssertNotNil(walker.root);
XCTAssertNotNil(walker.currentNode);
XCTAssertNil(walker.filter);
XCTAssertEqual(walker.whatToShow, HTMLNodeFilterShowAll);
XCTAssertEqualObjects(walker.root, root);
XCTAssertEqualObjects(walker.root, walker.currentNode);
}
#pragma mark - Basic Walking
- (HTMLNode *)basicWalkingDOM
{
// Tree structure:
// #a
// |
// +----+----+
// | |
// "b" #c
// |
// +----+----+
// | |
// #d <!--j-->
// |
// +----+----+
// | | |
// "e" #f "i"
// |
// +--+--+
// | |
// "g" <!--h-->
HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"a"}];
[div appendNode:[[HTMLText alloc] initWithData:@"b"]];
HTMLElement *c = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"c"}];
[div appendNode:c];
HTMLElement *d = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"d"}];
[c appendNode:d];
[c appendNode:[[HTMLComment alloc] initWithData:@"j"]];
[d appendNode:[[HTMLText alloc] initWithData:@"e"]];
HTMLElement *f = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"f"}];
[d appendNode:f];
[d appendNode:[[HTMLText alloc] initWithData:@"i"]];
[f appendNode:[[HTMLText alloc] initWithData:@"g"]];
[f appendNode:[[HTMLComment alloc] initWithData:@"h"]];
return div;
}
- (void)testBasicWalking
{
HTMLNode *root = self.basicWalkingDOM;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root];
HTMLNode *f = root.lastChild.firstChild.childNodes[1];
AssertElementWithId(walker.currentNode, @"a");
XCTAssertNil(walker.parentNode);
AssertElementWithId(walker.currentNode, @"a");
AssertTextWithValue(walker.firstChild, @"b");
AssertTextWithValue(walker.currentNode, @"b");
AssertElementWithId(walker.nextSibling, @"c");
AssertElementWithId(walker.currentNode, @"c");
AssertCommentWithValue(walker.lastChild, @"j");
AssertCommentWithValue(walker.currentNode, @"j");
AssertElementWithId(walker.previousSibling, @"d");
AssertElementWithId(walker.currentNode, @"d");
AssertTextWithValue(walker.nextNode, @"e");
AssertTextWithValue(walker.currentNode, @"e");
AssertElementWithId(walker.parentNode, @"d");
AssertElementWithId(walker.currentNode, @"d");
AssertElementWithId(walker.previousNode, @"c");
AssertElementWithId(walker.currentNode, @"c");
XCTAssertNil(walker.nextSibling);
AssertElementWithId(walker.currentNode, @"c");
walker.currentNode = f;
XCTAssertEqualObjects(walker.currentNode, f);
}
#pragma mark - Current Node
- (HTMLDocument *)currentNodeDOM
{
HTMLDocument *document = [HTMLDocument documentWithString:
@"<div id='first'><p><a></a></p></div>"
@"<div id='second'><p><b></b></p</div>"];
return document;
}
- (void)testThatTreeWalkerParentHasNoEffectCurrentNodeWhenParentIsNotUnderRoot
{
HTMLDocument *document = self.currentNodeDOM;
HTMLNode *first = document.body.firstChild;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:first
showOptions:HTMLNodeFilterShowElement
filter:nil];
AssertElementWithId(walker.currentNode, @"first");
XCTAssertNil(walker.parentNode);
AssertElementWithId(walker.currentNode, @"first");
}
- (void)testThatSettingCurrentNodeToNodesNotUnderRootIsHandledCorrectly
{
HTMLDocument *document = self.currentNodeDOM;
HTMLNode *first = document.body.firstChild;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:first
showOptions:HTMLNodeFilterShowElement|HTMLNodeFilterShowComment
filter:nil];
walker.currentNode = document.documentElement;
XCTAssertNil(walker.parentNode);
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
walker.currentNode = document.documentElement;
XCTAssertEqualObjects(walker.nextNode, document.documentElement.firstChild);
XCTAssertEqualObjects(walker.currentNode, document.documentElement.firstChild);
walker.currentNode = document.documentElement;
XCTAssertNil(walker.previousNode);
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
walker.currentNode = document.documentElement;
XCTAssertEqualObjects(walker.firstChild, document.documentElement.firstChild);
XCTAssertEqualObjects(walker.currentNode, document.documentElement.firstChild);
walker.currentNode = document.documentElement;
XCTAssertEqualObjects(walker.lastChild, document.documentElement.lastChild);
XCTAssertEqualObjects(walker.currentNode, document.documentElement.lastChild);
walker.currentNode = document.documentElement;
XCTAssertNil(walker.nextSibling);
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
walker.currentNode = document.documentElement;
XCTAssertNil(walker.previousSibling);
XCTAssertEqualObjects(walker.currentNode, document.documentElement);
}
#pragma mark - Filter
- (HTMLElement *)filterBasicDOM
{
HTMLElement *root = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"root"}];
HTMLElement *a1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"A1"}];
HTMLElement *b1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B1"}];
HTMLElement *b2 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B2"}];
[root appendNode:a1];
[a1 appendNode:b1];
[a1 appendNode:b2];
return root;
}
- (void)testTreeWalkerNilFilter
{
HTMLElement *root = self.filterBasicDOM;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:nil];
AssertElementWithId(walker.currentNode, @"root");
AssertElementWithId(walker.firstChild, @"A1");
AssertElementWithId(walker.currentNode, @"A1");
AssertElementWithId(walker.nextNode, @"B1");
AssertElementWithId(walker.currentNode, @"B1");
}
- (void)testTreeWalkerWithFilter
{
HTMLElement *root = self.filterBasicDOM;
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
if ([node.asElement[@"id"] isEqualToString:@"B1"]) {
return HTMLNodeFilterSkip;
}
return HTMLNodeFilterAccept;
}];
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
AssertElementWithId(walker.currentNode, @"root");
AssertElementWithId(walker.firstChild, @"A1");
AssertElementWithId(walker.currentNode, @"A1");
AssertElementWithId(walker.nextNode, @"B2");
AssertElementWithId(walker.currentNode, @"B2");
}
#pragma mark - Filter Skip
- (HTMLElement *)filterDOM
{
HTMLElement *root = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"root"}];
HTMLElement *a1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"A1"}];
HTMLElement *b1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B1"}];
HTMLElement *b2 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B2"}];
HTMLElement *b3 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"B3"}];
HTMLElement *c1 = [[HTMLElement alloc] initWithTagName:@"div" attributes:@{@"id": @"C1"}];
[root appendNode:a1];
[a1 appendNode:b1];
[a1 appendNode:b2];
[a1 appendNode:b3];
[b1 appendNode:c1];
return root;
}
- (id<HTMLNodeFilter>)skipB1Filter
{
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
if ([node.asElement[@"id"] isEqualToString:@"B1"]) {
return HTMLNodeFilterSkip;
}
return HTMLNodeFilterAccept;
}];
return filter;
}
- (id<HTMLNodeFilter>)skipB2Filter
{
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
if ([node.asElement[@"id"] isEqualToString:@"B2"]) {
return HTMLNodeFilterSkip;
}
return HTMLNodeFilterAccept;
}];
return filter;
}
- (id<HTMLNodeFilter>)rejectB1Filter
{
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
if ([node.asElement[@"id"] isEqualToString:@"B1"]) {
return HTMLNodeFilterReject;
}
return HTMLNodeFilterAccept;
}];
return filter;
}
- (id<HTMLNodeFilter>)rejectB2Filter
{
id<HTMLNodeFilter> filter = [HTMLNodeFilterBlock filterWithBlock:^HTMLNodeFilterValue(HTMLNode *node) {
if ([node.asElement[@"id"] isEqualToString:@"B2"]) {
return HTMLNodeFilterReject;
}
return HTMLNodeFilterAccept;
}];
return filter;
}
static HTMLElement * (^ FindElementById)(HTMLNode *, NSString *) = ^ HTMLElement * (HTMLNode *root, NSString *id) {
for (HTMLNode *node in [root nodeIteratorWithShowOptions:HTMLNodeFilterShowElement filter:nil]) {
if ([node.asElement[@"id"] isEqualToString:id]) {
return node.asElement;
}
}
return nil;
};
- (void)testThatFilterSkipsNextNode
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.skipB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
AssertElementWithId(walker.nextNode, @"A1");
AssertElementWithId(walker.nextNode, @"C1");
AssertElementWithId(walker.nextNode, @"B2");
AssertElementWithId(walker.nextNode, @"B3");
}
- (void)testThatFilterSkipsFirstChild
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.skipB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
AssertElementWithId(walker.firstChild, @"A1");
AssertElementWithId(walker.firstChild, @"C1");
}
- (void)testThatFilterSkipsNextSibling
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.skipB2Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
AssertElementWithId(walker.firstChild, @"A1");
AssertElementWithId(walker.firstChild, @"B1");
AssertElementWithId(walker.nextSibling, @"B3");
}
- (void)testThatFilterSkipsParentNode
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.skipB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
walker.currentNode = FindElementById(root, @"C1");
AssertElementWithId(walker.parentNode, @"A1");
}
- (void)testThatFilterSkipsPreviousSibling
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.skipB2Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
walker.currentNode = FindElementById(root, @"B3");
AssertElementWithId(walker.previousSibling, @"B1");
}
- (void)testThatFilterSkipsPreviousNode
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.skipB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
walker.currentNode = FindElementById(root, @"B3");
AssertElementWithId(walker.previousNode, @"B2");
AssertElementWithId(walker.previousNode, @"C1");
AssertElementWithId(walker.previousNode, @"A1");
}
#pragma mark - Filter Reject
- (void)testThatFilterRejectsNextNode
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.rejectB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
AssertElementWithId(walker.nextNode, @"A1");
AssertElementWithId(walker.nextNode, @"B2");
AssertElementWithId(walker.nextNode, @"B3");
}
- (void)testThatFilterRejectsFirstChild
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.rejectB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
AssertElementWithId(walker.firstChild, @"A1");
AssertElementWithId(walker.firstChild, @"B2");
}
- (void)testThatFilterRejectsNextSibling
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.rejectB2Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
AssertElementWithId(walker.firstChild, @"A1");
AssertElementWithId(walker.firstChild, @"B1");
AssertElementWithId(walker.nextSibling, @"B3");
}
- (void)testThatFilterRejectsParentNode
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.rejectB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
walker.currentNode = FindElementById(root, @"C1");
AssertElementWithId(walker.parentNode, @"A1");
}
- (void)testThatFilterRejectsPreviousSibling
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.rejectB2Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
walker.currentNode = FindElementById(root, @"B3");
AssertElementWithId(walker.previousSibling, @"B1");
}
- (void)testThatFilterRejectsPreviousNode
{
HTMLElement *root = self.filterDOM;
id<HTMLNodeFilter> filter = self.rejectB1Filter;
HTMLTreeWalker *walker = [[HTMLTreeWalker alloc] initWithNode:root
showOptions:HTMLNodeFilterShowElement
filter:filter];
walker.currentNode = FindElementById(root, @"B3");
AssertElementWithId(walker.previousNode, @"B2");
AssertElementWithId(walker.previousNode, @"A1");
}
@end