diff --git a/README.md b/README.md
index 9340382..2790f1b 100644
--- a/README.md
+++ b/README.md
@@ -72,7 +72,7 @@ Taken from example_test.go:
// remove the leading "x" before Output on the next line. This will cause the
// example to fail (all the "real" tests should pass).
- // xOutput: volutarily fail the Example output.
+ // xOutput: voluntarily fail the Example output.
}
diff --git a/example_test.go b/example_test.go
index 97abe19..3867ca3 100644
--- a/example_test.go
+++ b/example_test.go
@@ -38,5 +38,5 @@ func ExampleScrape_MetalReview() {
// remove the leading "x" before Output on the next line. This will cause the
// example to fail (all the "real" tests should pass).
- // xOutput: volutarily fail the Example output.
+ // xOutput: voluntarily fail the Example output.
}
diff --git a/property_test.go b/property_test.go
index 8257ff6..80882cb 100644
--- a/property_test.go
+++ b/property_test.go
@@ -7,8 +7,6 @@ import (
)
func TestAttrExists(t *testing.T) {
- EnsureDocLoaded()
-
if val, ok := Doc().Root.Find("a").Attr("href"); !ok {
t.Error("Expected a value for the href attribute.")
} else {
diff --git a/testdata/page2.html b/testdata/page2.html
new file mode 100644
index 0000000..66ea563
--- /dev/null
+++ b/testdata/page2.html
@@ -0,0 +1,16 @@
+
+
+
+ Tests for siblings
+
+
+
+
+
diff --git a/traversal.go b/traversal.go
index 0a4e8ef..5b6ef49 100644
--- a/traversal.go
+++ b/traversal.go
@@ -228,6 +228,24 @@ func (this *Selection) PrevUntil(selector string) *Selection {
selector, nil))
}
+// PrevUntilSelection() gets all preceding siblings of each element up to but not
+// including the element matched by the Selection. It returns a new Selection
+// object containing the matched elements.
+func (this *Selection) PrevUntilSelection(sel *Selection) *Selection {
+ if sel == nil {
+ return this.PrevAll()
+ }
+ return this.PrevUntilNodes(sel.Nodes...)
+}
+
+// PrevUntilNodes() gets all preceding siblings of each element up to but not
+// including the element matched by the nodes. It returns a new Selection
+// object containing the matched elements.
+func (this *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
+ return pushStack(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
+ "", nodes))
+}
+
// Filter and push filters the nodes based on a selector, and pushes the results
// on the stack, with the srcSel as previous selection.
func filterAndPush(srcSel *Selection, nodes []*html.Node, selector string) *Selection {
diff --git a/traversal_test.go b/traversal_test.go
index a7c846e..00471da 100644
--- a/traversal_test.go
+++ b/traversal_test.go
@@ -439,3 +439,40 @@ func TestPrevUntilRollback(t *testing.T) {
sel2 := sel.PrevUntil("#cf2-1").End()
AssertEqual(t, sel, sel2)
}
+
+func TestPrevUntilSelection(t *testing.T) {
+ sel := Doc2().Root.Find("#n4")
+ sel2 := Doc2().Root.Find("#n2")
+ sel2 = sel.PrevUntilSelection(sel2)
+ AssertLength(t, sel2.Nodes, 1)
+ if !sel2.Eq(0).Is("#n3") {
+ t.Errorf("Expected node 0 to be n3, found %+v.", sel2.Get(0))
+ }
+}
+
+func TestPrevUntilSelectionRollback(t *testing.T) {
+ sel := Doc2().Root.Find("#n4")
+ sel2 := Doc2().Root.Find("#n2")
+ sel2 = sel.PrevUntilSelection(sel2).End()
+ AssertEqual(t, sel, sel2)
+}
+
+func TestPrevUntilNodes(t *testing.T) {
+ sel := Doc2().Root.Find("#n5")
+ sel2 := Doc2().Root.Find("#n2")
+ sel2 = sel.PrevUntilNodes(sel2.Nodes...)
+ AssertLength(t, sel2.Nodes, 2)
+ if !sel2.Eq(0).Is("#n4") {
+ t.Errorf("Expected node 0 to be n4, found %+v.", sel2.Get(0))
+ }
+ if !sel2.Eq(1).Is("#n3") {
+ t.Errorf("Expected node 1 to be n3, found %+v.", sel2.Get(1))
+ }
+}
+
+func TestPrevUntilNodesRollback(t *testing.T) {
+ sel := Doc2().Root.Find("#n5")
+ sel2 := Doc2().Root.Find("#n2")
+ sel2 = sel.PrevUntilNodes(sel2.Nodes...).End()
+ AssertEqual(t, sel, sel2)
+}
diff --git a/type_test.go b/type_test.go
index da55224..336f9c1 100644
--- a/type_test.go
+++ b/type_test.go
@@ -2,19 +2,27 @@ package goquery
import (
"exp/html"
+ "fmt"
"os"
"testing"
)
// Test helper functions and members
var doc *Document
+var doc2 *Document
func Doc() *Document {
if doc == nil {
- EnsureDocLoaded()
+ doc = LoadDoc("page.html")
}
return doc
}
+func Doc2() *Document {
+ if doc2 == nil {
+ doc2 = LoadDoc("page2.html")
+ }
+ return doc2
+}
func AssertLength(t *testing.T, nodes []*html.Node, length int) {
if len(nodes) != length {
@@ -43,17 +51,18 @@ func AssertEqual(t *testing.T, s1 *Selection, s2 *Selection) {
}
}
-func EnsureDocLoaded() {
- if f, e := os.Open("./testdata/page.html"); e != nil {
+func LoadDoc(page string) *Document {
+ if f, e := os.Open(fmt.Sprintf("./testdata/%s", page)); e != nil {
panic(e.Error())
} else {
defer f.Close()
if node, e := html.Parse(f); e != nil {
panic(e.Error())
} else {
- doc = NewDocumentFromNode(node)
+ return NewDocumentFromNode(node)
}
}
+ return nil
}
func TestNewDocument(t *testing.T) {