This commit is contained in:
Nabil Chatbi 2018-04-03 20:14:14 +02:00
parent 129eeed16c
commit 8e064ada23
6 changed files with 75 additions and 58 deletions

View File

@ -47,7 +47,7 @@ public class CombiningEvaluator: Evaluator {
} }
public final class And: CombiningEvaluator { public final class And: CombiningEvaluator {
public override init(_ evaluators: Array<Evaluator>) { public override init(_ evaluators: [Evaluator]) {
super.init(evaluators) super.init(evaluators)
} }
@ -56,10 +56,10 @@ public class CombiningEvaluator: Evaluator {
} }
public override func matches(_ root: Element, _ node: Element) -> Bool { public override func matches(_ root: Element, _ node: Element) -> Bool {
for i in 0..<num { for index in 0..<num {
let s = evaluators[i] let evaluator = evaluators[index]
do { do {
if (try !s.matches(root, node)) { if (try !evaluator.matches(root, node)) {
return false return false
} }
} catch {} } catch {}
@ -69,8 +69,8 @@ public class CombiningEvaluator: Evaluator {
} }
public override func toString() -> String { public override func toString() -> String {
let ar: [String] = evaluators.map { String($0.toString()) } let array: [String] = evaluators.map { String($0.toString()) }
return StringUtil.join(ar, sep: " ") return StringUtil.join(array, sep: " ")
} }
} }
@ -79,9 +79,9 @@ public class CombiningEvaluator: Evaluator {
* Create a new Or evaluator. The initial evaluators are ANDed together and used as the first clause of the OR. * Create a new Or evaluator. The initial evaluators are ANDed together and used as the first clause of the OR.
* @param evaluators initial OR clause (these are wrapped into an AND evaluator). * @param evaluators initial OR clause (these are wrapped into an AND evaluator).
*/ */
public override init(_ evaluators: Array<Evaluator>) { public override init(_ evaluators: [Evaluator]) {
super.init() super.init()
if (num > 1) { if num > 1 {
self.evaluators.append(And(evaluators)) self.evaluators.append(And(evaluators))
} else { // 0 or 1 } else { // 0 or 1
self.evaluators.append(contentsOf: evaluators) self.evaluators.append(contentsOf: evaluators)
@ -91,7 +91,7 @@ public class CombiningEvaluator: Evaluator {
override init(_ evaluators: Evaluator...) { override init(_ evaluators: Evaluator...) {
super.init() super.init()
if (num > 1) { if num > 1 {
self.evaluators.append(And(evaluators)) self.evaluators.append(And(evaluators))
} else { // 0 or 1 } else { // 0 or 1
self.evaluators.append(contentsOf: evaluators) self.evaluators.append(contentsOf: evaluators)
@ -103,16 +103,16 @@ public class CombiningEvaluator: Evaluator {
super.init() super.init()
} }
public func add(_ e: Evaluator) { public func add(_ evaluator: Evaluator) {
evaluators.append(e) evaluators.append(evaluator)
updateNumEvaluators() updateNumEvaluators()
} }
public override func matches(_ root: Element, _ node: Element) -> Bool { public override func matches(_ root: Element, _ node: Element) -> Bool {
for i in 0..<num { for index in 0..<num {
let s: Evaluator = evaluators[i] let evaluator: Evaluator = evaluators[index]
do { do {
if (try s.matches(root, node)) { if (try evaluator.matches(root, node)) {
return true return true
} }
} catch {} } catch {}

View File

@ -387,7 +387,7 @@ public class Evaluator {
if let parent = element.parent() { if let parent = element.parent() {
let index = try element.elementSiblingIndex() let index = try element.elementSiblingIndex()
return !((parent as? Document) != nil) && index == (parent.getChildNodes().count - 1) return !(parent is Document) && index == (parent.getChildNodes().count - 1)
} }
return false return false
} }

View File

@ -19,33 +19,33 @@ class AttributeTest: XCTestCase {
#endif #endif
} }
func testHtml() { func testHtml()throws {
let attr = try! Attribute(key: "key", value: "value &") let attr = try Attribute(key: "key", value: "value &")
XCTAssertEqual("key=\"value &amp;\"", attr.html()) XCTAssertEqual("key=\"value &amp;\"", attr.html())
XCTAssertEqual(attr.html(), attr.toString()) XCTAssertEqual(attr.html(), attr.toString())
} }
func testWithSupplementaryCharacterInAttributeKeyAndValue() { func testWithSupplementaryCharacterInAttributeKeyAndValue()throws {
let s = "135361" let string = "135361"
let attr = try! Attribute(key: s, value: "A" + s + "B") let attr = try Attribute(key: string, value: "A" + string + "B")
XCTAssertEqual(s + "=\"A" + s + "B\"", attr.html()) XCTAssertEqual(string + "=\"A" + string + "B\"", attr.html())
XCTAssertEqual(attr.html(), attr.toString()) XCTAssertEqual(attr.html(), attr.toString())
} }
func testRemoveCaseSensitive()throws { func testRemoveCaseSensitive()throws {
let a: Attributes = Attributes() let atteibute: Attributes = Attributes()
try a.put("Tot", "a&p") try atteibute.put("Tot", "a&p")
try a.put("tot", "one") try atteibute.put("tot", "one")
try a.put("Hello", "There") try atteibute.put("Hello", "There")
try a.put("hello", "There") try atteibute.put("hello", "There")
try a.put("data-name", "Jsoup") try atteibute.put("data-name", "Jsoup")
XCTAssertEqual(5, a.size()) XCTAssertEqual(5, atteibute.size())
try a.remove(key: "Tot") try atteibute.remove(key: "Tot")
try a.remove(key: "Hello") try atteibute.remove(key: "Hello")
XCTAssertEqual(3, a.size()) XCTAssertEqual(3, atteibute.size())
XCTAssertTrue(a.hasKey(key: "tot")) XCTAssertTrue(atteibute.hasKey(key: "tot"))
XCTAssertFalse(a.hasKey(key: "Tot")) XCTAssertFalse(atteibute.hasKey(key: "Tot"))
} }
static var allTests = { static var allTests = {

View File

@ -60,8 +60,8 @@ class CssTest: XCTestCase {
} }
func testLastChild()throws { func testLastChild()throws {
try check(html.select("#pseudo :last-child"), "10") try! check(html.select("#pseudo :last-child"), "10")
try check(html.select("html:last-child")) try! check(html.select("html:last-child"))
} }
func testNthChild_simple()throws { func testNthChild_simple()throws {

View File

@ -24,12 +24,16 @@ class QueryParserTest: XCTestCase {
// tests that a selector "a b, c d, e f" evals to (a AND b) OR (c AND d) OR (e AND f)" // tests that a selector "a b, c d, e f" evals to (a AND b) OR (c AND d) OR (e AND f)"
// top level or, three child ands // top level or, three child ands
let eval: Evaluator = try QueryParser.parse("a b, c d, e f") let eval: Evaluator = try QueryParser.parse("a b, c d, e f")
XCTAssertTrue((eval as? CombiningEvaluator.Or) != nil) guard let orEvaluator = eval as? CombiningEvaluator.Or else {
let or: CombiningEvaluator.Or = eval as! CombiningEvaluator.Or XCTAssertTrue(false)
XCTAssertEqual(3, or.evaluators.count) return
for innerEval: Evaluator in or.evaluators { }
XCTAssertTrue((innerEval as? CombiningEvaluator.And) != nil) XCTAssertEqual(3, orEvaluator.evaluators.count)
let and: CombiningEvaluator.And = innerEval as! CombiningEvaluator.And for innerEval: Evaluator in orEvaluator.evaluators {
guard let and: CombiningEvaluator.And = innerEval as? CombiningEvaluator.And else {
XCTAssertTrue(false)
return
}
XCTAssertEqual(2, and.evaluators.count) XCTAssertEqual(2, and.evaluators.count)
XCTAssertTrue((and.evaluators[0] as? Evaluator.Tag) != nil) XCTAssertTrue((and.evaluators[0] as? Evaluator.Tag) != nil)
XCTAssertTrue((and.evaluators[1] as? StructuralEvaluator.Parent) != nil) XCTAssertTrue((and.evaluators[1] as? StructuralEvaluator.Parent) != nil)
@ -38,12 +42,19 @@ class QueryParserTest: XCTestCase {
func testParsesMultiCorrectly()throws { func testParsesMultiCorrectly()throws {
let eval: Evaluator = try QueryParser.parse(".foo > ol, ol > li + li") let eval: Evaluator = try QueryParser.parse(".foo > ol, ol > li + li")
XCTAssertTrue((eval as? CombiningEvaluator.Or) != nil) guard let orEvaluator: CombiningEvaluator.Or = eval as? CombiningEvaluator.Or else {
let or: CombiningEvaluator.Or = eval as! CombiningEvaluator.Or XCTAssertTrue(false)
XCTAssertEqual(2, or.evaluators.count) return
}
let andLeft: CombiningEvaluator.And = or.evaluators[0] as! CombiningEvaluator.And XCTAssertEqual(2, orEvaluator.evaluators.count)
let andRight: CombiningEvaluator.And = or.evaluators[1] as! CombiningEvaluator.And guard let andLeft: CombiningEvaluator.And = orEvaluator.evaluators[0] as? CombiningEvaluator.And else {
XCTAssertTrue(false)
return
}
guard let andRight: CombiningEvaluator.And = orEvaluator.evaluators[1] as? CombiningEvaluator.And else {
XCTAssertTrue(false)
return
}
XCTAssertEqual("ol :ImmediateParent.foo", andLeft.toString()) XCTAssertEqual("ol :ImmediateParent.foo", andLeft.toString())
XCTAssertEqual(2, andLeft.evaluators.count) XCTAssertEqual(2, andLeft.evaluators.count)

View File

@ -22,24 +22,25 @@ class XmlTreeBuilderTest: XCTestCase {
func testSimpleXmlParse()throws { func testSimpleXmlParse()throws {
let xml = "<doc id=2 href='/bar'>Foo <br /><link>One</link><link>Two</link></doc>" let xml = "<doc id=2 href='/bar'>Foo <br /><link>One</link><link>Two</link></doc>"
let tb: XmlTreeBuilder = XmlTreeBuilder() let treeBuilder: XmlTreeBuilder = XmlTreeBuilder()
let doc: Document = try tb.parse(xml, "http://foo.com/") let doc: Document = try treeBuilder.parse(xml, "http://foo.com/")
XCTAssertEqual("<doc id=\"2\" href=\"/bar\">Foo <br /><link>One</link><link>Two</link></doc>", try TextUtil.stripNewlines(doc.html())) XCTAssertEqual("<doc id=\"2\" href=\"/bar\">Foo <br /><link>One</link><link>Two</link></doc>",
try TextUtil.stripNewlines(doc.html()))
XCTAssertEqual(try doc.getElementById("2")?.absUrl("href"), "http://foo.com/bar") XCTAssertEqual(try doc.getElementById("2")?.absUrl("href"), "http://foo.com/bar")
} }
func testPopToClose()throws { func testPopToClose()throws {
// test: </val> closes Two, </bar> ignored // test: </val> closes Two, </bar> ignored
let xml = "<doc><val>One<val>Two</val></bar>Three</doc>" let xml = "<doc><val>One<val>Two</val></bar>Three</doc>"
let tb: XmlTreeBuilder = XmlTreeBuilder() let treeBuilder: XmlTreeBuilder = XmlTreeBuilder()
let doc = try tb.parse(xml, "http://foo.com/") let doc = try treeBuilder.parse(xml, "http://foo.com/")
XCTAssertEqual("<doc><val>One<val>Two</val>Three</val></doc>", try TextUtil.stripNewlines(doc.html())) XCTAssertEqual("<doc><val>One<val>Two</val>Three</val></doc>", try TextUtil.stripNewlines(doc.html()))
} }
func testCommentAndDocType()throws { func testCommentAndDocType()throws {
let xml = "<!DOCTYPE HTML><!-- a comment -->One <qux />Two" let xml = "<!DOCTYPE HTML><!-- a comment -->One <qux />Two"
let tb: XmlTreeBuilder = XmlTreeBuilder() let treeBuilder: XmlTreeBuilder = XmlTreeBuilder()
let doc = try tb.parse(xml, "http://foo.com/") let doc = try treeBuilder.parse(xml, "http://foo.com/")
XCTAssertEqual("<!DOCTYPE HTML><!-- a comment -->One <qux />Two", try TextUtil.stripNewlines(doc.html())) XCTAssertEqual("<!DOCTYPE HTML><!-- a comment -->One <qux />Two", try TextUtil.stripNewlines(doc.html()))
} }
@ -79,7 +80,8 @@ class XmlTreeBuilderTest: XCTestCase {
// } // }
func testDoesNotForceSelfClosingKnownTags()throws { func testDoesNotForceSelfClosingKnownTags()throws {
// html will force "<br>one</br>" to logically "<br />One<br />". XML should be stay "<br>one</br> -- don't recognise tag. // html will force "<br>one</br>" to logically "<br />One<br />".
// XML should be stay "<br>one</br> -- don't recognise tag.
let htmlDoc = try SwiftSoup.parse("<br>one</br>") let htmlDoc = try SwiftSoup.parse("<br>one</br>")
XCTAssertEqual("<br>one\n<br>", try htmlDoc.body()?.html()) XCTAssertEqual("<br>one\n<br>", try htmlDoc.body()?.html())
@ -90,14 +92,15 @@ class XmlTreeBuilderTest: XCTestCase {
func testHandlesXmlDeclarationAsDeclaration()throws { func testHandlesXmlDeclarationAsDeclaration()throws {
let html = "<?xml encoding='UTF-8' ?><body>One</body><!-- comment -->" let html = "<?xml encoding='UTF-8' ?><body>One</body><!-- comment -->"
let doc = try SwiftSoup.parse(html, "", Parser.xmlParser()) let doc = try SwiftSoup.parse(html, "", Parser.xmlParser())
try XCTAssertEqual("<?xml encoding=\"UTF-8\"?> <body> One </body> <!-- comment -->", StringUtil.normaliseWhitespace(doc.outerHtml())) try XCTAssertEqual("<?xml encoding=\"UTF-8\"?> <body> One </body> <!-- comment -->",
StringUtil.normaliseWhitespace(doc.outerHtml()))
XCTAssertEqual("#declaration", doc.childNode(0).nodeName()) XCTAssertEqual("#declaration", doc.childNode(0).nodeName())
XCTAssertEqual("#comment", doc.childNode(2).nodeName()) XCTAssertEqual("#comment", doc.childNode(2).nodeName())
} }
func testXmlFragment()throws { func testXmlFragment()throws {
let xml = "<one src='/foo/' />Two<three><four /></three>" let xml = "<one src='/foo/' />Two<three><four /></three>"
let nodes: Array<Node> = try Parser.parseXmlFragment(xml, "http://example.com/") let nodes: [Node] = try Parser.parseXmlFragment(xml, "http://example.com/")
XCTAssertEqual(3, nodes.count) XCTAssertEqual(3, nodes.count)
try XCTAssertEqual("http://example.com/foo/", nodes[0].absUrl("src")) try XCTAssertEqual("http://example.com/foo/", nodes[0].absUrl("src"))
@ -128,7 +131,10 @@ class XmlTreeBuilderTest: XCTestCase {
func testParseDeclarationAttributes()throws { func testParseDeclarationAttributes()throws {
let xml = "<?xml version='1' encoding='UTF-8' something='else'?><val>One</val>" let xml = "<?xml version='1' encoding='UTF-8' something='else'?><val>One</val>"
let doc = try SwiftSoup.parse(xml, "", Parser.xmlParser()) let doc = try SwiftSoup.parse(xml, "", Parser.xmlParser())
let decl: XmlDeclaration = doc.childNode(0) as! XmlDeclaration guard let decl: XmlDeclaration = doc.childNode(0) as? XmlDeclaration else {
XCTAssertTrue(false)
return
}
try XCTAssertEqual("1", decl.attr("version")) try XCTAssertEqual("1", decl.attr("version"))
try XCTAssertEqual("UTF-8", decl.attr("encoding")) try XCTAssertEqual("UTF-8", decl.attr("encoding"))
try XCTAssertEqual("else", decl.attr("something")) try XCTAssertEqual("else", decl.attr("something"))