add local html doc for tests

This commit is contained in:
Martin Angers
2012-08-29 11:31:25 -04:00
parent ff4e037994
commit f696fbf5bb
4 changed files with 180 additions and 12 deletions
+2 -9
View File
@@ -18,16 +18,9 @@ Once this is done, install GoQuery:
GoQuery exposes two classes, `Document` and `Selection`. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, GoQuery doesn't know which HTML document to act upon. So it needs to be told, and that's what the `Document` class is for. It holds the root document node to manipulate, and can make selections on this document.
### Document constructors
A `*Document` can be created by one of these methods:
* **NewDocument(url string) (*Document, error)** : loads the HTML document specified by the URL as a string, parses it to its in-memory node representation (using the experimental HTML package) and returns the document reference, or an error.
* **&Document{rootNode, nil}** : creates a document and sets its root node. Useful if you already parsed an HTML document and want to manipulate it using GoQuery.
### .Add(string), .AddFromSelection(*Selection)
Please note that Cascadia's selectors do NOT necessarily match all supported selectors of jQuery (Sizzle). See the [cascadia project][cascadia] for details.
(reference coming soon)
## License
+57
View File
@@ -3,17 +3,28 @@ package goquery
import (
"code.google.com/p/cascadia"
"exp/html"
//"fmt"
"net/http"
"net/url"
)
// TODO : Ensure no node is added more than once in a selection (especially with Add...)
// TODO : Add the following methods:
// - Closest()
// - Parents()
// - Fix ChildrenFiltered, by forking Cascadia and adding a MatchSingle() method?
type Document struct {
Root *html.Node
Url *url.URL
}
func NewDocumentFromNode(root *html.Node) (d *Document) {
// Create and fill the document
d = &Document{root, nil}
return
}
func NewDocument(url string) (d *Document, e error) {
// Load the URL
res, e := http.Get(url)
@@ -55,6 +66,32 @@ func findWithContext(selector string, nodes ...*html.Node) []*html.Node {
return matches
}
func childrenWithContext(selector string, nodes ...*html.Node) []*html.Node {
var matches []*html.Node
//var allChildren bool
//var sel *cascadia.Selector
/*
if selector == "*" || selector == "" {
// Get all children
allChildren = true
} else {
if sel, e := cascadia.Compile(selector); e != nil {
// Selector doesn't compile, empty selection
return nil
}
}
*/
for _, n := range nodes {
for _, nchild := range n.Child {
// TODO : At the moment, given Cascadia's API, cannot call Children with a selector string
//if allChildren /*|| sel(nchild)*/ {
matches = append(matches, nchild)
//}
}
}
return matches
}
// Returns a new Selection object
func (this *Document) Find(selector string) *Selection {
return &Selection{findWithContext(selector, this.Root), this}
@@ -101,3 +138,23 @@ func (this *Selection) Attr(attrName string) (val string, exists bool) {
}
return
}
// Returns a new Selection object.
func (this *Document) Children() *Selection {
return this.ChildrenFiltered("")
}
// Returns a new Selection object.
func (this *Selection) Children() *Selection {
return this.ChildrenFiltered("")
}
// Returns a new Selection object.
func (this *Document) ChildrenFiltered(selector string) *Selection {
return &Selection{childrenWithContext(selector, this.Root), this}
}
// Returns a new Selection object.
func (this *Selection) ChildrenFiltered(selector string) *Selection {
return &Selection{childrenWithContext(selector, this.Nodes...), this.document}
}
+19 -3
View File
@@ -2,16 +2,22 @@ package goquery
import (
"exp/html"
"os"
"testing"
)
var doc *Document
func TestNewDocument(t *testing.T) {
var e error
doc, e = NewDocument("http://provok.in")
if e != nil {
if f, e := os.Open("./testdata/page.html"); e != nil {
t.Error(e.Error())
} else {
defer f.Close()
if node, e := html.Parse(f); e != nil {
t.Error(e.Error())
} else {
doc = NewDocumentFromNode(node)
}
}
}
@@ -92,3 +98,13 @@ func TestAttrNotExist(t *testing.T) {
t.Errorf("Expected no value for the href attribute, got %v.", val)
}
}
func TestChildren(t *testing.T) {
sel := doc.Find(".pvk-content").Children()
if len(sel.Nodes) != 13 {
t.Errorf("Expected 13 child nodes, got %v.", len(sel.Nodes))
for _, n := range sel.Nodes {
t.Logf("%+v", n)
}
}
}
+102
View File
@@ -0,0 +1,102 @@
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>
Provok.in
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Provok.in - Prove your point. State an affirmation, back it up with evidence, unveil the truth.">
<meta name="author" content="Martin Angers">
<link href="http://fonts.googleapis.com/css?family=Belgrano" rel="stylesheet" type="text/css">
<!--[if lt IE 9]><link href="http://fonts.googleapis.com/css?family=Belgrano" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:400italic" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:700" rel="stylesheet" type="text/css"><link href="http://fonts.googleapis.com/css?family=Belgrano:700italic" rel="stylesheet" type="text/css"><![endif]-->
<link href="/css/pvk.min.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="container-fluid">
<div class="row-fluid">
<div class="pvk-gutter">
&nbsp;
</div>
<div class="pvk-content">
<div ng-controller="HeroCtrl" class="hero-unit">
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<h1>
<a href="/">Provok<span class="green">.</span><span class="red">i</span>n</a>
</h1>
<p>
Prove your point.
</p>
</div>
</div>
<div class="row-fluid">
<div class="span12 alert alert-error">
<strong>Beta Version.</strong> Things may change. Or disappear. Or fail miserably. If it's the latter, <a href="https://github.com/PuerkitoBio/Provok.in-issues" target="_blank" class="link">please file an issue.</a>
</div>
</div>
<div ng-cloak="" ng-show="isLoggedOut() &amp;&amp; !hideLogin" class="row-fluid">
<a ng-href="{{ROUTES.login}}" class="btn btn-primary">Sign in. Painless.</a> <span>or</span> <a ng-href="{{ROUTES.help}}" class="link">learn more about provok.in.</a>
</div>
<div ng-cloak="" ng-show="isLoggedIn()" class="row-fluid logged-in-state">
<span>Welcome,</span> <a ng-href="{{ROUTES.profile}}" class="link">{{getUserName()}}</a> <span>(</span> <a ng-click="doLogout($event)" class="link">logout</a> <span>)</span>
</div>
</div>
</div>
</div>
<div class="pvk-gutter">
&nbsp;
</div>
</div>
<div class="row-fluid">
<div class="pvk-gutter">
&nbsp;
</div>
<div class="pvk-content">
<div class="container-fluid">
<div class="row-fluid">
<div ng-cloak="" view-on-display="" ng-controller="MsgCtrl" ng-class="{'displayed': blockIsDisplayed}" class="message-box">
<div ng-class="{'alert-info': isInfo, 'alert-error': !isInfo, 'displayed': isDisplayed}" class="alert">
<a ng-click="hideMessage(true, $event)" class="close">×</a>
<h4 class="alert-heading">
{{ title }}
</h4>
<p>
{{ message }}
</p>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div ng-controller="ShareCtrl" ng-hide="isHidden" class="row-fluid center-content"></div>
</div>
<div ng-view=""></div>
</div>
<div class="pvk-gutter">
&nbsp;
</div>
</div>
<div class="row-fluid">
<div class="pvk-gutter">
&nbsp;
</div>
<div class="pvk-content">
<div class="footer">
<p>
<a href="/" class="link">Home</a> <span>|</span> <a href="/about" class="link">About</a> <span>|</span> <a href="/help" class="link">Help</a>
</p>
<p>
<small>© 2012 Martin Angers</small>
</p>
</div>
</div>
<div class="pvk-gutter">
&nbsp;
</div>
</div>
</div>
</body>
</html>