langalex-culerity 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile ADDED
@@ -0,0 +1,86 @@
1
+ h2. Introduction
2
+
3
+ Culerity integrates Cucumber and Celerity in order to test your application's full stack.
4
+
5
+ Culerity lets you:
6
+ * run Celerity from within Cucumber which allows you to test the full stack of your Rails (or other web) application from Database to in browser JavaScript
7
+ * run your application in any Ruby (like MRI 1.8.6) while Celerity runs in JRuby so you can still use gems/plugins that would not work with JRuby
8
+ * reuse existing Webrat-Style step definitions
9
+
10
+ h2. Getting Started
11
+
12
+ The following guide is written for a Rails application (tested with 2.2.2) but Culerity should work with any other Web Framework that is supported by Cucumber.
13
+
14
+ First download JRuby and unpack it to some location, for example $HOME/jruby. Make sure that the jruby executable is in your path. You can do this by either setting your PATH accordingly...
15
+
16
+ export PATH=$HOME/jruby/bin:$PATH
17
+
18
+ ... or by creating a symlink from your bin directory:
19
+
20
+ ln -s $HOME/jruby/bin/jruby /usr/bin/jruby
21
+
22
+ Next install the celerity gem for JRuby:
23
+
24
+ jruby -S gem install celerity
25
+
26
+ Now (assuming you have a Rails application set up already) install Culerity as a Rails Plugin:
27
+
28
+ cd RAILS_ROOT
29
+ git clone git://github.com/langalex/culerity.git
30
+
31
+ or as a gem: (definitely preferred)
32
+
33
+ gem install langalex-culerity
34
+
35
+ And add the culerity gem to your environment.rb:
36
+
37
+ config.gem 'langalex-culerity', :lib => 'culerity', :version => '0.1', :source => 'http://gems.github.com'
38
+
39
+ Run the RSpec, Cucumber and Culerity generators:
40
+
41
+ cd RAILS_ROOT
42
+ script/generate rspec
43
+ script/generate cucumber
44
+ script/generate culerity
45
+
46
+ This creates the features folder and a file common_celerity.rb into your application. This file contains step definitions for basic interactions like clicking links or filling out forms.
47
+
48
+ After you have written a first feature you can run it just like you would run a standard cucumber feature. The only difference is that you have to start a web server (e.g. mongrel) with the test environment enabled beforehand.
49
+
50
+ NOTE: For now this server has to run on port 80 because of some problem with redirects losing the port information.
51
+
52
+
53
+ sudo script/server -p 80 -e test
54
+ cucumber features/my_feature.feature
55
+
56
+ h2. How does it work
57
+
58
+ While Celerity is based on Java and requires JRuby to run, with Culerity you can still run your tests in your own Ruby Environment. When you run your features a separate JRuby process for Celerity is spawned and all Celerity Commands are redirected to this other process.
59
+
60
+ h2. Troubleshooting
61
+
62
+ I get a broken pipe error:
63
+ * make sure JRuby is installed and in your path: running _jruby -v_ should not produce an error
64
+
65
+ I get _Connection Refused_ errors
66
+ * make sure you have started a server in the test environment that runs on port 80
67
+
68
+
69
+ h2. Links to Celerity documentation
70
+
71
+ * "How to select elements":http://celerity.rubyforge.org/yard/Celerity/Container.html
72
+ * "FAQ":http://celerity.rubyforge.org/wiki/wiki.pl
73
+ * "Tutorial":http://celerity.rubyforge.org/wiki/wiki.pl?GettingStarted
74
+ * "API docs":http://celerity.rubyforge.org/yard/
75
+
76
+ h2. Links
77
+
78
+ * "cucumber":http://github.com/aslakhellesoy/cucumber/wikis
79
+ * "celerity":http://celerity.rubyforge.org
80
+ * "jruby":http://jruby.codehaus.org
81
+ * "rspec":http://rspec.info
82
+ * "htmlunit":http://htmlunit.sourceforge.net/
83
+
84
+ h2. Contact
85
+
86
+ Written 2009 by Alexander Lang, contact alex[at]upstream-berlin.com or http://github.com/langalex, released under the MIT license
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 1
4
+ :patch: 1
@@ -0,0 +1,20 @@
1
+ class CulerityGenerator < Rails::Generator::Base
2
+
3
+ def initialize(runtime_args, runtime_options = {})
4
+ Dir.mkdir('features/step_definitions') unless File.directory?('features/step_definitions')
5
+ super
6
+ end
7
+
8
+ def manifest
9
+ record do |m|
10
+ m.template 'common_celerity.rb', 'features/step_definitions/common_celerity.rb'
11
+ end
12
+ end
13
+
14
+ protected
15
+
16
+ def banner
17
+ "Usage: #{$0} culerity"
18
+ end
19
+
20
+ end
@@ -0,0 +1,70 @@
1
+ Before do
2
+ @server = Culerity::run_server
3
+ @browser = Culerity::RemoteBrowserProxy.new @server
4
+ @host = 'http://localhost'
5
+ end
6
+
7
+ After do
8
+ @browser.close
9
+ @browser.exit
10
+ @server.close
11
+ end
12
+
13
+ When /I press "(.*)"/ do |button|
14
+ @browser.button(:text, button).click
15
+ assert_successful_response
16
+ end
17
+
18
+ When /I follow "(.*)"/ do |link|
19
+ @browser.link(:text, /#{link}/).click
20
+ assert_successful_response
21
+ end
22
+
23
+ When /I fill in "(.*)" for "(.*)"/ do |value, field|
24
+ @browser.text_field(:id, find_label(field).for).set(value)
25
+ end
26
+
27
+ When /I check "(.*)"/ do |field|
28
+ @browser.check_box(:id, find_label(field).for).set(true)
29
+ end
30
+
31
+ When /^I uncheck "(.*)"$/ do |field|
32
+ @browser.check_box(:id, find_label(field).for).set(false)
33
+ end
34
+
35
+ When /I choose "(.*)"/ do |field|
36
+ @browser.radio(:id, find_label(field).for).set(true)
37
+ end
38
+
39
+ When /I go to "(.*)"/ do |path|
40
+ @browser.goto @host + path
41
+ assert_successful_response
42
+ end
43
+
44
+ When "I wait for the AJAX call to finish" do
45
+ @browser.page.getEnclosingWindow().getThreadManager().joinAll(10000)
46
+ end
47
+
48
+
49
+ Then /I should see "(.*)"/ do |text|
50
+ @browser.html.should =~ /#{text}/m
51
+ end
52
+
53
+ Then /I should not see "(.*)"/ do |text|
54
+ @browser.html.should_not =~ /#{text}/m
55
+ end
56
+
57
+ def find_label(text)
58
+ @browser.label :text, text
59
+ end
60
+
61
+ def assert_successful_response
62
+ status = @browser.page.web_response.status_code
63
+ if(status == 302 || status == 301)
64
+ location = @browser.page.web_response.get_response_header_value('Location')
65
+ puts "Being redirected to #{location}"
66
+ @browser.goto location
67
+ elsif status != 200
68
+ raise "Brower returned Response Code #{@browser.page.web_response.status_code}"
69
+ end
70
+ end
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+ require 'celerity'
3
+
4
+
5
+ module Culerity
6
+ class CelerityServer
7
+
8
+ def initialize(_in, _out)
9
+ @browser = Celerity::Browser.new
10
+ @proxies = {}
11
+
12
+ while(true)
13
+ call = eval _in.gets.to_s.strip
14
+ return if call == ["_exit_"]
15
+ unless call.nil?
16
+ begin
17
+ result = target(call.first).send call[1], *call[2..-1]
18
+ _out << "[:return, #{proxify result}]\n"
19
+ rescue => e
20
+ _out << "[:exception, \"#{e.class}\", #{e.message.inspect}]\n"
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ private
28
+
29
+ def target(object_id)
30
+ if object_id == 'browser'
31
+ @browser
32
+ else
33
+ @proxies[object_id]
34
+ end
35
+ end
36
+
37
+ def proxify(result)
38
+ if [String, TrueClass, FalseClass, Fixnum, Float, NilClass].include?(result.class)
39
+ result.inspect
40
+ else
41
+ @proxies[result.object_id] = result
42
+ "Culerity::RemoteObjectProxy.new(#{result.object_id}, @io)"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ module Culerity
2
+
3
+ class RemoteBrowserProxy < RemoteObjectProxy
4
+ def initialize(io)
5
+ @io = io
6
+ end
7
+
8
+ private
9
+
10
+ def remote_object_id
11
+ '"browser"'
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,33 @@
1
+ module Culerity
2
+
3
+ class RemoteObjectProxy
4
+ def initialize(remote_object_id, io)
5
+ @remote_object_id = remote_object_id
6
+ @io = io
7
+ end
8
+
9
+ def method_missing(name, *args)
10
+ @io << "[#{remote_object_id}, \"#{name}\", #{args.map{|a| a.inspect}.join(', ')}]\n"
11
+ process_result @io.gets.to_s.strip
12
+ end
13
+
14
+ def exit
15
+ @io << '["_exit_"]'
16
+ end
17
+
18
+ private
19
+
20
+ def process_result(result)
21
+ res = eval result
22
+ if res.first == :return
23
+ res[1]
24
+ elsif res.first == :exception
25
+ raise "#{res[1]}: #{res[2]}"
26
+ end
27
+ end
28
+
29
+ def remote_object_id
30
+ @remote_object_id
31
+ end
32
+ end
33
+ end
data/lib/culerity.rb ADDED
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/culerity/remote_object_proxy'
2
+ require File.dirname(__FILE__) + '/culerity/remote_browser_proxy'
3
+
4
+ module Culerity
5
+
6
+ def self.run_server
7
+ IO.popen("jruby #{__FILE__}", 'r+')
8
+ end
9
+
10
+ end
11
+
12
+ if __FILE__ == $0
13
+ require File.dirname(__FILE__) + '/culerity/celerity_server'
14
+ Culerity::CelerityServer.new STDIN, STDOUT
15
+ end
@@ -0,0 +1,70 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Culerity::CelerityServer do
4
+ before(:each) do
5
+ @browser = stub 'browser'
6
+ Celerity::Browser.stub!(:new).and_return(@browser)
7
+ end
8
+
9
+ it "should pass the method call to the selerity browser" do
10
+ @browser.should_receive(:goto).with('/homepage')
11
+ _in = stub 'in'
12
+ _in.stub!(:gets).and_return("[\"browser\", \"goto\", \"/homepage\"]\n", "[\"_exit_\"]\n")
13
+ _out = stub 'out', :<< => nil
14
+ Culerity::CelerityServer.new(_in, _out)
15
+ end
16
+
17
+ it "should send back the return value of the call" do
18
+ @browser.stub!(:goto).and_return(true)
19
+ _in = stub 'in'
20
+ _in.stub!(:gets).and_return("[\"browser\", \"goto\", \"/homepage\"]\n", "[\"_exit_\"]\n")
21
+ _out = stub 'out'
22
+ _out.should_receive(:<<).with("[:return, true]\n")
23
+ Culerity::CelerityServer.new(_in, _out)
24
+ end
25
+
26
+ it "should ignore empty inputs" do
27
+ _in = stub 'in'
28
+ _in.stub!(:gets).and_return("\n", "[\"_exit_\"]\n")
29
+ _out = stub 'out'
30
+ _out.should_not_receive(:<<)
31
+ Culerity::CelerityServer.new(_in, _out)
32
+ end
33
+
34
+ it "should send back a proxy if the return value is not a string, number, nil or boolean" do
35
+ @browser.stub!(:goto).and_return(stub('123', :object_id => 456))
36
+ _in = stub 'in'
37
+ _in.stub!(:gets).and_return("[\"browser\", \"goto\", \"/homepage\"]\n", "[\"_exit_\"]\n")
38
+ _out = stub 'out'
39
+ _out.should_receive(:<<).with("[:return, Culerity::RemoteObjectProxy.new(456, @io)]\n")
40
+ Culerity::CelerityServer.new(_in, _out)
41
+ end
42
+
43
+ it "should pass the method call to a proxy" do
44
+ proxy = stub('123', :object_id => 456)
45
+ @browser.stub!(:goto).and_return(proxy)
46
+ _in = stub 'in'
47
+ _in.stub!(:gets).and_return("[\"browser\", \"goto\", \"/homepage\"]\n", "[456, \"goto_2\", \"1\"]", "[\"_exit_\"]\n")
48
+ _out = stub 'out', :<< => nil
49
+ proxy.should_receive(:goto_2).with('1')
50
+ Culerity::CelerityServer.new(_in, _out)
51
+ end
52
+
53
+ it "should pass multiple method calls" do
54
+ @browser.should_receive(:goto).with('/homepage')
55
+ @browser.should_receive(:goto).with('/page2')
56
+ _in = stub 'in'
57
+ _in.stub!(:gets).and_return("[\"browser\", \"goto\", \"/homepage\"]\n", "[\"browser\", \"goto\", \"/page2\"]\n", "[\"_exit_\"]\n")
58
+ _out = stub 'out', :<< => nil
59
+ Culerity::CelerityServer.new(_in, _out)
60
+ end
61
+
62
+ it "should return an exception" do
63
+ @browser.stub!(:goto).and_raise(RuntimeError.new('test exception'))
64
+ _in = stub 'in'
65
+ _in.stub!(:gets).and_return("[\"browser\", \"goto\", \"/homepage\"]\n", "[\"_exit_\"]\n")
66
+ _out = stub 'out'
67
+ _out.should_receive(:<<).with("[:exception, \"RuntimeError\", \"test exception\"]\n")
68
+ Culerity::CelerityServer.new(_in, _out)
69
+ end
70
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Culerity::RemoteBrowserProxy do
4
+ it "should send the serialized method call to the output" do
5
+ io = stub 'io', :gets => '[return, :okay]'
6
+ io.should_receive(:<<).with("[\"browser\", \"goto\", \"/homepage\"]\n")
7
+ proxy = Culerity::RemoteBrowserProxy.new io
8
+ proxy.goto '/homepage'
9
+ end
10
+
11
+ it "should return the deserialized return value" do
12
+ io = stub 'io', :gets => "[:return, :okay]\n", :<< => nil
13
+ proxy = Culerity::RemoteBrowserProxy.new io
14
+ proxy.goto.should == :okay
15
+ end
16
+
17
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Culerity::RemoteObjectProxy do
4
+ it "should send the serialized method call to the output" do
5
+ io = stub 'io', :gets => '[:return]'
6
+ io.should_receive(:<<).with("[345, \"goto\", \"/homepage\"]\n")
7
+ proxy = Culerity::RemoteObjectProxy.new 345, io
8
+ proxy.goto '/homepage'
9
+ end
10
+
11
+ it "should return the deserialized return value" do
12
+ io = stub 'io', :gets => "[:return, :okay]\n", :<< => nil
13
+ proxy = Culerity::RemoteObjectProxy.new 345, io
14
+ proxy.goto.should == :okay
15
+ end
16
+
17
+ it "should raise the received exception" do
18
+ io = stub 'io', :gets => "[:exception, \"RuntimeError\", \"test exception\"]", :<< => nil
19
+ proxy = Culerity::RemoteObjectProxy.new 345, io
20
+ lambda {
21
+ proxy.goto '/home'
22
+ }.should raise_error(RuntimeError, 'RuntimeError: test exception')
23
+ end
24
+
25
+ it "should send exit" do
26
+ io = stub 'io', :gets => '[:return]'
27
+ io.should_receive(:<<).with('["_exit_"]')
28
+ proxy = Culerity::RemoteObjectProxy.new 345, io
29
+ proxy.exit
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ if RUBY_PLATFORM != 'java'
2
+ puts "You need JRuby to run these specs"
3
+ exit -1
4
+ end
5
+
6
+ require File.dirname(__FILE__) + '/../lib/culerity'
7
+ require File.dirname(__FILE__) + '/../lib/culerity/celerity_server'
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: langalex-culerity
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Lang
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-25 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: cucumber
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: rspec
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0"
32
+ version:
33
+ description: Culerity integrates Cucumber and Celerity in order to test your application's full stack.
34
+ email: alex@upstream-berlin.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files: []
40
+
41
+ files:
42
+ - README.textile
43
+ - VERSION.yml
44
+ - generators/culerity
45
+ - generators/culerity/culerity_generator.rb
46
+ - generators/culerity/templates
47
+ - generators/culerity/templates/common_celerity.rb
48
+ - lib/culerity
49
+ - lib/culerity/celerity_server.rb
50
+ - lib/culerity/remote_browser_proxy.rb
51
+ - lib/culerity/remote_object_proxy.rb
52
+ - lib/culerity.rb
53
+ - spec/celerity_server_spec.rb
54
+ - spec/remote_browser_proxy_spec.rb
55
+ - spec/remote_object_proxy_spec.rb
56
+ - spec/spec_helper.rb
57
+ has_rdoc: true
58
+ homepage: http://github.com/langalex/culerity
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --inline-source
62
+ - --charset=UTF-8
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.2.0
81
+ signing_key:
82
+ specification_version: 2
83
+ summary: Culerity integrates Cucumber and Celerity in order to test your application's full stack.
84
+ test_files: []
85
+