rails-carrot 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest ADDED
@@ -0,0 +1,9 @@
1
+ Manifest
2
+ README
3
+ Rakefile
4
+ carrot.gemspec
5
+ lib/carrot.rb
6
+ lib/carrot/extend_server.rb
7
+ lib/carrot/rails.rb
8
+ lib/carrot/server.rb
9
+ lib/carrot/util/timeout.rb
data/README ADDED
@@ -0,0 +1,81 @@
1
+ You can use carrot with celerity, or another driver.
2
+
3
+ 1. gem 'carrot'
4
+
5
+ 2. add a celerity_helper
6
+
7
+ 3. Add some code in celerity_helper
8
+ require 'database_cleaner'
9
+ require 'celerity'
10
+ require 'carrot'
11
+
12
+ ENV["RAILS_ENV"] = 'celerity' # You can change it with your enviroment
13
+ require File.expand_path("../../config/environment", __FILE__)
14
+ require 'rspec/rails'
15
+
16
+
17
+
18
+ 4. Three test styles
19
+ a) Remote
20
+ Carrot.configure do |config|
21
+ config.run_server = false
22
+ config.app_host = "www.google.com"
23
+ end
24
+ Carrot.register_driver(Celerity::Browser.new)
25
+
26
+ b) Local
27
+ Carrot.configure do |config|
28
+ config.run_server = true
29
+ end
30
+ Carrot.register_driver(Celerity::Browser.new)
31
+ Carrot.boot
32
+
33
+ c) Local, server with external ruby
34
+
35
+ Carrot.configure do |config|
36
+ config.run_server = true
37
+ config.external_ruby = true
38
+ config.rails_command = "~/.rvm/gems/ruby-1.9.2-p0/bin/rails s -e celerity -p 3001"
39
+ config.project_path = "#{Rails.root}"
40
+ config.server_port = 3001
41
+ # config.server_debug = true
42
+ end
43
+ Carrot.register_driver(Celerity::Browser.new)
44
+ Carrot.boot
45
+
46
+ RSpec.configure do |config|
47
+ DatabaseCleaner.strategy = :truncation
48
+
49
+ config.before :each do
50
+ @browser = Carrot.driver # get native driver
51
+ DatabaseCleaner.clean
52
+ end
53
+
54
+ config.after :all do
55
+ Carrot.shutdown # shutdown server
56
+ DatabaseCleaner.clean
57
+ end
58
+
59
+ config.use_transactional_fixtures = false
60
+
61
+ end
62
+
63
+ 5 Test
64
+ a) get url
65
+ Carrot.url(path)
66
+ eg:
67
+ Carrot.url('/') => http://host/
68
+ Carrot.url('/hello') => http://host/hello
69
+
70
+ b) get native browser driver
71
+ Carrot.driver
72
+
73
+ 6 FAQ
74
+ a) Does Carrot support server with external ruby?
75
+ Yes, but it just supports jruby run rspec and run server using external ruby. I use jruby to create native java process to run server using external ruby.
76
+
77
+ If you want to use ruby to run rspec and run server using external ruby, you can create a new server class to support it or wait for my upgrade.
78
+
79
+
80
+
81
+
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('rails-carrot', '1.0.0') do |p|
6
+ p.description = "Carrot can make QA test easy with any integration test gem."
7
+ p.url = "http://github.com/sloanwu/carrot.git"
8
+ p.author = "Sloan Wu"
9
+ p.email = "sloanwu@gmail.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
data/carrot.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{carrot}
5
+ s.version = "1.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Sloan Wu"]
9
+ s.date = %q{2010-11-02}
10
+ s.description = %q{Carrot can make QA test easy with any integration test gem.}
11
+ s.email = %q{sloanwu@gmail.com}
12
+ s.extra_rdoc_files = ["lib/carrot.rb", "lib/carrot/extend_server.rb", "lib/carrot/rails.rb", "lib/carrot/server.rb", "lib/carrot/util/timeout.rb"]
13
+ s.files = ["Manifest", "Rakefile", "carrot.gemspec", "lib/carrot.rb", "lib/carrot/extend_server.rb", "lib/carrot/rails.rb", "lib/carrot/server.rb", "lib/carrot/util/timeout.rb"]
14
+ s.homepage = %q{http://github.com/sloanwu/carrot.git}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Carrot", "--main", "README"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{carrot}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Carrot can make QA test easy with any integration test gem.}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
@@ -0,0 +1,59 @@
1
+ require "java"
2
+ require 'carrot/util/timeout'
3
+ require 'uri'
4
+ require 'net/http'
5
+ require 'rack'
6
+ import java.lang.Runtime
7
+ import java.io.InputStreamReader
8
+ import java.io.BufferedReader
9
+
10
+ module Carrot
11
+ class ExtendServer
12
+ attr_accessor :server_process, :shutdown_process
13
+
14
+ def run()
15
+ Thread.new do
16
+ command = ["/bin/bash","-c", "cd #{Carrot.project_path} ; #{Carrot.rails_command}"].to_java(java.lang.String)
17
+ begin
18
+ @server_process = Runtime.getRuntime().exec(command);
19
+ if Carrot.server_debug
20
+ buf = BufferedReader.new(InputStreamReader.new(@server_process.get_input_stream))
21
+ while line = buf.readLine()
22
+ puts line
23
+ end
24
+ end
25
+ @server_process.wait_for
26
+ rescue Exception => e
27
+ puts e
28
+ end
29
+
30
+ end
31
+ Carrot.timeout(60) { if responsive? then true else sleep(0.5) and false end }
32
+ end
33
+
34
+ def shutdown
35
+ Thread.new do
36
+ command = ["/bin/bash","-c", "cd #{Carrot.project_path} ; kill `cat #{Carrot.project_path}/tmp/pids/server.pid`"].to_java(java.lang.String)
37
+ begin
38
+ @shutdown_process = Runtime.getRuntime().exec(command);
39
+ @shutdown_process.wait_for
40
+ @shutdown_process.destroy
41
+ rescue Exception => e
42
+ puts e
43
+ end
44
+ end
45
+ end
46
+
47
+ def responsive?
48
+ host = "127.0.0.1"
49
+ res = Net::HTTP.start(host, Carrot.server_port) { |http| http.get('/__identify__') }
50
+
51
+ unless res.nil?
52
+ return true
53
+ end
54
+ rescue Errno::ECONNREFUSED, Errno::EBADF
55
+ return false
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ require 'carrot'
2
+
3
+ Carrot.app = Rack::Builder.new do
4
+ map "/" do
5
+ if Rails.version.to_f >= 3.0
6
+ run Rails.application
7
+ else # Rails 2
8
+ use Rails::Rack::Static
9
+ run ActionController::Dispatcher.new
10
+ end
11
+ end
12
+ end.to_app
13
+
14
+ Carrot.asset_root = Rails.root.join('public')
15
+
@@ -0,0 +1,96 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'rack'
4
+ require 'carrot/util/timeout'
5
+ require 'carrot/rails'
6
+
7
+ module Carrot
8
+ class Server
9
+ class Identify
10
+ def initialize(app)
11
+ @app = app
12
+ end
13
+
14
+ def call(env)
15
+ if env["PATH_INFO"] == "/__identify__"
16
+ [200, {}, @app.object_id.to_s]
17
+ else
18
+ @app.call(env)
19
+ end
20
+ end
21
+ end
22
+
23
+ class << self
24
+ def ports
25
+ @ports ||= {}
26
+ end
27
+ end
28
+
29
+ attr_reader :app, :port
30
+
31
+ def initialize(app)
32
+ @app = app
33
+ end
34
+
35
+ def host
36
+ "127.0.0.1"
37
+ end
38
+
39
+ def url(path)
40
+ if path =~ /^http/
41
+ path
42
+ else
43
+ (Carrot.app_host || "http://#{host}:#{Carrot.server_port || port}") + path.to_s
44
+ end
45
+ end
46
+
47
+ def responsive?
48
+ res = Net::HTTP.start(host, @port) { |http| http.get('/__identify__') }
49
+
50
+ if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
51
+ return res.body == @app.object_id.to_s
52
+ end
53
+ rescue Errno::ECONNREFUSED, Errno::EBADF
54
+ return false
55
+ end
56
+
57
+ def boot
58
+ if Carrot.external_ruby
59
+ require 'carrot/extend_server'
60
+ Carrot.external_server = ExtendServer.new
61
+ Carrot.external_server.run
62
+ elsif @app
63
+ @port = Carrot::Server.ports[@app.object_id]
64
+
65
+ if not @port or not responsive?
66
+ @port = Carrot.server_port || find_available_port
67
+ Carrot::Server.ports[@app.object_id] = @port
68
+
69
+ Thread.new do
70
+ begin
71
+ require 'rack/handler/thin'
72
+ Thin::Logging.silent = true
73
+ Rack::Handler::Thin.run(Identify.new(@app), :Port => @port)
74
+ rescue LoadError
75
+ require 'rack/handler/webrick'
76
+ Rack::Handler::WEBrick.run(Identify.new(@app), :Port => @port, :AccessLog => [], :Logger => WEBrick::Log::new(nil, 0))
77
+ end
78
+ end
79
+
80
+ Carrot.timeout(10) { if responsive? then true else sleep(0.5) and false end }
81
+ end
82
+ end
83
+ end
84
+
85
+
86
+ private
87
+
88
+ def find_available_port
89
+ server = TCPServer.new('127.0.0.1', 0)
90
+ server.addr[1]
91
+ ensure
92
+ server.close if server
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,27 @@
1
+ module Carrot
2
+ class << self
3
+
4
+ ##
5
+ # Provides timeout similar to standard library Timeout, but avoids threads
6
+ #
7
+ def timeout(seconds = 1, driver = nil, &block)
8
+ start_time = Time.now
9
+
10
+ result = nil
11
+
12
+ until result
13
+ return result if result = yield
14
+
15
+ delay = seconds - (Time.now - start_time)
16
+ if delay <= 0
17
+ raise TimeoutError
18
+ end
19
+
20
+ driver && driver.wait_until(delay)
21
+
22
+ sleep(0.05)
23
+ end
24
+ end
25
+
26
+ end
27
+ end
data/lib/carrot.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'timeout'
2
+ require 'nokogiri'
3
+ require 'xpath'
4
+
5
+ module Carrot
6
+ class CarrotError < StandardError; end
7
+ class DriverNotFoundError < CarrotError; end
8
+ class ElementNotFound < CarrotError; end
9
+ class UnselectNotAllowed < CarrotError; end
10
+ class NotSupportedByDriverError < CarrotError; end
11
+ class TimeoutError < CarrotError; end
12
+ class LocateHiddenElementError < CarrotError; end
13
+ class InfiniteRedirectError < TimeoutError; end
14
+
15
+ class << self
16
+ attr_accessor :asset_root, :app_host, :run_server, :default_host
17
+ attr_accessor :server_port
18
+ attr_accessor :driver
19
+ attr_accessor :app
20
+ attr_accessor :external_ruby, :rails_command, :project_path
21
+ attr_accessor :external_server, :server_debug
22
+
23
+ ##
24
+ #
25
+ # Configure Carrot to suit your needs.
26
+ #
27
+ # Carrot.configure do |config|
28
+ # config.run_server = false
29
+ # config.app_host = 'http://www.google.com'
30
+ # end
31
+ #
32
+ # === Configurable options
33
+ #
34
+ # [asset_root = String] Where static assets are located, used by save_and_open_page
35
+ # [app_host = String] The default host to use when giving a relative URL to visit
36
+ # [run_server = Boolean] Whether to start a Rack server for the given Rack app (Default: true)
37
+ # [default_selector = :css/:xpath] Methods which take a selector use the given type by default (Default: CSS)
38
+ # [default_wait_time = Integer] The number of seconds to wait for asynchronous processes to finish (Default: 2)
39
+ # [ignore_hidden_elements = Boolean] Whether to ignore hidden elements on the page (Default: false)
40
+ #
41
+
42
+ def configure
43
+ yield self
44
+ end
45
+
46
+ def url(path)
47
+ @rack_server.url(path)
48
+ end
49
+
50
+ def register_driver(obj)
51
+ @driver = obj
52
+ end
53
+
54
+ def boot
55
+ @rack_server = Carrot::Server.new(@app)
56
+ @rack_server.boot if Carrot.run_server
57
+ end
58
+
59
+ def shutdown
60
+ @external_server.shutdown if @external_server
61
+ end
62
+
63
+ end
64
+
65
+ autoload :Server, 'carrot/server'
66
+
67
+ end
68
+
69
+ Carrot.configure do |config|
70
+ config.run_server = true
71
+ config.external_ruby = false
72
+ config.server_debug = false
73
+ config.server_port = 3000
74
+ end
75
+
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{rails-carrot}
5
+ s.version = "1.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Sloan Wu"]
9
+ s.date = %q{2010-11-02}
10
+ s.description = %q{Carrot can make QA test easy with any integration test gem.}
11
+ s.email = %q{sloanwu@gmail.com}
12
+ s.extra_rdoc_files = ["README", "lib/carrot.rb", "lib/carrot/extend_server.rb", "lib/carrot/rails.rb", "lib/carrot/server.rb", "lib/carrot/util/timeout.rb"]
13
+ s.files = ["Manifest", "README", "Rakefile", "carrot.gemspec", "lib/carrot.rb", "lib/carrot/extend_server.rb", "lib/carrot/rails.rb", "lib/carrot/server.rb", "lib/carrot/util/timeout.rb", "rails-carrot.gemspec"]
14
+ s.homepage = %q{http://github.com/sloanwu/carrot.git}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rails-carrot", "--main", "README"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{rails-carrot}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Carrot can make QA test easy with any integration test gem.}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-carrot
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Sloan Wu
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-02 00:00:00 +08:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Carrot can make QA test easy with any integration test gem.
22
+ email: sloanwu@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README
29
+ - lib/carrot.rb
30
+ - lib/carrot/extend_server.rb
31
+ - lib/carrot/rails.rb
32
+ - lib/carrot/server.rb
33
+ - lib/carrot/util/timeout.rb
34
+ files:
35
+ - Manifest
36
+ - README
37
+ - Rakefile
38
+ - carrot.gemspec
39
+ - lib/carrot.rb
40
+ - lib/carrot/extend_server.rb
41
+ - lib/carrot/rails.rb
42
+ - lib/carrot/server.rb
43
+ - lib/carrot/util/timeout.rb
44
+ - rails-carrot.gemspec
45
+ has_rdoc: true
46
+ homepage: http://github.com/sloanwu/carrot.git
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --line-numbers
52
+ - --inline-source
53
+ - --title
54
+ - Rails-carrot
55
+ - --main
56
+ - README
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 1
74
+ - 2
75
+ version: "1.2"
76
+ requirements: []
77
+
78
+ rubyforge_project: rails-carrot
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Carrot can make QA test easy with any integration test gem.
83
+ test_files: []
84
+