cucumber_tree 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rvmrc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cucumber_tree.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Gabriel Reis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,83 @@
1
+ # Cucumber Tree
2
+
3
+ Organize your features in a tree directory and don't waste your cpu time running the same steps over and over.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ group :test do
10
+ gem 'cucumber_tree', require: false
11
+ end
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ If you already have installed cucumber-rails, go to the next step. Otherwise execute:
18
+
19
+ $ rails g cucumber:install
20
+
21
+ Add the option "--require features" to the std_opts in config/cucumber.yml:
22
+
23
+ std_opts = "--require features --format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
24
+
25
+ Change the file "features/support/env.rb" to require 'cucumber_tree'. It should be after the 'cucumber/rails' line:
26
+
27
+ require 'cucumber/rails'
28
+ require 'cucumber_tree'
29
+
30
+ This gem depends on database_cleaner and overrides the default strategy to :truncation, so you could remove all the references to DatabaseCleaner inside features/support/env.rb
31
+
32
+ ## Usage
33
+
34
+ Given an application to manage products and the following scenarios:
35
+
36
+ 1. User signs in
37
+ 2. User adds a new product
38
+ 3. User edits a product
39
+
40
+ Using cucumber_tree your tests should be organized in a tree directory:
41
+
42
+ ```
43
+ |-- features
44
+ ` |-- sign_in.feature
45
+ `-- sign_in
46
+ |-- add_product.feature
47
+ `-- add_product
48
+ `-- edit_product.feature
49
+ ```
50
+
51
+ Each feature contains only the necessary steps:
52
+
53
+ features/sign_in.feature
54
+ Feature:
55
+ Scenario:
56
+ Given I am signed in
57
+ Then I should see a welcome message
58
+
59
+ features/sign_in/add_product.feature
60
+ Feature:
61
+ Scenario:
62
+ When I click to add a new product
63
+ And I create a new product
64
+ Then I should see a message for product creation
65
+
66
+ features/sign_in/add_product/edit_product.feature
67
+ Feature:
68
+ Scenario:
69
+ When I click to edit the product
70
+ And I update the product
71
+ Then I should see a message for product update
72
+
73
+ When you execute `$ cucumber` the file sign_in.feature is the first to run. When it's done, then a snapshot of the current state (database, cookies, current page) is taken. This snapshot is loaded and the file add_product.feature runs. Another snapshot and finally the file edit_product.feature runs.
74
+
75
+ If you execute `$ cucumber features/sign_in/add_product/edit_product.feature` then all the parent features will be executed before it.
76
+
77
+ ## Contributing
78
+
79
+ 1. Fork it
80
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
81
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
82
+ 4. Push to the branch (`git push origin my-new-feature`)
83
+ 5. Create new Pull Request
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+
3
+ task :default do
4
+ ["rspec", "cucumber"].each do |cmd|
5
+ puts "Starting to run #{cmd}..."
6
+ system(cmd)
7
+ raise "#{cmd} failed!" unless $?.exitstatus == 0
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/cucumber_tree/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Gabriel Reis"]
6
+ gem.email = ["gabriel.oreis@gmail.com"]
7
+ gem.description = %q{Organize your features in a tree directory and don't waste your CPU time running the same steps over and over.}
8
+ gem.summary = %q{Better way to organize your features}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "cucumber_tree"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = CucumberTree::VERSION
17
+
18
+ gem.add_runtime_dependency 'cucumber-rails', '>= 1.3.0'
19
+ gem.add_runtime_dependency 'database_cleaner', '>= 0.7.2'
20
+ gem.add_runtime_dependency 'rspec', '>= 2.9.0'
21
+
22
+ gem.add_development_dependency 'aruba', '>= 0.5.0'
23
+ gem.add_development_dependency 'bundler', '>= 1.1.0'
24
+ gem.add_development_dependency 'rails', '>= 3.2.8'
25
+ gem.add_development_dependency 'sqlite3', '>= 1.3.6'
26
+ gem.add_development_dependency 'pg', '>= 0.14.1'
27
+
28
+ # Dependencies that Rails puts inside apps.
29
+ gem.add_development_dependency 'sass-rails', '>= 3.2.5'
30
+ gem.add_development_dependency 'coffee-rails', '>= 3.2.2'
31
+ gem.add_development_dependency 'uglifier', '>= 1.2.4'
32
+ gem.add_development_dependency 'jquery-rails', '>= 2.0.2'
33
+ end
@@ -0,0 +1,57 @@
1
+ Feature: Cookies Snapshot
2
+ Scenario:
3
+ Given I have created a new rails app
4
+ And I write to "app/controllers/cookies_controller.rb" with:
5
+ """
6
+ class CookiesController < ApplicationController
7
+ def index
8
+ render text: cookies[:page]
9
+ end
10
+
11
+ def new
12
+ cookies[:page] = 'new cookie'
13
+ render nothing: true
14
+ end
15
+ end
16
+ """
17
+ And I write to "config/routes.rb" with:
18
+ """
19
+ TestApp::Application.routes.draw do
20
+ resources :cookies
21
+ end
22
+ """
23
+ And I write to "features/parent.feature" with:
24
+ """
25
+ Feature:
26
+ Scenario:
27
+ Given I go to the new cookie page
28
+ """
29
+ And I write to "features/parent/child.feature" with:
30
+ """
31
+ Feature:
32
+ Scenario:
33
+ When I go to the cookies display page
34
+ Then I should see "new cookie"
35
+ """
36
+ And I write to "features/step_definitions/all_steps.rb" with:
37
+ """
38
+ When /^I go to the new cookie page$/ do
39
+ visit '/cookies/new'
40
+ end
41
+
42
+ When /^I go to the cookies display page$/ do
43
+ visit '/cookies'
44
+ end
45
+
46
+ Then /^I should see "(.*)"$/ do |content|
47
+ page.should have_content(content)
48
+ end
49
+ """
50
+ And I run `bundle exec rake db:migrate`
51
+
52
+ When I run `bundle exec cucumber`
53
+ Then it should pass with:
54
+ """
55
+ 2 scenarios (2 passed)
56
+ 3 steps (3 passed)
57
+ """
@@ -0,0 +1,66 @@
1
+ Feature: Current Url Snapshot
2
+ Scenario:
3
+ Given I have created a new rails app
4
+ And I write to "app/controllers/users_controller.rb" with:
5
+ """
6
+ class UsersController < ApplicationController
7
+ def index
8
+ render text: 'Users Index'
9
+ end
10
+ end
11
+ """
12
+ And I write to "config/routes.rb" with:
13
+ """
14
+ TestApp::Application.routes.draw do
15
+ resources :users
16
+ end
17
+ """
18
+ And I write to "features/parent.feature" with:
19
+ """
20
+ Feature:
21
+ Scenario:
22
+ Given I go to the users page
23
+ """
24
+ And I write to "features/parent/child.feature" with:
25
+ """
26
+ Feature:
27
+ Scenario:
28
+ Then I should be on the users page
29
+ """
30
+ And I write to "features/another.feature" with:
31
+ """
32
+ Feature:
33
+ Scenario:
34
+ Given I go to the index page
35
+ """
36
+ And I write to "features/step_definitions/all_steps.rb" with:
37
+ """
38
+ When /^I go to the users page$/ do
39
+ visit '/users'
40
+ end
41
+
42
+ When /^I go to the index page$/ do
43
+ visit '/'
44
+ end
45
+
46
+ Then /^I should be on the users page$/ do
47
+ page.current_path.should == '/users'
48
+ end
49
+ """
50
+ And I run `bundle exec rake db:migrate`
51
+
52
+ # Running only child feature
53
+ When I run `bundle exec cucumber features/parent/child.feature`
54
+ Then it should pass with:
55
+ """
56
+ 2 scenarios (2 passed)
57
+ 2 steps (2 passed)
58
+ """
59
+
60
+ #Running entire suite test
61
+ When I run `bundle exec cucumber`
62
+ Then it should pass with:
63
+ """
64
+ 3 scenarios (3 passed)
65
+ 3 steps (3 passed)
66
+ """
@@ -0,0 +1,80 @@
1
+ Feature: Database Snapshot
2
+ Scenario: Sqlite
3
+ Given I have created a new rails app
4
+ And I write to "features/parent.feature" with:
5
+ """
6
+ Feature:
7
+ Scenario:
8
+ Given 1 user
9
+ """
10
+ And I write to "features/parent/child.feature" with:
11
+ """
12
+ Feature:
13
+ Scenario:
14
+ Then 1 user should be created
15
+ """
16
+ And I write to "features/step_definitions/all_steps.rb" with:
17
+ """
18
+ When /^(\d+) users?$/ do |count|
19
+ User.create
20
+ end
21
+
22
+ Then /^(\d+) users? should be created$/ do |count|
23
+ User.count.should == count.to_i
24
+ end
25
+ """
26
+ And I write to "features/z-last-feature-to-run.feature" with:
27
+ """
28
+ Feature:
29
+ Scenario: Testing truncation
30
+ Then 0 users should be created
31
+ """
32
+ And I run `rails g model user`
33
+ And I run `bundle exec rake db:migrate db:test:prepare`
34
+
35
+ When I run `bundle exec cucumber`
36
+ Then it should pass with:
37
+ """
38
+ 3 scenarios (3 passed)
39
+ 3 steps (3 passed)
40
+ """
41
+
42
+ Scenario: Postgresql
43
+ Given I have created a new rails app with postgresql
44
+ And I write to "features/parent.feature" with:
45
+ """
46
+ Feature:
47
+ Scenario:
48
+ Given 1 user
49
+ """
50
+ And I write to "features/parent/child.feature" with:
51
+ """
52
+ Feature:
53
+ Scenario:
54
+ Then 1 user should be created
55
+ """
56
+ And I write to "features/step_definitions/all_steps.rb" with:
57
+ """
58
+ When /^(\d+) users?$/ do |count|
59
+ User.create
60
+ end
61
+
62
+ Then /^(\d+) users? should be created$/ do |count|
63
+ User.count.should == count.to_i
64
+ end
65
+ """
66
+ And I write to "features/z-last-feature-to-run.feature" with:
67
+ """
68
+ Feature:
69
+ Scenario: Testing truncation
70
+ Then 0 users should be created
71
+ """
72
+ And I run `rails g model user`
73
+ And I run `bundle exec rake db:drop db:create db:migrate db:test:prepare`
74
+
75
+ When I run `bundle exec cucumber`
76
+ Then it should pass with:
77
+ """
78
+ 3 scenarios (3 passed)
79
+ 3 steps (3 passed)
80
+ """
@@ -0,0 +1,43 @@
1
+ Feature: Make sure DatabaseCleaner works with javascript tags
2
+ Scenario:
3
+ Given I have created a new rails app
4
+ And I write to "features/parent.feature" with:
5
+ """
6
+ Feature:
7
+ @javascript
8
+ Scenario:
9
+ Given 1 user
10
+ """
11
+ And I write to "features/parent/child.feature" with:
12
+ """
13
+ Feature:
14
+ @javascript
15
+ Scenario:
16
+ Then 1 user should be created
17
+ """
18
+ And I write to "features/step_definitions/all_steps.rb" with:
19
+ """
20
+ When /^(\d+) users?$/ do |count|
21
+ User.create
22
+ end
23
+
24
+ Then /^(\d+) users? should be created$/ do |count|
25
+ User.count.should == count.to_i
26
+ end
27
+ """
28
+ And I write to "features/z-last-feature-to-run.feature" with:
29
+ """
30
+ Feature:
31
+ @javascript
32
+ Scenario: Testing truncation
33
+ Then 0 users should be created
34
+ """
35
+ And I run `rails g model user`
36
+ And I run `bundle exec rake db:migrate db:test:prepare`
37
+
38
+ When I run `bundle exec cucumber`
39
+ Then it should pass with:
40
+ """
41
+ 3 scenarios (3 passed)
42
+ 3 steps (3 passed)
43
+ """
@@ -0,0 +1,38 @@
1
+ module CucumberTreeHelper
2
+ def rails_new(options={})
3
+ options[:name] ||= 'test_app'
4
+ run_simple "rails new #{options[:name]} --skip-bundle --skip-test-unit #{options[:args]}"
5
+ assert_passing_with('README')
6
+ cd options[:name]
7
+ end
8
+
9
+ def install_cucumber_tree(*options)
10
+ gem "cucumber_tree", group: :test, path: "#{File.expand_path('.')}", require: false
11
+ run_simple 'bundle exec rails generate cucumber:install'
12
+ replace_content('config/cucumber.yml', /std_opts = "/, 'std_opts = "--require features ')
13
+ append_to_file('features/support/env.rb', "require 'cucumber_tree'")
14
+ end
15
+
16
+ def replace_content(file, from_content, to_content)
17
+ content = with_file_content(file) { |content| content }
18
+ content = content.gsub(from_content, to_content)
19
+ overwrite_file(file, content)
20
+ end
21
+
22
+ def gem(name, options)
23
+ line = %{gem "#{name}", #{options.inspect}\n}
24
+ append_to_file('Gemfile', line)
25
+ end
26
+ end
27
+ World(CucumberTreeHelper)
28
+
29
+ Given /^I have created a new rails app$/ do
30
+ rails_new
31
+ install_cucumber_tree
32
+ end
33
+
34
+ Given /^I have created a new rails app with postgresql$/ do
35
+ `createuser --superuser test_app`
36
+ rails_new(args: '--database=postgresql')
37
+ install_cucumber_tree
38
+ end
@@ -0,0 +1,5 @@
1
+ require 'aruba/cucumber'
2
+
3
+ Before do
4
+ @aruba_timeout_seconds = 120
5
+ end
@@ -0,0 +1,33 @@
1
+ Feature: Variables Snapshot
2
+ Scenario:
3
+ Given I have created a new rails app
4
+ And I write to "features/parent.feature" with:
5
+ """
6
+ Feature:
7
+ Scenario:
8
+ Given one user
9
+ """
10
+ And I write to "features/parent/child.feature" with:
11
+ """
12
+ Feature:
13
+ Scenario:
14
+ Then that user should be present
15
+ """
16
+ And I write to "features/step_definitions/all_steps.rb" with:
17
+ """
18
+ When /^one user$/ do
19
+ @user = "Jack"
20
+ end
21
+
22
+ Then /^that user should be present$/ do
23
+ @user.should == "Jack"
24
+ end
25
+ """
26
+ And I run `bundle exec rake db:migrate db:test:prepare`
27
+
28
+ When I run `bundle exec cucumber`
29
+ Then it should pass with:
30
+ """
31
+ 2 scenarios (2 passed)
32
+ 2 steps (2 passed)
33
+ """
@@ -0,0 +1,75 @@
1
+ env_caller = caller.detect{|f| f =~ /\/env\.rb:/} && !caller.detect{|f| f =~ /\/environment\.rb:/}
2
+ if env_caller
3
+ require "cucumber_tree/version"
4
+ require "cucumber_tree/hooks"
5
+ require "cucumber_tree/configuration"
6
+ require "cucumber_tree/handlers"
7
+ require "cucumber_tree/temp_dir"
8
+ require "cucumber_tree/temp_dir"
9
+ require "cucumber_tree/database_cleaner_hook"
10
+
11
+ module CucumberTree
12
+
13
+ class << self
14
+
15
+ attr_accessor :handler_instances
16
+ attr_accessor :handler_classes
17
+
18
+ def load_snapshot(world, scenario)
19
+ parent_feature = scenario.feature.file.gsub(/\A(.*)\/.*(\.feature)\z/, '\1\2')
20
+ snapshot = snapshots[parent_feature]
21
+ instantiate_handlers(world, scenario)
22
+ if snapshot.present?
23
+ handler_instances.each do |handler|
24
+ handler.load(snapshot)
25
+ end
26
+ end
27
+ end
28
+
29
+ def save_snapshot(world, scenario)
30
+ feature_file = scenario.feature.file
31
+ if is_parent_feature?(feature_file)
32
+ snapshots[feature_file] = {}.tap do |snapshot|
33
+ handler_instances.each do |handler|
34
+ handler.save(snapshot)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def setup
41
+ TempDir.clear!
42
+ end
43
+
44
+ def register_handler(*handlers)
45
+ self.handler_classes ||= []
46
+ self.handler_classes += handlers
47
+ end
48
+
49
+ private
50
+
51
+ def is_parent_feature?(file)
52
+ dir_name = file.gsub(/\A(.*)(\.feature)\z/, '\1')
53
+ File.directory?(dir_name)
54
+ end
55
+
56
+ def instantiate_handlers(world, scenario)
57
+ self.handler_instances = handler_classes.map do |class_name|
58
+ class_name.new(world, scenario)
59
+ end
60
+ end
61
+
62
+ def snapshots
63
+ @snapshots ||= {}
64
+ end
65
+
66
+ end
67
+
68
+ # Handler::Url should always be the last
69
+ register_handler(Handler::Database.get_handler, Handler::Cookies, Handler::Variables, Handler::Url)
70
+
71
+ end
72
+ else
73
+ warn "WARNING: cucumber_tree required outside of env.rb. The rest of loading is being defered until env.rb is called.
74
+ To avoid this warning, move 'gem cucumber_tree' under only group :test in your Gemfile"
75
+ end
@@ -0,0 +1,17 @@
1
+ class Cucumber::Cli::Configuration
2
+ alias __cucumber_orig_feature_files__ feature_files
3
+
4
+ def feature_files
5
+ files = __cucumber_orig_feature_files__
6
+ missing_files = []
7
+
8
+ files.each do |file|
9
+ (file.count('/') - 1).times do
10
+ file = file.gsub(/\A(.*)\/.*(\.feature)(:\d+)?\z/, '\1\2')
11
+ missing_files << file if File.file?(file)
12
+ end
13
+ end
14
+
15
+ (missing_files + files).uniq.sort!
16
+ end
17
+ end
@@ -0,0 +1,2 @@
1
+ DatabaseCleaner.strategy = :truncation
2
+ Cucumber::Rails::Database.javascript_strategy = :truncation
@@ -0,0 +1,4 @@
1
+ require "cucumber_tree/handlers/database"
2
+ require "cucumber_tree/handlers/cookies"
3
+ require "cucumber_tree/handlers/variables"
4
+ require "cucumber_tree/handlers/url"
@@ -0,0 +1,11 @@
1
+ module CucumberTree
2
+ module Handler
3
+ class Base < Struct.new(:world, :scenario)
4
+
5
+ def page
6
+ world.page
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require "cucumber_tree/handlers/base"
2
+
3
+ module CucumberTree
4
+ module Handler
5
+ class Cookies < Base
6
+
7
+ def load(snapshot)
8
+ snapshot[:cookies].each do |name, value|
9
+ page.cookies[name] = value
10
+ end
11
+ end
12
+
13
+ def save(snapshot)
14
+ snapshot[:cookies] = {}.tap do |hash|
15
+ page.cookies.each do |name, value|
16
+ hash[name.to_sym] = value
17
+ end
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ require "cucumber_tree/handlers/base"
2
+ require "cucumber_tree/handlers/databases/sqlite"
3
+ require "cucumber_tree/handlers/databases/postgresql"
4
+
5
+ module CucumberTree
6
+ module Handler
7
+ module Database
8
+
9
+ def self.get_handler
10
+ @get_handler ||= begin
11
+ adapter = Rails.configuration.database_configuration[Rails.env]["adapter"]
12
+ case adapter
13
+ when /sqlite/
14
+ Sqlite
15
+ when /postgresql/
16
+ Postgresql
17
+ else
18
+ raise "Database not supported: #{adapter}"
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ require "cucumber_tree/handlers/base"
2
+
3
+ module CucumberTree
4
+ module Handler
5
+ module Database
6
+ class Postgresql < Base
7
+ def load(snapshot)
8
+ dump_file = snapshot[:postgres_file]
9
+ options = []
10
+ options << "-U #{db_config['username']}" if db_config['username'].present?
11
+ options << "-d #{db_config['database']}"
12
+ options << "-f #{dump_file}"
13
+ `psql #{options.join(' ')}`
14
+ end
15
+
16
+ def save(snapshot)
17
+ dump_file = ::CucumberTree::TempDir.file_name("postgres.dump")
18
+ options = []
19
+ options << "-f #{dump_file}"
20
+ options << "-U #{db_config['username']}" if db_config['username'].present?
21
+ options << "--exclude-table=schema_migrations"
22
+ options << "-a #{db_config['database']}"
23
+ `pg_dump #{options.join(' ')}`
24
+ snapshot[:postgres_file] = dump_file
25
+ end
26
+
27
+ private
28
+
29
+ def db_config
30
+ Rails.configuration.database_configuration[Rails.env]
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ require "cucumber_tree/handlers/base"
2
+
3
+ module CucumberTree
4
+ module Handler
5
+ module Database
6
+ class Sqlite < Base
7
+ def load(snapshot)
8
+ FileUtils.cp(snapshot[:sqlite_file], db_file)
9
+ end
10
+
11
+ def save(snapshot)
12
+ dump_file = ::CucumberTree::TempDir.file_name("dbfile.sqlite")
13
+ FileUtils.cp(db_file, dump_file)
14
+ snapshot[:sqlite_file] = dump_file
15
+ end
16
+
17
+ private
18
+
19
+ def db_file
20
+ Rails.root.join(Rails.configuration.database_configuration[Rails.env]["database"])
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ require "cucumber_tree/handlers/base"
2
+
3
+ module CucumberTree
4
+ module Handler
5
+ class Url < Base
6
+
7
+ def load(snapshot)
8
+ url = snapshot[:url]
9
+ page.visit url unless url.nil?
10
+ end
11
+
12
+ def save(snapshot)
13
+ snapshot[:url] = page.current_path
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require "cucumber_tree/handlers/base"
2
+
3
+ module CucumberTree
4
+ module Handler
5
+ class Variables < Base
6
+
7
+ EXCLUDED_VARIABLES = %w(@__cucumber_step_mother @__natural_language @integration_session @app @controller @response @request)
8
+
9
+ def load(snapshot)
10
+ snapshot[:variables].each do |name, value|
11
+ world.instance_variable_set(name, value)
12
+ end
13
+ end
14
+
15
+ def save(snapshot)
16
+ names = world.instance_variables.map { |var| var.to_s } - EXCLUDED_VARIABLES
17
+ snapshot[:variables] = {}.tap do |hash|
18
+ names.each do |name|
19
+ hash[name] = world.instance_variable_get(name)
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ require "cucumber/rspec/doubles"
2
+
3
+ module Capybara
4
+ class Session
5
+ def cookies
6
+ @cookies ||= begin
7
+ secret = Rails.application.config.secret_token
8
+ cookies = ActionDispatch::Cookies::CookieJar.new(secret)
9
+ cookies.stub(:close!)
10
+ cookies
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ Before do |scenario|
17
+ stub_cookies(page)
18
+ CucumberTree.load_snapshot(self, scenario)
19
+ end
20
+
21
+ After do |scenario|
22
+ CucumberTree.save_snapshot(self, scenario)
23
+ end
24
+
25
+ AfterConfiguration do
26
+ CucumberTree.setup
27
+ end
28
+
29
+ def stub_cookies(page)
30
+ request = ActionDispatch::Request.any_instance
31
+ request.stub(:cookie_jar).and_return{ page.cookies }
32
+ request.stub(:cookies).and_return{ page.cookies }
33
+ end
@@ -0,0 +1,26 @@
1
+ module CucumberTree
2
+ class TempDir
3
+
4
+ class << self
5
+
6
+ def clear!
7
+ tmp_path.children.each do |child|
8
+ child.rmtree
9
+ end
10
+ end
11
+
12
+ def file_name(name)
13
+ tmp_path.join(Time.now.to_f.to_s).tap(&:mkpath).join(name).to_path
14
+ end
15
+
16
+ private
17
+
18
+ def tmp_path
19
+ tmp_path = Rails.root.join('tmp','cucumber_tree')
20
+ tmp_path.mkpath unless tmp_path.exist?
21
+ tmp_path
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module CucumberTree
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,31 @@
1
+ require 'cucumber_tree/handlers/cookies'
2
+
3
+ describe CucumberTree::Handler::Cookies do
4
+
5
+ let(:world) { stub(:world, page: page) }
6
+ let(:page) { stub(:page, cookies: cookies) }
7
+ let(:handler) { described_class.new(world) }
8
+
9
+ describe "#load" do
10
+ let(:cookies) { {} }
11
+ let(:snapshot) { {cookies: {a: 1} } }
12
+
13
+ before { handler.load(snapshot) }
14
+
15
+ it "sets the cookies in the page" do
16
+ page.cookies.should == {a: 1}
17
+ end
18
+ end
19
+
20
+ describe "#save" do
21
+ let(:cookies) { {a: 1} }
22
+ let(:snapshot) { {} }
23
+
24
+ before { handler.save(snapshot) }
25
+
26
+ it "sets the cookies in the snapshot" do
27
+ snapshot[:cookies].should == {a: 1}
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ require 'cucumber_tree/handlers/url'
2
+
3
+ describe CucumberTree::Handler::Url do
4
+
5
+ let(:world) { stub(:world, page: page) }
6
+ let(:handler) { described_class.new(world) }
7
+
8
+ describe "#load" do
9
+ let(:page) { stub(:page) }
10
+ let(:snapshot) { {url: '/url'} }
11
+
12
+ it "visits the url" do
13
+ page.should_receive(:visit).with('/url')
14
+ handler.load(snapshot)
15
+ end
16
+ end
17
+
18
+ describe "#save" do
19
+ let(:page) { stub(:page, current_path: '/url' ) }
20
+ let(:snapshot) { {} }
21
+
22
+ before { handler.save(snapshot) }
23
+
24
+ it "sets the current url in the snapshot" do
25
+ snapshot[:url].should == '/url'
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ require 'cucumber_tree/handlers/variables'
2
+
3
+ describe CucumberTree::Handler::Variables do
4
+
5
+ let(:world) { Object.new }
6
+ let(:handler) { described_class.new(world) }
7
+
8
+ describe "#load" do
9
+ let(:snapshot) { {variables: {'@num' => 1} } }
10
+
11
+ before { handler.load(snapshot) }
12
+
13
+ it "sets the instance variables in the world" do
14
+ world.instance_variable_get('@num').should == 1
15
+ end
16
+ end
17
+
18
+ describe "#save" do
19
+ let(:snapshot) { {} }
20
+ let(:instance_variable_name) { "@num" }
21
+
22
+ before do
23
+ world.instance_variable_set(instance_variable_name, 1)
24
+ handler.save(snapshot)
25
+ end
26
+
27
+ it "sets the variables in the snapshot" do
28
+ snapshot[:variables].should == {'@num' => 1}
29
+ end
30
+
31
+ context "with excluded instance variable name" do
32
+ let(:instance_variable_name) { "@app" }
33
+
34
+ it "does not set the variable in the snapshot" do
35
+ snapshot[:variables].should == {}
36
+ end
37
+ end
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,220 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cucumber_tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gabriel Reis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: cucumber-rails
16
+ requirement: &70234007700840 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70234007700840
25
+ - !ruby/object:Gem::Dependency
26
+ name: database_cleaner
27
+ requirement: &70234007700360 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.7.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70234007700360
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70234007699900 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: 2.9.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70234007699900
47
+ - !ruby/object:Gem::Dependency
48
+ name: aruba
49
+ requirement: &70234007699440 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.5.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70234007699440
58
+ - !ruby/object:Gem::Dependency
59
+ name: bundler
60
+ requirement: &70234007698980 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: 1.1.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70234007698980
69
+ - !ruby/object:Gem::Dependency
70
+ name: rails
71
+ requirement: &70234007698520 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: 3.2.8
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70234007698520
80
+ - !ruby/object:Gem::Dependency
81
+ name: sqlite3
82
+ requirement: &70234007698060 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: 1.3.6
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70234007698060
91
+ - !ruby/object:Gem::Dependency
92
+ name: pg
93
+ requirement: &70234007697600 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: 0.14.1
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70234007697600
102
+ - !ruby/object:Gem::Dependency
103
+ name: sass-rails
104
+ requirement: &70234007697140 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 3.2.5
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *70234007697140
113
+ - !ruby/object:Gem::Dependency
114
+ name: coffee-rails
115
+ requirement: &70234007696680 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: 3.2.2
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *70234007696680
124
+ - !ruby/object:Gem::Dependency
125
+ name: uglifier
126
+ requirement: &70234007696220 !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: 1.2.4
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: *70234007696220
135
+ - !ruby/object:Gem::Dependency
136
+ name: jquery-rails
137
+ requirement: &70234006532320 !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: 2.0.2
143
+ type: :development
144
+ prerelease: false
145
+ version_requirements: *70234006532320
146
+ description: Organize your features in a tree directory and don't waste your CPU time
147
+ running the same steps over and over.
148
+ email:
149
+ - gabriel.oreis@gmail.com
150
+ executables: []
151
+ extensions: []
152
+ extra_rdoc_files: []
153
+ files:
154
+ - .gitignore
155
+ - .rspec
156
+ - Gemfile
157
+ - LICENSE
158
+ - README.md
159
+ - Rakefile
160
+ - cucumber_tree.gemspec
161
+ - features/cookies_snapshot.feature
162
+ - features/current_url_snapshot.feature
163
+ - features/database_snapshot.feature
164
+ - features/javascript.feature
165
+ - features/step_definitions/cucumber_tree_steps.rb
166
+ - features/support/env.rb
167
+ - features/variables_snapshot.feature
168
+ - lib/cucumber_tree.rb
169
+ - lib/cucumber_tree/configuration.rb
170
+ - lib/cucumber_tree/database_cleaner_hook.rb
171
+ - lib/cucumber_tree/handlers.rb
172
+ - lib/cucumber_tree/handlers/base.rb
173
+ - lib/cucumber_tree/handlers/cookies.rb
174
+ - lib/cucumber_tree/handlers/database.rb
175
+ - lib/cucumber_tree/handlers/databases/postgresql.rb
176
+ - lib/cucumber_tree/handlers/databases/sqlite.rb
177
+ - lib/cucumber_tree/handlers/url.rb
178
+ - lib/cucumber_tree/handlers/variables.rb
179
+ - lib/cucumber_tree/hooks.rb
180
+ - lib/cucumber_tree/temp_dir.rb
181
+ - lib/cucumber_tree/version.rb
182
+ - spec/cucumber_tree/handlers/cookies_spec.rb
183
+ - spec/cucumber_tree/handlers/url_spec.rb
184
+ - spec/cucumber_tree/handlers/variables_spec.rb
185
+ homepage: ''
186
+ licenses: []
187
+ post_install_message:
188
+ rdoc_options: []
189
+ require_paths:
190
+ - lib
191
+ required_ruby_version: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ! '>='
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ required_rubygems_version: !ruby/object:Gem::Requirement
198
+ none: false
199
+ requirements:
200
+ - - ! '>='
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ requirements: []
204
+ rubyforge_project:
205
+ rubygems_version: 1.8.17
206
+ signing_key:
207
+ specification_version: 3
208
+ summary: Better way to organize your features
209
+ test_files:
210
+ - features/cookies_snapshot.feature
211
+ - features/current_url_snapshot.feature
212
+ - features/database_snapshot.feature
213
+ - features/javascript.feature
214
+ - features/step_definitions/cucumber_tree_steps.rb
215
+ - features/support/env.rb
216
+ - features/variables_snapshot.feature
217
+ - spec/cucumber_tree/handlers/cookies_spec.rb
218
+ - spec/cucumber_tree/handlers/url_spec.rb
219
+ - spec/cucumber_tree/handlers/variables_spec.rb
220
+ has_rdoc: