+#import "CSSSelectors.h"
+#import "HTMLParser.h"
+#import "HTMLDOM.h"
+
+@interface CSSNThExpressionSelectorTests : XCTestCase
+{
+ HTMLDocument *_childTree;
+ HTMLDocument *_typeTree;
+}
+@end
+
+@implementation CSSNThExpressionSelectorTests
+
+- (void)setUp
+{
+ [super setUp];
+
+ /*
+ |
+ |
+ | | 11 |
+ | | 12 |
+ | | 13 |
+ | | 14 |
+ |
+ |
+ |
+ |
+ |
+ | | 31 |
+ | | 32 |
+ | | 33 |
+ | | 34 |
+ | | 35 |
+ | | 36 |
+ |
+ |
+ */
+ _childTree = [[[HTMLParser alloc] initWithString:@""
+ "| 11 |
"
+ "| 12 |
"
+ "| 13 |
"
+ "| 14 |
"
+ "
"
+ ""
+ ""
+ "| 31 |
"
+ "| 32 |
"
+ "| 33 |
"
+ "| 34 |
"
+ "| 35 |
"
+ "| 36 |
"
+ "
"] document];
+
+ /*
+ |
+ | s11
+ | s12
+ | s13
+ | b1
+ |
+ |
+ | b2
+ | s21
+ | s22
+ | s23
+ |
+ |
+ | s31
+ | b3
+ | s32
+ | b4
+ | s33
+ | b5
+ | s34
+ |
+ */
+ _typeTree = [[[HTMLParser alloc] initWithString:@""
+ "s11"
+ "s12"
+ "s13"
+ "b1"
+ "
"
+ ""
+ "b2"
+ "s21"
+ "s22"
+ "s23"
+ "
"
+ ""
+ "s31"
+ "b3"
+ "s32"
+ "b4"
+ "s33"
+ "b5"
+ "s34"
+ "
"] document];
+}
+
+- (void)testOddSelector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), oddSelector()])];
+ NSArray *expected = @[@"11", @"13", @"21", @"31", @"33", @"35"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)testEvenSelector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), evenSlector()])];
+ NSArray *expected = @[@"12", @"14", @"32", @"34", @"36"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)testFirstChildSelector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), firstChildSelector()])];
+ NSArray *expected = @[@"11", @"21", @"31"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)testLastChildSelector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), lastChildSelector()])];
+ NSArray *expected = @[@"14", @"21", @"36"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)testFirstOfTypeSelector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), firstOfTypeSelector()])];
+ NSArray *expected = @[@"s11", @"s21", @"s31"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)testLastOfTypeSelector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), lastOfTypeSelector()])];
+ NSArray *expected = @[@"s13", @"s23", @"s34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)testOnlyChildSelector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), onlyChildSelector()])];
+ NSArray *expected = @[@"21"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)testOnlyOfTypeSelector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), onlyOfTypeSelector()])];
+ NSArray *expected = @[];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), onlyOfTypeSelector()])];
+ expected = @[];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"b"), onlyOfTypeSelector()])];
+ expected = @[@"b1", @"b2"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+#pragma mark - Nth-Child Selector
+
+- (void)test_NthChild_B_Selector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(0, 1))])];
+ NSArray *expected = @[@"11", @"21", @"31"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(0, 2))])];
+ expected = @[@"12", @"32"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(0, 3))])];
+ expected = @[@"13", @"33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthChild_An_Selector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(2, 0))])];
+ NSArray *expected = @[@"12", @"14", @"32", @"34", @"36"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(3, 0))])];
+ expected = @[@"13", @"33", @"36"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(4, 0))])];
+ expected = @[@"14", @"34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthChild_An_B_Selector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(3, 1))])];
+ NSArray *expected = @[@"11", @"14", @"21", @"31", @"34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthChildSelector(CSSNthExpressionMake(3, 2))])];
+ expected = @[@"12", @"32", @"35"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+#pragma mark - Nth-Last-Child Selector
+
+- (void)test_NthLastChild_B_Selector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(0, 1))])];
+ NSArray *expected = @[@"14", @"21", @"36"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(0, 2))])];
+ expected = @[@"13", @"35"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(0, 3))])];
+ expected = @[@"12", @"34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthLastChild_An_Selector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(2, 0))])];
+ NSArray *expected = @[@"11", @"13", @"31", @"33", @"35"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(3, 0))])];
+ expected = @[@"12", @"31", @"34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(4, 0))])];
+ expected = @[@"11", @"33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthLastChild_An_B_Selector
+{
+ NSArray *elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(3, 1))])];
+ NSArray *expected = @[@"11", @"14", @"21", @"33", @"36"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_childTree elementsMatchingSelector:allOf(@[typeSelector(@"tr"), nthLastChildSelector(CSSNthExpressionMake(3, 2))])];
+ expected = @[@"13", @"32", @"35"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+#pragma mark - Nth-Of-Type Selector
+
+- (void)test_NthOfType_B_Selector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(0, 1))])];
+ NSArray *expected = @[@"s11", @"s21", @"s31"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(0, 2))])];
+ expected = @[@"s12", @"s22", @"s32"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(0, 3))])];
+ expected = @[@"s13", @"s23", @"s33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthOfType_An_Selector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(2, 0))])];
+ NSArray *expected = @[@"s12", @"s22", @"s32", @"s34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(3, 0))])];
+ expected = @[@"s13", @"s23", @"s33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(4, 0))])];
+ expected = @[@"s34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthOfType_An_B_Selector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(2, 1))])];
+ NSArray *expected = @[@"s11", @"s13", @"s21", @"s23", @"s31", @"s33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthOfTypeSelector(CSSNthExpressionMake(2, 2))])];
+ expected = @[@"s12", @"s22", @"s32", @"s34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+#pragma mark - Nth-Last-Of-Type Selector
+
+- (void)test_NthLastOfType_B_Selector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(0, 1))])];
+ NSArray *expected = @[@"s13", @"s23", @"s34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(0, 2))])];
+ expected = @[@"s12", @"s22", @"s33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(0, 3))])];
+ expected = @[@"s11", @"s21", @"s32"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthLastOfType_An_Selector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(2, 0))])];
+ NSArray *expected = @[@"s12", @"s22", @"s31", @"s33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(3, 0))])];
+ expected = @[@"s11", @"s21", @"s32"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(4, 0))])];
+ expected = @[@"s31"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+- (void)test_NthLastOfType_An_B_Selector
+{
+ NSArray *elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(2, 1))])];
+ NSArray *expected = @[@"s11", @"s13", @"s21", @"s23", @"s32", @"s34"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+
+ elements = [_typeTree elementsMatchingSelector:allOf(@[typeSelector(@"span"), nthLastOfTypeSelector(CSSNthExpressionMake(2, 2))])];
+ expected = @[@"s12", @"s22", @"s31", @"s33"];
+ XCTAssertEqualObjects([elements valueForKeyPath:@"attributes.id"], expected);
+}
+
+@end