cucumber_tree 0.0.1
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.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +83 -0
- data/Rakefile +9 -0
- data/cucumber_tree.gemspec +33 -0
- data/features/cookies_snapshot.feature +57 -0
- data/features/current_url_snapshot.feature +66 -0
- data/features/database_snapshot.feature +80 -0
- data/features/javascript.feature +43 -0
- data/features/step_definitions/cucumber_tree_steps.rb +38 -0
- data/features/support/env.rb +5 -0
- data/features/variables_snapshot.feature +33 -0
- data/lib/cucumber_tree.rb +75 -0
- data/lib/cucumber_tree/configuration.rb +17 -0
- data/lib/cucumber_tree/database_cleaner_hook.rb +2 -0
- data/lib/cucumber_tree/handlers.rb +4 -0
- data/lib/cucumber_tree/handlers/base.rb +11 -0
- data/lib/cucumber_tree/handlers/cookies.rb +23 -0
- data/lib/cucumber_tree/handlers/database.rb +25 -0
- data/lib/cucumber_tree/handlers/databases/postgresql.rb +36 -0
- data/lib/cucumber_tree/handlers/databases/sqlite.rb +26 -0
- data/lib/cucumber_tree/handlers/url.rb +18 -0
- data/lib/cucumber_tree/handlers/variables.rb +26 -0
- data/lib/cucumber_tree/hooks.rb +33 -0
- data/lib/cucumber_tree/temp_dir.rb +26 -0
- data/lib/cucumber_tree/version.rb +3 -0
- data/spec/cucumber_tree/handlers/cookies_spec.rb +31 -0
- data/spec/cucumber_tree/handlers/url_spec.rb +28 -0
- data/spec/cucumber_tree/handlers/variables_spec.rb +39 -0
- metadata +220 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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,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,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,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:
|