phantom_menace 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +7 -0
- data/.rspec +0 -0
- data/CHANGELOG.md +9 -0
- data/README.md +29 -2
- data/Rakefile +7 -0
- data/bin/phantom_menace.coffee +13 -28
- data/lib/phantom_menace/browser.rb +40 -3
- data/lib/phantom_menace/version.rb +1 -1
- data/phantom_menace.gemspec +2 -0
- data/spec/browser_spec.rb +27 -3
- data/spec/test_server/README.md +10 -0
- data/spec/test_server/public/index.html +11 -0
- data/spec/test_server/server.rb +1 -0
- metadata +43 -8
data/.autotest
ADDED
data/.rspec
ADDED
File without changes
|
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# phantom_menace
|
2
2
|
|
3
3
|
A real headless "browser." It uses phantomjs and provides an API like a
|
4
4
|
real browser does. Much like poltergeist but decoupled from capybara.
|
@@ -11,7 +11,7 @@ It is perfect for scraping or doing any browser related tasks.
|
|
11
11
|
## Install
|
12
12
|
|
13
13
|
```sh
|
14
|
-
gem install
|
14
|
+
gem install phantom_menace
|
15
15
|
```
|
16
16
|
|
17
17
|
## Getting Started
|
@@ -43,3 +43,30 @@ When the server is running, run the example by doing.
|
|
43
43
|
```sh
|
44
44
|
bundle exec ruby examples/simple.rb
|
45
45
|
```
|
46
|
+
|
47
|
+
## Running The Tests
|
48
|
+
|
49
|
+
Unfortunately, we still don't have an automated test suite to run the
|
50
|
+
different services.
|
51
|
+
|
52
|
+
We have to run three things.
|
53
|
+
|
54
|
+
1. The `phantom_menace` binary
|
55
|
+
|
56
|
+
```sh
|
57
|
+
bundle exec ./bin/phantom_menace
|
58
|
+
```
|
59
|
+
|
60
|
+
2. The sinatra test server - This serves the files needed for the tests
|
61
|
+
instead of hitting third party sites. This ensures that we can run
|
62
|
+
the tests without internet.
|
63
|
+
|
64
|
+
```sh
|
65
|
+
bundle exec ruby ./spec/test_server/server.rb
|
66
|
+
```
|
67
|
+
|
68
|
+
3. Finally we can run the specs
|
69
|
+
|
70
|
+
```sh
|
71
|
+
bundle exec rake spec
|
72
|
+
```
|
data/Rakefile
CHANGED
data/bin/phantom_menace.coffee
CHANGED
@@ -1,17 +1,6 @@
|
|
1
1
|
USER_AGENT = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) ' +
|
2
2
|
'AppleWebKit/A.B (KHTML, like Gecko) Chrome/X.Y.Z.W Safari/A.B.'
|
3
3
|
|
4
|
-
class Page
|
5
|
-
constructor: ->
|
6
|
-
@_loaded = false
|
7
|
-
@_page = require('webpage').create()
|
8
|
-
|
9
|
-
open: (url) ->
|
10
|
-
@_page.open url
|
11
|
-
|
12
|
-
isLoaded: ->
|
13
|
-
@_loaded
|
14
|
-
|
15
4
|
class Browser
|
16
5
|
constructor: ->
|
17
6
|
# This is the response container
|
@@ -26,36 +15,32 @@ class Browser
|
|
26
15
|
click: (left, top) ->
|
27
16
|
@page.sendEvent left, top
|
28
17
|
|
29
|
-
find: (
|
18
|
+
find: (data) ->
|
30
19
|
console.log 'Finding it'
|
31
|
-
|
32
|
-
ret = @page.evaluate ->
|
20
|
+
onEvaluate = (eArgs) ->
|
33
21
|
elements = []
|
34
|
-
jQuery(
|
22
|
+
jQuery(eArgs.selector).each (i, obj) ->
|
35
23
|
attrs = {}
|
36
24
|
attrs[attr.name] = attr.value for attr in obj.attributes
|
37
|
-
|
38
25
|
elements.push
|
39
26
|
attrs: attrs
|
40
27
|
text: jQuery(obj).text()
|
41
28
|
pos: jQuery(obj).offset()
|
42
29
|
elements
|
43
30
|
|
31
|
+
ret = @page.evaluate(onEvaluate, { selector: data.selector })
|
32
|
+
|
44
33
|
@resp =
|
45
34
|
success: true
|
46
35
|
ret: ret
|
47
36
|
|
48
37
|
@state = 'default'
|
49
38
|
|
50
|
-
|
51
|
-
findAll: ->
|
52
|
-
console.log 'Finding all'
|
53
|
-
|
54
39
|
goforward: ->
|
55
40
|
console.log 'Going forward a page'
|
56
41
|
|
57
|
-
goto: (
|
58
|
-
@page.open decodeURIComponent(url)
|
42
|
+
goto: (data) ->
|
43
|
+
@page.open decodeURIComponent(data.url)
|
59
44
|
|
60
45
|
goback: ->
|
61
46
|
this.goto @history.pop
|
@@ -66,8 +51,10 @@ class Browser
|
|
66
51
|
reload: ->
|
67
52
|
this.goto @history[@history.length - 1]
|
68
53
|
|
69
|
-
render: ->
|
70
|
-
@page.render()
|
54
|
+
render: (data) ->
|
55
|
+
@page.render(data.filename)
|
56
|
+
@resp = success: true
|
57
|
+
@state = 'default'
|
71
58
|
|
72
59
|
content: ->
|
73
60
|
@page.content
|
@@ -118,23 +105,21 @@ class Server
|
|
118
105
|
@server.listen 8080, this._handleRequest
|
119
106
|
|
120
107
|
_handleRequest: (req, res) =>
|
121
|
-
params = req.post
|
108
|
+
params = JSON.parse(req.post.payload)
|
122
109
|
|
123
110
|
if @browser[params.command]
|
124
111
|
@browser.runCommand(params.command, params.data)
|
125
112
|
this._runLoop(req, res)
|
126
113
|
else
|
127
114
|
res.statusCode = 200
|
128
|
-
res.write JSON.stringify
|
115
|
+
res.write JSON.stringify
|
129
116
|
success: false
|
130
117
|
message: "Command not found"
|
131
|
-
})
|
132
118
|
res.close()
|
133
119
|
|
134
120
|
_runLoop: (req, res) =>
|
135
121
|
setTimeout =>
|
136
122
|
console.log 'THE STATE: ' + @browser.state
|
137
|
-
|
138
123
|
if @browser.state is 'loading'
|
139
124
|
this._runLoop(req, res)
|
140
125
|
else if @browser.state is 'default'
|
@@ -3,28 +3,65 @@ require "uri"
|
|
3
3
|
require "json"
|
4
4
|
|
5
5
|
module PhantomMenace
|
6
|
+
# PhantomMenace::Browser
|
7
|
+
#
|
8
|
+
# Creates a Browser that you can interact with. Exposes methods like
|
9
|
+
# how you would find a real browser.
|
10
|
+
#
|
11
|
+
# == Example
|
12
|
+
#
|
13
|
+
# browser = PhantomMenace::Browser.new
|
14
|
+
# browser.goto "http://facebook.com"
|
15
|
+
#
|
16
|
+
# Look at the API for more methods.
|
6
17
|
class Browser
|
18
|
+
# Navigates to the specified URL.
|
7
19
|
def goto(url)
|
8
20
|
options = {
|
9
21
|
command: "goto",
|
10
|
-
data: url
|
22
|
+
data: { url: url }
|
11
23
|
}
|
12
24
|
post(options)
|
13
25
|
end
|
14
26
|
|
15
27
|
def find_all_links
|
16
28
|
options = {
|
17
|
-
command: "find"
|
29
|
+
command: "find",
|
30
|
+
data: { selector: "a" }
|
18
31
|
}
|
19
32
|
post(options)["ret"].map do |node|
|
20
33
|
PhantomMenace::Element.new(node)
|
21
34
|
end
|
22
35
|
end
|
23
36
|
|
37
|
+
# Uses jQuery's selector method. `$(sel)`
|
38
|
+
def find(sel)
|
39
|
+
options = {
|
40
|
+
command: "find",
|
41
|
+
data: { selector: sel }
|
42
|
+
}
|
43
|
+
post(options)["ret"].map do |node|
|
44
|
+
PhantomMenace::Element.new(node)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Renders the loaded page in the specified path,
|
49
|
+
# if path is not given, defaults to the current
|
50
|
+
# directory.
|
51
|
+
def render(filename = nil)
|
52
|
+
filename ||= File.expand_path("../", __FILE__) + "/screenshot.png"
|
53
|
+
options = {
|
54
|
+
command: "render",
|
55
|
+
data: { filename: filename }
|
56
|
+
}
|
57
|
+
post(options)
|
58
|
+
end
|
59
|
+
|
24
60
|
private
|
25
61
|
|
26
62
|
def post(options)
|
27
|
-
|
63
|
+
data = { payload: options.to_json }
|
64
|
+
req = Net::HTTP.post_form(URI.parse(URL), data)
|
28
65
|
JSON.parse(req.body)
|
29
66
|
end
|
30
67
|
end
|
data/phantom_menace.gemspec
CHANGED
data/spec/browser_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'phantom_menace'
|
2
2
|
|
3
|
+
TEST_URL = "http://localhost:4567/index.html"
|
4
|
+
|
3
5
|
describe PhantomMenace::Browser do
|
4
6
|
before do
|
5
7
|
@browser = PhantomMenace::Browser.new
|
@@ -7,16 +9,38 @@ describe PhantomMenace::Browser do
|
|
7
9
|
|
8
10
|
describe "#goto" do
|
9
11
|
it "responds with success if page opens successfully" do
|
10
|
-
resp = @browser.goto
|
12
|
+
resp = @browser.goto TEST_URL
|
11
13
|
resp["success"].should == true
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
17
|
describe "#find_all_links" do
|
16
18
|
it "responds with the links in the page" do
|
17
|
-
@browser.goto
|
19
|
+
@browser.goto TEST_URL
|
18
20
|
resp = @browser.find_all_links
|
19
|
-
resp.length.should_not
|
21
|
+
resp.length.should_not == 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#find" do
|
26
|
+
it "responds with the element found" do
|
27
|
+
@browser.goto TEST_URL
|
28
|
+
resp = @browser.find('#first_div')
|
29
|
+
resp.length.should_not == 0
|
30
|
+
end
|
31
|
+
|
32
|
+
it "responds with a blank array if nothing found" do
|
33
|
+
@browser.goto TEST_URL
|
34
|
+
resp = @browser.find('.non-existing-class')
|
35
|
+
resp.should be_empty
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#render" do
|
40
|
+
it "saves the file in the path specified" do
|
41
|
+
@browser.goto TEST_URL
|
42
|
+
resp = @browser.render
|
43
|
+
resp["success"].should == true
|
20
44
|
end
|
21
45
|
end
|
22
46
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "sinatra"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phantom_menace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -59,6 +59,38 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: ZenTest
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: sinatra
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
62
94
|
description: Ruby Wrapper for Phantomjs with a Browser API
|
63
95
|
email:
|
64
96
|
- william.estoque@gmail.com
|
@@ -69,7 +101,10 @@ executables:
|
|
69
101
|
extensions: []
|
70
102
|
extra_rdoc_files: []
|
71
103
|
files:
|
104
|
+
- .autotest
|
72
105
|
- .gitignore
|
106
|
+
- .rspec
|
107
|
+
- CHANGELOG.md
|
73
108
|
- Gemfile
|
74
109
|
- LICENSE
|
75
110
|
- README.md
|
@@ -84,6 +119,9 @@ files:
|
|
84
119
|
- lib/phantom_menace/version.rb
|
85
120
|
- phantom_menace.gemspec
|
86
121
|
- spec/browser_spec.rb
|
122
|
+
- spec/test_server/README.md
|
123
|
+
- spec/test_server/public/index.html
|
124
|
+
- spec/test_server/server.rb
|
87
125
|
homepage: ''
|
88
126
|
licenses: []
|
89
127
|
post_install_message:
|
@@ -96,18 +134,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
134
|
- - ! '>='
|
97
135
|
- !ruby/object:Gem::Version
|
98
136
|
version: '0'
|
99
|
-
segments:
|
100
|
-
- 0
|
101
|
-
hash: -1323133816147866598
|
102
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
138
|
none: false
|
104
139
|
requirements:
|
105
140
|
- - ! '>='
|
106
141
|
- !ruby/object:Gem::Version
|
107
142
|
version: '0'
|
108
|
-
segments:
|
109
|
-
- 0
|
110
|
-
hash: -1323133816147866598
|
111
143
|
requirements: []
|
112
144
|
rubyforge_project:
|
113
145
|
rubygems_version: 1.8.24
|
@@ -116,3 +148,6 @@ specification_version: 3
|
|
116
148
|
summary: Phantomjs based browser with a ruby wrapper
|
117
149
|
test_files:
|
118
150
|
- spec/browser_spec.rb
|
151
|
+
- spec/test_server/README.md
|
152
|
+
- spec/test_server/public/index.html
|
153
|
+
- spec/test_server/server.rb
|