mattscilipoti-cucumber-rails 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. data/.gitignore +3 -0
  2. data/History.txt +84 -0
  3. data/README.rdoc +38 -0
  4. data/Rakefile +19 -0
  5. data/VERSION +1 -0
  6. data/cucumber-rails.gemspec +84 -0
  7. data/generators/cucumber/USAGE +14 -0
  8. data/generators/cucumber/cucumber_generator.rb +196 -0
  9. data/generators/cucumber/templates/config/cucumber.yml.erb +7 -0
  10. data/generators/cucumber/templates/environments/cucumber.rb.erb +37 -0
  11. data/generators/cucumber/templates/script/cucumber +10 -0
  12. data/generators/cucumber/templates/step_definitions/capybara_steps.rb.erb +187 -0
  13. data/generators/cucumber/templates/step_definitions/web_steps_cs.rb.erb +136 -0
  14. data/generators/cucumber/templates/step_definitions/web_steps_de.rb.erb +136 -0
  15. data/generators/cucumber/templates/step_definitions/web_steps_es.rb.erb +136 -0
  16. data/generators/cucumber/templates/step_definitions/web_steps_no.rb.erb +114 -0
  17. data/generators/cucumber/templates/step_definitions/web_steps_pt-BR.rb.erb +140 -0
  18. data/generators/cucumber/templates/step_definitions/webrat_steps.rb.erb +258 -0
  19. data/generators/cucumber/templates/support/_rails_each_run.rb +29 -0
  20. data/generators/cucumber/templates/support/_rails_prefork.rb.erb +10 -0
  21. data/generators/cucumber/templates/support/capybara.rb +9 -0
  22. data/generators/cucumber/templates/support/edit_warning.txt +5 -0
  23. data/generators/cucumber/templates/support/paths.rb +27 -0
  24. data/generators/cucumber/templates/support/rails.rb.erb +4 -0
  25. data/generators/cucumber/templates/support/rails_spork.rb.erb +13 -0
  26. data/generators/cucumber/templates/support/webrat.rb +8 -0
  27. data/generators/cucumber/templates/tasks/cucumber.rake.erb +42 -0
  28. data/generators/feature/USAGE +12 -0
  29. data/generators/feature/feature_generator.rb +41 -0
  30. data/generators/feature/templates/feature.erb +59 -0
  31. data/generators/feature/templates/steps.erb +14 -0
  32. data/lib/cucumber/rails/action_controller.rb +65 -0
  33. data/lib/cucumber/rails/active_record.rb +36 -0
  34. data/lib/cucumber/rails/capybara_javascript_emulation.rb +61 -0
  35. data/lib/cucumber/rails/rspec.rb +10 -0
  36. data/lib/cucumber/rails/test_unit.rb +9 -0
  37. data/lib/cucumber/rails/world.rb +47 -0
  38. data/lib/cucumber/web/tableish.rb +75 -0
  39. data/spec/cucumber/web/tableish_spec.rb +160 -0
  40. data/spec/spec_helper.rb +6 -0
  41. data/tasks/rspec.rake +13 -0
  42. metadata +107 -0
@@ -0,0 +1,29 @@
1
+ # If you set this to false, any error raised from within your app will bubble
2
+ # up to your step definition and out to cucumber unless you catch it somewhere
3
+ # on the way. You can make Rails rescue errors and render error pages on a
4
+ # per-scenario basis by tagging a scenario or feature with the @allow-rescue tag.
5
+ #
6
+ # If you set this to true, Rails will rescue all errors and render error
7
+ # pages, more or less in the same way your application would behave in the
8
+ # default production environment. It's not recommended to do this for all
9
+ # of your scenarios, as this makes it hard to discover errors in your application.
10
+ ActionController::Base.allow_rescue = false
11
+
12
+ # If you set this to true, each scenario will run in a database transaction.
13
+ # You can still turn off transactions on a per-scenario basis, simply tagging
14
+ # a feature or scenario with the @no-txn tag. If you are using Capybara,
15
+ # tagging with @culerity or @javascript will also turn transactions off.
16
+ #
17
+ # If you set this to false, transactions will be off for all scenarios,
18
+ # regardless of whether you use @no-txn or not.
19
+ #
20
+ # Beware that turning transactions off will leave data in your database
21
+ # after each scenario, which can lead to hard-to-debug failures in
22
+ # subsequent scenarios. If you do this, we recommend you create a Before
23
+ # block that will explicitly put your database in a known state.
24
+ Cucumber::Rails::World.use_transactional_fixtures = true
25
+
26
+ # How to clean your database when transactions are turned off. See
27
+ # http://github.com/bmabey/database_cleaner for more info.
28
+ require 'database_cleaner'
29
+ DatabaseCleaner.strategy = :truncation
@@ -0,0 +1,10 @@
1
+ ENV["RAILS_ENV"] ||= "cucumber"
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
3
+
4
+ require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support
5
+ <% if framework == :rspec -%>
6
+ require 'cucumber/rails/rspec'
7
+ <% end -%>
8
+ require 'cucumber/rails/world'
9
+ require 'cucumber/rails/active_record'
10
+ require 'cucumber/web/tableish'
@@ -0,0 +1,9 @@
1
+ require 'capybara/rails'
2
+ require 'capybara/cucumber'
3
+ require 'capybara/session'
4
+ require 'cucumber/rails/capybara_javascript_emulation' # Lets you click links with onclick javascript handlers without using @culerity or @javascript
5
+ # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In
6
+ # order to ease the transition to Capybara we set the default here. If you'd
7
+ # prefer to use XPath just remove this line and adjust any selectors in your
8
+ # steps to use the XPath syntax.
9
+ Capybara.default_selector = :css
@@ -0,0 +1,5 @@
1
+ # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
2
+ # It is recommended to regenerate this file in the future when you upgrade to a
3
+ # newer version of cucumber-rails. Consider adding your own code to a new file
4
+ # instead of editing this one. Cucumber will automatically load all features/**/*.rb
5
+ # files.
@@ -0,0 +1,27 @@
1
+ module NavigationHelpers
2
+ # Maps a name to a path. Used by the
3
+ #
4
+ # When /^I go to (.+)$/ do |page_name|
5
+ #
6
+ # step definition in web_steps.rb
7
+ #
8
+ def path_to(page_name)
9
+ case page_name
10
+
11
+ when /the home\s?page/
12
+ '/'
13
+
14
+ # Add more mappings here.
15
+ # Here is an example that pulls values out of the Regexp:
16
+ #
17
+ # when /^(.*)'s profile page$/i
18
+ # user_profile_path(User.find_by_login($1))
19
+
20
+ else
21
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
22
+ "Now, go and add a mapping in #{__FILE__}"
23
+ end
24
+ end
25
+ end
26
+
27
+ World(NavigationHelpers)
@@ -0,0 +1,4 @@
1
+ <%= embed_file('support/edit_warning.txt') %>
2
+ <%= embed_template('support/_rails_prefork.rb.erb') %>
3
+ <%= embed_file("support/#{driver}.rb") %>
4
+ <%= embed_file('support/_rails_each_run.rb') %>
@@ -0,0 +1,13 @@
1
+ <%= embed_file('support/edit_warning.txt') %>
2
+ require 'rubygems'
3
+ require 'spork'
4
+
5
+ Spork.prefork do
6
+ <%= embed_template('support/_rails_prefork.rb.erb', ' ') %>
7
+
8
+ <%= embed_file("support/#{driver}.rb", ' ') %>
9
+ end
10
+
11
+ Spork.each_run do
12
+ <%= embed_file('support/_rails_each_run.rb', ' ') %>
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'webrat'
2
+ require 'webrat/core/matchers'
3
+
4
+ Webrat.configure do |config|
5
+ config.mode = :rails
6
+ config.open_error_files = false # Set to true if you want error pages to pop up in the browser
7
+ end
8
+
@@ -0,0 +1,42 @@
1
+ <%= embed_file('support/edit_warning.txt') %>
2
+
3
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
4
+
5
+ vendored_cucumber_bin = Dir["#{RAILS_ROOT}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
6
+ $LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
7
+
8
+ begin
9
+ require 'cucumber/rake/task'
10
+
11
+ namespace :cucumber do
12
+ Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
13
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
14
+ t.fork = true # You may get faster startup if you set this to false
15
+ t.profile = 'default'
16
+ end
17
+
18
+ Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
19
+ t.binary = vendored_cucumber_bin
20
+ t.fork = true # You may get faster startup if you set this to false
21
+ t.profile = 'wip'
22
+ end
23
+
24
+ desc 'Run all features'
25
+ task :all => [:ok, :wip]
26
+ end
27
+ desc 'Alias for cucumber:ok'
28
+ task :cucumber => 'cucumber:ok'
29
+
30
+ task :default => :cucumber
31
+
32
+ task :features => :cucumber do
33
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
34
+ end
35
+ rescue LoadError
36
+ desc 'cucumber rake task not available (cucumber not installed)'
37
+ task :cucumber do
38
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,12 @@
1
+ Description:
2
+ Generates a skeleton for a new feature. Both a simple .feature file and
3
+ a steps.rb file is generated. This generator should be used with moderation.
4
+ See http://github.com/aslakhellesoy/cucumber/wikis/feature-coupled-steps-antipattern
5
+ for details about the dangers involved.
6
+
7
+ This generator can take an optional list of attribute pairs similar to Rails'
8
+ built-in resource generator.
9
+
10
+ Examples:
11
+ `./script/generate feature post` # no attributes
12
+ `./script/generate feature post title:string body:text published:boolean`
@@ -0,0 +1,41 @@
1
+ # This generator generates a baic feature.
2
+ class FeatureGenerator < Rails::Generator::NamedBase
3
+ def manifest
4
+ record do |m|
5
+ m.directory 'features/step_definitions'
6
+ m.template 'feature.erb', "features/manage_#{plural_name}.feature"
7
+ m.template 'steps.erb', "features/step_definitions/#{singular_name}_steps.rb"
8
+
9
+ m.gsub_file 'features/support/paths.rb', /'\/'/mi do |match|
10
+ "#{match}\n when /the new #{singular_name} page/\n new_#{singular_name}_path\n"
11
+ end
12
+ end
13
+ end
14
+
15
+ class NamedArg
16
+ attr_reader :name
17
+ attr_reader :type
18
+
19
+ def initialize(s)
20
+ @name, @type = *s.split(':')
21
+ end
22
+
23
+ def value(n)
24
+ if @type == 'boolean'
25
+ (n % 2) == 0
26
+ else
27
+ "#{@name} #{n}"
28
+ end
29
+ end
30
+ end
31
+
32
+ def named_args
33
+ args.map{|arg| NamedArg.new(arg)}
34
+ end
35
+
36
+ protected
37
+
38
+ def banner
39
+ "Usage: #{$0} feature ModelName [field:type, field:type]"
40
+ end
41
+ end
@@ -0,0 +1,59 @@
1
+ Feature: Manage <%= plural_name %>
2
+ In order to [goal]
3
+ [stakeholder]
4
+ wants [behaviour]
5
+
6
+ Scenario: Register new <%= singular_name %>
7
+ Given I am on the new <%= singular_name %> page
8
+ <% keyword = 'When' -%>
9
+ <% named_args.each do |arg| -%>
10
+ <% if arg.type == 'boolean' -%>
11
+ <%= keyword %> I uncheck "<%= arg.name.humanize %>"
12
+ <% else -%>
13
+ <%= keyword %> I fill in "<%= arg.name.humanize %>" with "<%= arg.value(1) %>"
14
+ <% end -%>
15
+ <% keyword = 'And' -%>
16
+ <% end -%>
17
+ And I press "Create"
18
+ <% keyword = 'Then' -%>
19
+ <% named_args.each do |arg| -%>
20
+ <%= keyword %> I should see "<%= arg.value(1) %>"
21
+ <% keyword = 'And' -%>
22
+ <% end -%>
23
+
24
+ <% if IO.read('features/support/env.rb') =~ /capybara/n -%>
25
+ # Rails generates Delete links that use Javascript to pop up a confirmation
26
+ # dialog and then do a HTTP POST request (emulated DELETE request).
27
+ #
28
+ # Capybara must use Culerity or Selenium2 (webdriver) when pages rely on
29
+ # Javascript events. Only Culerity supports confirmation dialogs.
30
+ #
31
+ # cucumber-rails will turn off transactions for scenarios tagged with
32
+ # @selenium, @culerity, @javascript or @no-txn and clean the database with
33
+ # DatabaseCleaner after the scenario has finished. This is to prevent data
34
+ # from leaking into the next scenario.
35
+ #
36
+ # Culerity has some performance overhead, and there are two alternatives to using
37
+ # Culerity:
38
+ #
39
+ # a) You can remove the @culerity tag and run everything in-process, but then you
40
+ # also have to modify your views to use <button> instead: http://github.com/jnicklas/capybara/issues#issue/12
41
+ #
42
+ # b) Replace the @culerity tag with @emulate_rails_javascript. This will detect
43
+ # the onclick javascript and emulate its behaviour without a real Javascript
44
+ # interpreter.
45
+ #
46
+ @culerity
47
+ <% end -%>
48
+ Scenario: Delete <%= singular_name %>
49
+ Given the following <%= plural_name %>:
50
+ |<%= named_args.map(&:name).join('|') %>|
51
+ <% (1..4).each do |n| -%>
52
+ |<%= named_args.map{|arg| arg.value(n)}.join('|') %>|
53
+ <% end -%>
54
+ When I delete the 3rd <%= singular_name %>
55
+ Then I should see the following <%= plural_name %>:
56
+ |<%= named_args.map{|arg| arg.name.humanize}.join('|') %>|
57
+ <% [1,2,4].each do |n| -%>
58
+ |<%= named_args.map{|arg| arg.value(n)}.join('|') %>|
59
+ <% end -%>
@@ -0,0 +1,14 @@
1
+ Given /^the following <%= plural_name %>:$/ do |<%= plural_name %>|
2
+ <%= class_name %>.create!(<%= plural_name %>.hashes)
3
+ end
4
+
5
+ When /^I delete the (\d+)(?:st|nd|rd|th) <%= singular_name %>$/ do |pos|
6
+ visit <%= plural_name %>_url
7
+ within("table tr:nth-child(#{pos.to_i+1})") do
8
+ click_link "Destroy"
9
+ end
10
+ end
11
+
12
+ Then /^I should see the following <%= plural_name %>:$/ do |expected_<%= plural_name %>_table|
13
+ expected_<%= plural_name %>_table.diff!(tableish('table tr', 'td,th'))
14
+ end
@@ -0,0 +1,65 @@
1
+ if Rails.version.to_f >= 3.0
2
+ module ActionController #:nodoc:
3
+ module AllowRescueException
4
+ extend ActiveSupport::Concern
5
+ include ActiveSupport::Rescuable
6
+
7
+ private
8
+ def process_action(*args)
9
+ if ActionController::Base.allow_rescue
10
+ super
11
+ else
12
+ begin
13
+ super
14
+ rescue Exception => exception
15
+ raise(exception)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ ActionController::Base.class_eval do
23
+ cattr_accessor :allow_rescue
24
+ include ActionController::AllowRescueException
25
+ end
26
+ else
27
+ ActionController::Base.class_eval do
28
+ cattr_accessor :allow_rescue
29
+
30
+ alias_method :rescue_action_without_bypass, :rescue_action
31
+
32
+ def rescue_action(exception)
33
+ if ActionController::Base.allow_rescue
34
+ rescue_action_without_bypass(exception)
35
+ else
36
+ raise exception
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ begin
43
+ ActionController::Failsafe.class_eval do
44
+ alias_method :failsafe_response_without_bypass, :failsafe_response
45
+
46
+ def failsafe_response(exception)
47
+ raise exception
48
+ end
49
+ end
50
+ rescue NameError # Failsafe was introduced in Rails 2.3.2
51
+ ActionController::Dispatcher.class_eval do
52
+ def self.failsafe_response(output, status, exception = nil)
53
+ raise exception
54
+ end
55
+ end
56
+ end
57
+
58
+ Before('@allow-rescue') do
59
+ @__orig_allow_rescue = ActionController::Base.allow_rescue
60
+ ActionController::Base.allow_rescue = true
61
+ end
62
+
63
+ After('@allow-rescue') do
64
+ ActionController::Base.allow_rescue = @__orig_allow_rescue
65
+ end
@@ -0,0 +1,36 @@
1
+ puts 'INFO: Using mattscilipoti-cucumber-rails -v0.2.4'
2
+ if defined?(ActiveRecord::Base)
3
+ Before do
4
+ $__cucumber_global_use_txn = !!Cucumber::Rails::World.use_transactional_fixtures if $__cucumber_global_use_txn.nil?
5
+ end
6
+
7
+ Before('~@no-txn', '~@selenium', '~@culerity', '~@celerity', '~@javascript') do
8
+ Cucumber::Rails::World.use_transactional_fixtures = $__cucumber_global_use_txn
9
+ end
10
+
11
+ Before('@no-txn,@selenium,@culerity,@celerity,@javascript') do
12
+ Cucumber::Rails::World.use_transactional_fixtures = false
13
+ end
14
+
15
+ Before do
16
+ DatabaseCleaner.clean #WORKAROUND: transactional mysql does not reset pk seed unless 'cleaned'
17
+ if Cucumber::Rails::World.use_transactional_fixtures
18
+ run_callbacks :setup if respond_to?(:run_callbacks)
19
+ else
20
+ DatabaseCleaner.start
21
+ end
22
+ ActionMailer::Base.deliveries = [] if defined?(ActionMailer::Base)
23
+ end
24
+
25
+ After do
26
+ if Cucumber::Rails::World.use_transactional_fixtures
27
+ run_callbacks :teardown if respond_to?(:run_callbacks)
28
+ else
29
+ DatabaseCleaner.clean if Cucumber::Rails::World.clean_database_after
30
+ end
31
+ end
32
+ else
33
+ module Cucumber::Rails
34
+ def World.fixture_table_names; []; end # Workaround for projects that don't use ActiveRecord
35
+ end
36
+ end
@@ -0,0 +1,61 @@
1
+ module Cucumber
2
+ module Rails
3
+ module CapybaraJavascriptEmulation
4
+ def self.included(base)
5
+ base.class_eval do
6
+ alias_method :click_without_rails_javascript_emulation, :click
7
+ end
8
+ end
9
+
10
+ def click_with_rails_javascript_emulation
11
+ if link_with_onclick_from_rails?
12
+ Capybara::Driver::RackTest::Form.new(driver, js_form(self[:href], emulated_method)).submit(self)
13
+ else
14
+ click_without_rails_javascript_emulation
15
+ end
16
+ end
17
+
18
+
19
+ private
20
+ def js_form(action, emulated_method, method = 'POST')
21
+ js_form = node.document.create_element('form')
22
+ js_form['action'] = action
23
+ js_form['method'] = method
24
+
25
+ if emulated_method and emulated_method.downcase != method.downcase
26
+ input = node.document.create_element('input')
27
+ input['type'] = 'hidden'
28
+ input['name'] = '_method'
29
+ input['value'] = emulated_method
30
+ js_form.add_child(input)
31
+ end
32
+
33
+ js_form
34
+ end
35
+
36
+ def link_with_onclick_from_rails?
37
+ tag_name == 'a' and node['onclick'] =~ /var f = document\.createElement\('form'\); f\.style\.display = 'none';/
38
+ end
39
+
40
+ def emulated_method
41
+ node['onclick'][/m\.setAttribute\('value', '([^']*)'\)/, 1]
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ class Capybara::Driver::RackTest::Node
48
+ include Cucumber::Rails::CapybaraJavascriptEmulation
49
+ end
50
+
51
+ Before('@emulate_rails_javascript') do
52
+ Capybara::Driver::RackTest::Node.class_eval do
53
+ alias_method :click, :click_with_rails_javascript_emulation
54
+ end
55
+ end
56
+
57
+ After('@emulate_rails_javascript') do
58
+ Capybara::Driver::RackTest::Node.class_eval do
59
+ alias_method :click, :click_without_rails_javascript_emulation
60
+ end
61
+ end