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.
@@ -0,0 +1,7 @@
1
+ require 'autotest/restart'
2
+
3
+ Autotest.add_hook :initialize do |at|
4
+ at.add_mapping(/.*/) do |f, _|
5
+ at.files_matching(/.*.rb$/)
6
+ end
7
+ end
data/.rspec ADDED
File without changes
@@ -0,0 +1,9 @@
1
+ ## 0.0.2 (2012-06-10)
2
+
3
+ * Added Browser#find
4
+ * Added Browser#render
5
+
6
+ ## 0.0.1 (2012-06-08)
7
+
8
+ * First release
9
+ * Browser has methods #find_all_links and #goto
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # phantom-menace
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 phantom-menace
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
@@ -1,2 +1,9 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ desc "Run all specs"
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ desc "Default: run specs."
9
+ task default: :spec
@@ -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: (selector) ->
18
+ find: (data) ->
30
19
  console.log 'Finding it'
31
-
32
- ret = @page.evaluate ->
20
+ onEvaluate = (eArgs) ->
33
21
  elements = []
34
- jQuery('a').each (i, obj) ->
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: (url) ->
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
- req = Net::HTTP.post_form(URI.parse(URL), options)
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
@@ -1,3 +1,3 @@
1
1
  module PhantomMenace
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -18,4 +18,6 @@ Gem::Specification.new do |gem|
18
18
  gem.add_development_dependency "rspec"
19
19
  gem.add_development_dependency "rake"
20
20
  gem.add_development_dependency "phantomjs.rb"
21
+ gem.add_development_dependency "ZenTest"
22
+ gem.add_development_dependency "sinatra"
21
23
  end
@@ -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 "http://google.com"
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 "http://google.com"
19
+ @browser.goto TEST_URL
18
20
  resp = @browser.find_all_links
19
- resp.length.should_not be(0)
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,10 @@
1
+ # Test Server
2
+
3
+ The test server is a sinatra based server that serves static files
4
+ needed by the tests.
5
+
6
+ ## Running
7
+
8
+ ```sh
9
+ bundle exec ruby server.rb
10
+ ```
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Hello World</title>
5
+ </head>
6
+ <body>
7
+ <h1>Hello World</h1>
8
+ <a href="/first_link_href.html">The First Text</a>
9
+ <div id="first_div">I am the first div</div>
10
+ </body>
11
+ </html>
@@ -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.1
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-08 00:00:00.000000000 Z
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