akephalos2-stable 2.1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Bernerd Schaefer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,365 @@
1
+ # Important Notice
2
+
3
+ This repo has rewritten its history and as such is not compatible with the main Akephalos repo.
4
+
5
+ You can get the unaltered – before history rewrite – pristine copy at: [https://github.com/Nerian/akephalos](https://github.com/Nerian/akephalos)
6
+
7
+ Further development will be done here:
8
+ [https://github.com/Nerian/akephalos2](https://github.com/Nerian/akephalos2)
9
+
10
+ Its history was rewritten in order to remove .jar vendor files that were making its size huge.
11
+
12
+
13
+ # Akephalos
14
+
15
+ Akephalos is a full-stack headless browser for integration testing with
16
+ [Capybara](https://github.com/jnicklas/capybara). It is built on top of [HtmlUnit](http://htmlunit.sourceforge.net),
17
+ a GUI-less browser for the Java platform, but can be run on both JRuby and
18
+ MRI with no need for JRuby to be installed on the system.
19
+
20
+ The name Akephalos /ā-sĕf'ə-ləs/ comes from the Greek ἀκέφαλος akephalos, which literally means "headless".
21
+
22
+
23
+ ## Installation
24
+
25
+ ``` ruby
26
+ gem install akephalos2
27
+ ```
28
+
29
+ Or
30
+
31
+ ``` ruby
32
+ gem 'akephalos2', :require => 'akephalos'
33
+ ```
34
+
35
+ Or (for the current master branch)
36
+
37
+ ``` ruby
38
+ gem 'akephalos2', :git => 'git://github.com/Nerian/akephalos2.git'
39
+ ```
40
+
41
+ Akephalos creates a `.akephalos` folder where it stores HTMLUnit binaries. You should set Git to ignore that folder.
42
+
43
+ ```
44
+ git ignore .akephalos
45
+ ```
46
+
47
+
48
+ # Questions, bugs, etc:
49
+
50
+ We use GitHub issues:
51
+
52
+ [https://github.com/Nerian/akephalos2/issues](https://github.com/Nerian/akephalos2/issues)
53
+
54
+
55
+ # Development
56
+
57
+ <a href='http://travis-ci.org/#!/Nerian/akephalos2'>
58
+ <img src="https://secure.travis-ci.org/Nerian/akephalos2.png?branch=master&amp;.png"/>
59
+ </a>
60
+
61
+ ``` bash
62
+ git clone https://github.com/Nerian/akephalos2
63
+ ```
64
+
65
+ Also, we have a .rvmrc file already cooked:
66
+
67
+ ``` bash
68
+ cp .rvmrc.example .rvmrc
69
+ ```
70
+
71
+
72
+ ## Setup
73
+
74
+ Configuring akephalos is as simple as requiring it and setting Capybara's
75
+ javascript driver:
76
+
77
+ ``` ruby
78
+ require 'akephalos'
79
+ Capybara.javascript_driver = :akephalos
80
+ ```
81
+
82
+
83
+ ## Basic Usage
84
+
85
+ Akephalos provides a driver for Capybara, so using Akephalos is no
86
+ different than using Selenium or Rack::Test. For a full usage guide, check
87
+ out Capybara's DSL [documentation](http://github.com/jnicklas/capybara). It
88
+ makes no assumptions about the testing framework being used, and works with
89
+ RSpec, Cucumber, and Test::Unit.
90
+
91
+ Here's some sample RSpec code:
92
+
93
+ ``` ruby
94
+ # encoding: utf-8
95
+
96
+ describe "Home Page" do
97
+ before { visit "/" }
98
+
99
+ context "searching" do
100
+
101
+ before do
102
+ fill_in "Search", :with => "akephalos"
103
+ click_button "Go"
104
+ end
105
+
106
+ it "returns results" { page.should have_css("#results") }
107
+
108
+ it "includes the search term" { page.should have_content("akephalos") }
109
+ end
110
+
111
+ end
112
+ ```
113
+
114
+
115
+ ### Encoding
116
+
117
+ Akephalos uses UTF-8 encoding by default. You may need to add `# encoding: utf-8` at the first line of your test. This behavior is the default using JRuby in 1.9 mode, but you can use JRuby in 1.8 mode by setting the environment variable `ENV['JRUBY_1_8']=true`. Note that Akephalos works with MRI. I refer here to the JRuby that is used internally by Akephalos.
118
+
119
+
120
+ ### Frames
121
+
122
+ Capybara allows you to perform your action on a context, for example inside a div or a frame. With Akephalos you can select the frame either by id or by index.
123
+
124
+ ``` html
125
+ <body>
126
+ <p id="test">Test</p>
127
+ <iframe id="first" src="/one_text"></iframe>
128
+ <p id="test2">Test2</p>
129
+ <iframe class="second" src="/two_text"></iframe>
130
+ <p id="test3">Test3</p>
131
+ <iframe id="third" src="/three_text"></iframe>
132
+ </body>
133
+ ```
134
+
135
+ You can operate within the context of iframe `test2` with any of these calls:
136
+
137
+ ``` ruby
138
+ # By ID
139
+ within_frame("test2") do
140
+ ....
141
+ end
142
+
143
+ # By index
144
+ within_frame(1) do
145
+ ....
146
+ end
147
+ ```
148
+
149
+ ## Configuration
150
+
151
+ There are now a few configuration options available through Capybara's new
152
+ `register_driver` API.
153
+
154
+
155
+ ### Configure the max memory that Java Virtual Machine can use
156
+
157
+ The max memory that the JVM is going to use can be set using an environment variable in your spec_helper or .bashrc file.
158
+
159
+ ``` ruby
160
+ ENV['akephalos_jvm_max_memory']
161
+ ```
162
+
163
+
164
+ The default value is 128 MB.
165
+
166
+ If you use Akephalos's bin the parameter `-m [memory]` sets the max memory for the JVM.
167
+
168
+ ``` bash
169
+ $ akephalos -m 670
170
+ ```
171
+
172
+
173
+ ### Configure the version of HTMLUnit
174
+
175
+ The Htmlunit version is configured with a environmental variable named `htmlunit_version`. The possible versions are listed at [here](http://sourceforge.net/projects/htmlunit/files/htmlunit/)
176
+
177
+ ```
178
+ ENV["htmlunit_version"] = "2.10" # Development Snapshots
179
+ ENV["htmlunit_version"] = "2.9"
180
+ ENV["htmlunit_version"] = "2.8"
181
+ ENV["htmlunit_version"] = "2.7"
182
+ ```
183
+
184
+ It defaults to HtmlUnit 2.9. You can manually download or copy your own version to .akephalos/:version and use it with `ENV["htmlunit_version"] = "version"`
185
+
186
+ ### Using a different browser
187
+
188
+ HtmlUnit supports a few browser implementations, and you can choose which
189
+ browser you would like to use through Akephalos. By default, Akephalos uses
190
+ Firefox 3.6.
191
+
192
+ ``` ruby
193
+ Capybara.register_driver :akephalos do |app|
194
+ # available options:
195
+ # :ie6, :ie7, :ie8, :firefox_3_6
196
+ Capybara::Driver::Akephalos.new(app, :browser => :ie8)
197
+ end
198
+ ```
199
+
200
+
201
+ ### Using a Proxy Server
202
+
203
+ ``` ruby
204
+ Capybara.register_driver :akephalos do |app|
205
+ Capybara::Driver::Akephalos.new(app, :http_proxy => 'myproxy.com', :http_proxy_port => 8080)
206
+ end
207
+ ```
208
+
209
+
210
+ ### Ignoring javascript errors
211
+
212
+ By default HtmlUnit (and Akephalos) will raise an exception when an error
213
+ is encountered in javascript files. This is generally desirable, except
214
+ that certain libraries aren't supported by HtmlUnit. If possible, it's
215
+ best to keep the default behaviour, and use Filters (see below) to mock
216
+ offending libraries. If needed, however, you can configure Akephalos to
217
+ ignore javascript errors.
218
+
219
+ ``` ruby
220
+ Capybara.register_driver :akephalos do |app|
221
+ Capybara::Driver::Akephalos.new(app, :validate_scripts => false)
222
+ end
223
+ ```
224
+
225
+
226
+ ### Setting the HtmlUnit log level
227
+
228
+ By default it uses the 'fatal' level. You can change that like this:
229
+
230
+ ``` ruby
231
+ Capybara.register_driver :akephalos do |app|
232
+ # available options
233
+ # "trace", "debug", "info", "warn", "error", or "fatal"
234
+ Capybara::Driver::Akephalos.new(app, :htmlunit_log_level => 'fatal')
235
+ end
236
+ ```
237
+
238
+
239
+ ### Running Akephalos with Spork
240
+
241
+ ``` ruby
242
+ Spork.prefork do
243
+ ...
244
+ Akephalos::RemoteClient.manager
245
+ end
246
+
247
+ Spork.each_run do
248
+ ...
249
+ Thread.current['DRb'] = { 'server' => DRb::DRbServer.new }
250
+ end
251
+ ```
252
+
253
+
254
+ More info at : [sporking-with-akephalos](http://spacevatican.org/2011/7/3/sporking-with-akephalos)
255
+
256
+ ### Filters
257
+
258
+ Akephalos allows you to filter requests originating from the browser and return mock responses. This will let you easily filter requests for external resources when running your tests, such as Facebook's API and Google Analytics.
259
+
260
+ Configuring filters in Akephalos should be familiar to anyone who has used FakeWeb or a similar library. The simplest filter requires only an HTTP method (:get, :post, :put, :delete, :any) and a string or regex to match against.
261
+
262
+ ``` ruby
263
+ Akephalos.filter(:get, "http://www.google.com")
264
+ Akephalos.filter(:any, %r{^http://(api\.)?twitter\.com/.*$})
265
+ ```
266
+
267
+
268
+ By default, all filtered requests will return an empty body with a 200 status code. You can change this by passing additional options to your filter call.
269
+
270
+ ``` ruby
271
+ Akephalos.filter(:get, "http://google.com/missing",
272
+ :status => 404, :body => "... <h1>Not Found</h1> ...")
273
+
274
+ Akephalos.filter(:post, "http://my-api.com/resource.xml",
275
+ :status => 201, :headers => {
276
+ "Content-Type" => "application/xml",
277
+ "Location" => "http://my-api.com/resources/1.xml" },
278
+ :body => {:id => 100}.to_xml)
279
+ ```
280
+
281
+
282
+ And that's really all there is to it! It should be fairly trivial to set up filters for the external resources you need to fake. For reference, however, here's what we ended up using for our external sources.
283
+
284
+ #### Example: Google Maps
285
+
286
+ Google Analytics code is passively applied based on HTML comments, so simply returning an empty response body is enough to disable it without errors.
287
+
288
+ ``` ruby
289
+ Akephalos.filter(:get, "http://www.google-analytics.com/ga.js",
290
+ :headers => {"Content-Type" => "application/javascript"})
291
+ ```
292
+
293
+
294
+ Google Maps requires the most extensive amount of API definitions of the three, but these few lines cover everything we've encountered so far.
295
+
296
+ ``` ruby
297
+ Akephalos.filter(:get, "http://maps.google.com/maps/api/js?sensor=false",
298
+ :headers => {"Content-Type" => "application/javascript"},
299
+ :body => "window.google = {
300
+ maps: {
301
+ LatLng: function(){},
302
+ Map: function(){},
303
+ Marker: function(){},
304
+ MapTypeId: {ROADMAP:1}
305
+ }
306
+ };")
307
+ ```
308
+
309
+
310
+ #### Example: Facebook Connect
311
+
312
+ Facebook Connect
313
+
314
+ When you enable Facebook Connect on your page, the FeatureLoader is requested, and then additional resources are loaded when you call FB_RequireFeatures. We can therefore return an empty function from our filter to disable all Facebook Connect code.
315
+
316
+ ``` ruby
317
+ Akephalos.filter(:get,
318
+ "http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php",
319
+ :headers => {"Content-Type" => "application/javascript"},
320
+ :body => "window.FB_RequireFeatures = function() {};")
321
+ ```
322
+
323
+
324
+ ### Akephalos' Interactive mode
325
+
326
+ #### bin/akephalos
327
+
328
+ The bundled akephalos binary provides a command line interface to a few useful features.
329
+
330
+
331
+ #### akephalos --interactive
332
+
333
+ Running Akephalos in interactive mode gives you an IRB context for interacting with your site just as you would in your tests:
334
+
335
+ ``` ruby
336
+ $ akephalos --interactive
337
+ -> Capybara.app_host # => "http://localhost:3000"
338
+ -> page.visit "/"
339
+ -> page.fill_in "Search", :with => "akephalos"
340
+ -> page.click_button "Go"
341
+ -> page.has_css?("#search_results") # => true
342
+ ```
343
+
344
+
345
+ #### akephalos --use-htmlunit-snapshot
346
+
347
+ This will instruct Akephalos to use the latest development snapshot of HtmlUnit as found on it's Cruise Control server. HtmlUnit and its dependencies will be unpacked into vendor/htmlunit in the current working directory.
348
+
349
+ This is what the output looks like:
350
+
351
+ ``` ruby
352
+ $ akephalos --use-htmlunit-snapshot
353
+
354
+ Downloading latest snapshot... done
355
+ Extracting dependencies... done
356
+ ========================================
357
+ The latest HtmlUnit snapshot has been extracted to vendor/htmlunit!
358
+ Once HtmlUnit has been extracted, Akephalos will automatically detect
359
+ the vendored version and use it instead of the bundled version.
360
+ ```
361
+
362
+
363
+ #### akephalos --server <socket_file>
364
+
365
+ Akephalos uses this command internally to start a JRuby DRb server using the provided socket file.
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:set filetype=ruby:
3
+
4
+ require "pathname"
5
+ require "optparse"
6
+ require 'rubygems'
7
+ require "akephalos/htmlunit_downloader"
8
+
9
+ options = { :interactive => false, :default_jvm_max_memory => '128'}
10
+
11
+ parser = OptionParser.new do |opts|
12
+ opts.banner = "Usage: akephalos [--interactive, --use-htmlunit-snapshot, --memory [number]] | [--server] <port>"
13
+ opts.on("-s", "--server", "Run in server mode (default)")
14
+ opts.on("-i", "--interactive", "Run in interactive mode") { options[:interactive] = true }
15
+ opts.on("--use-htmlunit-snapshot", "Use the snapshot of htmlunit") { options[:use_htmlunit_snapshot] = true }
16
+ opts.on("-m", "--memory [number]", "Max memory for the Java Virtual Machine, defaults to #{options[:default_jvm_max_memory]}
17
+ or env variable $akephalos_jvm_max_memory") do |memory|
18
+ options[:akephalos_jvm_max_memory] = memory.to_s
19
+ end
20
+
21
+ if options[:akephalos_jvm_max_memory].nil?
22
+ if ENV['akephalos_jvm_max_memory'].nil?
23
+ options[:akephalos_jvm_max_memory] = options[:default_jvm_max_memory]
24
+ else
25
+ options[:akephalos_jvm_max_memory] = ENV['akephalos_jvm_max_memory']
26
+ end
27
+ end
28
+ puts "Using #{options[:akephalos_jvm_max_memory]} MB for the JVM"
29
+
30
+ ENV['htmlunit_version'] ||= "2.9"
31
+ HtmlUnit.download_htmlunit(ENV["htmlunit_version"])
32
+
33
+ opts.on_tail("-h", "--help", "Show this message") { puts opts; exit }
34
+ end
35
+ parser.parse!
36
+
37
+ root = Pathname(__FILE__).expand_path.dirname.parent
38
+ lib = root + 'lib'
39
+ src = root + 'vendor'
40
+
41
+ case
42
+ when options[:use_htmlunit_snapshot]
43
+ require "fileutils"
44
+
45
+ FileUtils.mkdir_p("vendor/html-unit")
46
+ Dir["vendor/html-unit/*.jar"].each { |jar| File.unlink(jar) }
47
+
48
+ Dir.chdir("vendor") do
49
+ $stdout.print "Downloading latest snapshot... "
50
+ $stdout.flush
51
+ %x[curl -O http://build.canoo.com/htmlunit/artifacts/htmlunit-2.10-SNAPSHOT-with-dependencies.zip]
52
+ puts "done"
53
+
54
+ $stdout.print "Extracting dependencies... "
55
+ $stdout.flush
56
+ %x[unzip -j -d html-unit htmlunit-2.10-SNAPSHOT-with-dependencies.zip htmlunit-2.10-SNAPSHOT/lib htmlunit-2.10-SNAPSHOT/lib/* &> /dev/null]
57
+ puts "done"
58
+
59
+ File.unlink "htmlunit-2.10-SNAPSHOT-with-dependencies.zip"
60
+ end
61
+
62
+ $stdout.puts "="*40
63
+ $stdout.puts "The latest HtmlUnit snapshot has been extracted to vendor/html-unit!"
64
+ when options[:interactive]
65
+ $LOAD_PATH.unshift('vendor', lib, src)
66
+ require 'akephalos'
67
+ require 'akephalos/console'
68
+ Akephalos::Console.start
69
+ else
70
+ unless port = ARGV[0]
71
+ puts parser.help
72
+ exit
73
+ end
74
+
75
+ if RUBY_PLATFORM == "java"
76
+ $LOAD_PATH.unshift("vendor", lib, src)
77
+ require 'akephalos/server'
78
+ Akephalos::Server.start!(port)
79
+ else
80
+ require 'jruby-jars'
81
+
82
+ jruby = JRubyJars.core_jar_path
83
+ jruby_stdlib = JRubyJars.stdlib_jar_path
84
+
85
+ java_args = [
86
+ "-Xmx#{options[:akephalos_jvm_max_memory]}M",
87
+ "-cp", [JRubyJars.core_jar_path, JRubyJars.stdlib_jar_path].join(File::PATH_SEPARATOR),
88
+ "org.jruby.Main",
89
+ "-X+O"
90
+ ]
91
+
92
+ ruby_args = [
93
+ "-Ku",
94
+ "-I", ["#{Dir.pwd}/.akephalos/#{ENV['htmlunit_version']}", lib, src].join(File::PATH_SEPARATOR),
95
+ "-r", "akephalos/server",
96
+ "-e", "Akephalos::Server.start!(#{port.inspect})"
97
+ ]
98
+
99
+ # Bundler sets ENV["RUBYOPT"] to automatically load bundler/setup.rb, but
100
+ # since the akephalos server doesn't have any gem dependencies and is
101
+ # always executed with the same context, we clear RUBYOPT before running
102
+ # exec.
103
+ if ENV['JRUBY_1_8']
104
+ ENV["RUBYOPT"] = ''
105
+ else
106
+ ENV["RUBYOPT"] = "--1.9"
107
+ end
108
+ exec("java", *(java_args + ruby_args))
109
+ end
110
+ end