diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj index f1cd70e..f4e0e6f 100644 --- a/HTMLKit.xcodeproj/project.pbxproj +++ b/HTMLKit.xcodeproj/project.pbxproj @@ -78,6 +78,10 @@ 62491C471AFE51F100ACF9E2 /* CSSLexer.c in Sources */ = {isa = PBXBuildFile; fileRef = 62491C451AFE51F100ACF9E2 /* CSSLexer.c */; }; 62491C481AFE51F100ACF9E2 /* CSSLexer.c in Sources */ = {isa = PBXBuildFile; fileRef = 62491C451AFE51F100ACF9E2 /* CSSLexer.c */; }; 62491C491AFE51F100ACF9E2 /* CSSLexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 62491C461AFE51F100ACF9E2 /* CSSLexer.h */; }; + 624AB3171B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */; }; + 624AB3181B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */; }; + 624AB31A1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */; }; + 624AB31B1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */; }; 624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = 624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */; }; 624AC90119FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */; }; 624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */; }; @@ -238,6 +242,8 @@ 62491C451AFE51F100ACF9E2 /* CSSLexer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CSSLexer.c; sourceTree = ""; }; 62491C461AFE51F100ACF9E2 /* CSSLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSLexer.h; sourceTree = ""; }; 624AB3151B04EA4200F3830D /* CSSSelectors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSSelectors.h; sourceTree = ""; }; + 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSTypeSelectorTests.m; sourceTree = ""; }; + 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSAttributeSelectorTests.m; sourceTree = ""; }; 624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokens.h; sourceTree = ""; }; 624AC90019FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitTokenizerTests.m; sourceTree = ""; }; 624AC90419FBFE8A00BD3C4A /* html5lib-tests */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "html5lib-tests"; sourceTree = ""; }; @@ -501,6 +507,8 @@ 624B9FB71AE072CB00646C4C /* Nodes */, 624B9FB81AE072D500646C4C /* Categories */, 625A14CB19C7829400AD0C32 /* Supporting Files */, + 624AB3161B0508AE00F3830D /* CSSTypeSelectorTests.m */, + 624AB3191B050A4D00F3830D /* CSSAttributeSelectorTests.m */, ); name = Tests; path = HTMLKitTests; @@ -828,7 +836,9 @@ 6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */, 623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */, 62EC7AE71AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */, + 624AB31B1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */, 624B9FB61AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */, + 624AB3181B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */, 6236738F1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */, 624AC90219FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */, 624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */, @@ -886,7 +896,9 @@ 6239755A1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */, 623CAF9D1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */, 62EC7AE61AEEAC6F0015D3BE /* HTMLKitMutationAlgorithmsTests.m in Sources */, + 624AB31A1B050A4D00F3830D /* CSSAttributeSelectorTests.m in Sources */, 624B9FB51AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */, + 624AB3171B0508AE00F3830D /* CSSTypeSelectorTests.m in Sources */, 6236738E1AC0CE2500FF89B3 /* HTMLKitTokenizerPerformance.m in Sources */, 624AC90119FBF9ED00BD3C4A /* HTMLKitTokenizerTests.m in Sources */, 624B9FB21AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */, diff --git a/HTMLKit/CSSSelectors.h b/HTMLKit/CSSSelectors.h index fd583d6..30d21f3 100644 --- a/HTMLKit/CSSSelectors.h +++ b/HTMLKit/CSSSelectors.h @@ -6,8 +6,6 @@ // Copyright (c) 2015 BrainCookie. All rights reserved. // -#ifndef HTMLKit_CSSSelectors_h -#define HTMLKit_CSSSelectors_h - - -#endif +#import "CSSSelector.h" +#import "CSSTypeSelector.h" +#import "CSSAttributeSelector.h" diff --git a/HTMLKitTests/CSSAttributeSelectorTests.m b/HTMLKitTests/CSSAttributeSelectorTests.m new file mode 100644 index 0000000..2b8357e --- /dev/null +++ b/HTMLKitTests/CSSAttributeSelectorTests.m @@ -0,0 +1,210 @@ +// +// CSSAttributeSelectorTests.m +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelectors.h" +#import "HTMLNodes.h" + +@interface CSSAttributeSelectorTests : XCTestCase +{ + HTMLElement *_element; +} +@end + +@implementation CSSAttributeSelectorTests + +- (void)setUp +{ + [super setUp]; + _element = [[HTMLElement alloc] initWithTagName:@"div"]; +} + +- (void)testAttributeExists +{ + CSSAttributeSelector *selector = [[CSSAttributeSelector alloc] initWithType:CSSAttributeSelectorExists + attributeName:@"attr" + attrbiuteValue:@""]; + + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"class"] = @"class"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"value 2"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"value 3"; + XCTAssertTrue([selector acceptNode:_element]); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertFalse([selector acceptNode:_element]); +} + +- (void)testAttributeExactMatch +{ + CSSAttributeSelector *selector = [[CSSAttributeSelector alloc] initWithType:CSSAttributeSelectorExactMatch + attributeName:@"attr" + attrbiuteValue:@"value"]; + + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"class"] = @"class"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value 1"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value 2"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value 3"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value"; + XCTAssertTrue([selector acceptNode:_element]); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertFalse([selector acceptNode:_element]); +} + +- (void)testAttributeIncludes +{ + CSSAttributeSelector *selector = [[CSSAttributeSelector alloc] initWithType:CSSAttributeSelectorIncludes + attributeName:@"attr" + attrbiuteValue:@"value"]; + + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"class"] = @"class"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"a b value"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"a value b"; + XCTAssertTrue([selector acceptNode:_element]); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertFalse([selector acceptNode:_element]); +} + +- (void)testAttributeBegins +{ + CSSAttributeSelector *selector = [[CSSAttributeSelector alloc] initWithType:CSSAttributeSelectorBegins + attributeName:@"attr" + attrbiuteValue:@"value"]; + + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"class"] = @"class"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"val"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"a value"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"values"; + XCTAssertTrue([selector acceptNode:_element]); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertFalse([selector acceptNode:_element]); +} + +- (void)testAttributeEnds +{ + CSSAttributeSelector *selector = [[CSSAttributeSelector alloc] initWithType:CSSAttributeSelectorEnds + attributeName:@"attr" + attrbiuteValue:@"value"]; + + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"class"] = @"class"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"val"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"a value"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"some-value"; + XCTAssertTrue([selector acceptNode:_element]); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertFalse([selector acceptNode:_element]); +} + +- (void)testAttributeContains +{ + CSSAttributeSelector *selector = [[CSSAttributeSelector alloc] initWithType:CSSAttributeSelectorContains + attributeName:@"attr" + attrbiuteValue:@"value"]; + + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"class"] = @"class"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"val"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"value"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"a value b"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"some-values"; + XCTAssertTrue([selector acceptNode:_element]); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertFalse([selector acceptNode:_element]); +} + +- (void)testAttributeHyphen +{ + CSSAttributeSelector *selector = [[CSSAttributeSelector alloc] initWithType:CSSAttributeSelectorHyphen + attributeName:@"attr" + attrbiuteValue:@"top"]; + + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"class"] = @"class"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"top_text"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"toptext"; + XCTAssertFalse([selector acceptNode:_element]); + + _element[@"attr"] = @"top"; + XCTAssertTrue([selector acceptNode:_element]); + + _element[@"attr"] = @"top-text"; + XCTAssertTrue([selector acceptNode:_element]); + + [_element.attributes removeObjectForKey:@"attr"]; + XCTAssertFalse([selector acceptNode:_element]); +} + +@end diff --git a/HTMLKitTests/CSSTypeSelectorTests.m b/HTMLKitTests/CSSTypeSelectorTests.m new file mode 100644 index 0000000..88f13fd --- /dev/null +++ b/HTMLKitTests/CSSTypeSelectorTests.m @@ -0,0 +1,51 @@ +// +// CSSTypeSelectorTests.m +// HTMLKit +// +// Created by Iska on 14/05/15. +// Copyright (c) 2015 BrainCookie. All rights reserved. +// + +#import +#import "CSSSelectors.h" +#import "HTMLNodes.h" + +@interface CSSTypeSelectorTests : XCTestCase + +@end + +@implementation CSSTypeSelectorTests + +- (void)testUniversalSelector +{ + CSSTypeSelector *selector = [CSSTypeSelector universalSelector]; + + XCTAssertFalse([selector acceptNode:[HTMLDocumentType new]]); + XCTAssertFalse([selector acceptNode:[HTMLDocumentFragment new]]); + XCTAssertFalse([selector acceptNode:[[HTMLText alloc] initWithData:@"Text"]]); + XCTAssertFalse([selector acceptNode:[[HTMLComment alloc] initWithData:@"Comment"]]); + + XCTAssertTrue([selector acceptNode:[[HTMLElement alloc] initWithTagName:nil]]); + XCTAssertTrue([selector acceptNode:[[HTMLElement alloc] initWithTagName:@""]]); + XCTAssertTrue([selector acceptNode:[[HTMLElement alloc] initWithTagName:@"div"]]); + XCTAssertTrue([selector acceptNode:[[HTMLElement alloc] initWithTagName:@"p"]]); + XCTAssertTrue([selector acceptNode:[[HTMLElement alloc] initWithTagName:@"any other name"]]); +} + +- (void)testTypeSelector +{ + CSSTypeSelector *selector = [[CSSTypeSelector alloc] initWithType:@"div"]; + + XCTAssertFalse([selector acceptNode:[HTMLDocumentType new]]); + XCTAssertFalse([selector acceptNode:[HTMLDocumentFragment new]]); + XCTAssertFalse([selector acceptNode:[[HTMLText alloc] initWithData:@"Text"]]); + XCTAssertFalse([selector acceptNode:[[HTMLComment alloc] initWithData:@"Comment"]]); + XCTAssertFalse([selector acceptNode:[[HTMLElement alloc] initWithTagName:nil]]); + XCTAssertFalse([selector acceptNode:[[HTMLElement alloc] initWithTagName:@""]]); + XCTAssertFalse([selector acceptNode:[[HTMLElement alloc] initWithTagName:@"p"]]); + XCTAssertFalse([selector acceptNode:[[HTMLElement alloc] initWithTagName:@"any other name"]]); + + XCTAssertTrue([selector acceptNode:[[HTMLElement alloc] initWithTagName:@"div"]]); +} + +@end