capybara-workflows 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +199 -0
- data/Rakefile +2 -0
- data/capybara-workflows.gemspec +23 -0
- data/lib/capybara/workflows.rb +14 -0
- data/lib/capybara/workflows/version.rb +5 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e0ced3bcfbcf204817c8806227b5b79452b3e98e
|
4
|
+
data.tar.gz: 621b5b0a3fb3ddd880aa04d71f81fcbde9c5180f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b15ca25183a838ea484b862af871902f151ebbe926ddfd38022d7558ef5fb45184e24795f04d8c0f452c977943a1fe5f7d180a5a19dc3869099d37c902822336
|
7
|
+
data.tar.gz: 26ba2e5ba1fac9581fad180a32ddfb6cd9e93e44d1d49e3ff37610e370f9688371217709c6d5f5db94ffe480af95b3b4854f4a3c69f53418cd2aef52f8751635
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Nicholas Rutherford
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
# Capybara::Workflows
|
2
|
+
|
3
|
+
Organise your Capybara helper library into by-role workflow sets or [page objects](https://code.google.com/p/selenium/wiki/PageObjects).
|
4
|
+
|
5
|
+
Helpers are executed by the original Capybara session, which you provide by dependency injection, as if you'd written the code where you call the method. All your usual helpers are available.
|
6
|
+
|
7
|
+
Example:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
specify 'I can enter my qualifications' do
|
11
|
+
qualifications = QualificationWorkflows.new(self)
|
12
|
+
qualifications.add_course 'GCSE', 'Maths', 'A', 'Predicted'
|
13
|
+
qualifications.add_course 'A2', 'Other', 'A*', '2010'
|
14
|
+
qualifications.add_course 'AS', 'Chemistry', 'B', '2011'
|
15
|
+
expect(page).to have_css('tr', text: 'GCSE Maths A Predicted')
|
16
|
+
expect(page).to have_css('tr', text: 'A2 Other A* 2010')
|
17
|
+
expect(page).to have_css('tr', text: 'AS Chemistry B 2011')
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
Where you have defined the QualificationWorkflows class and its #add_course method as explained below.
|
22
|
+
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
Add to your Gemfile's test group:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem 'capybara-workflows'
|
30
|
+
```
|
31
|
+
|
32
|
+
And then execute:
|
33
|
+
|
34
|
+
$ bundle
|
35
|
+
|
36
|
+
Or install it yourself as:
|
37
|
+
|
38
|
+
$ gem install capybara-workflows
|
39
|
+
|
40
|
+
## Usage
|
41
|
+
|
42
|
+
How you group things is up to you. This could have been called Capybara::PageObjectModel instead, but I wasn't grouping them that way at time of writing, and don't want to stand on [site_prism's](https://github.com/natritmeyer/site_prism) toes.
|
43
|
+
|
44
|
+
That is to say, rather than having classes like
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
MemberWorkflows.new(self, email, password).log_in
|
48
|
+
```
|
49
|
+
|
50
|
+
you could instead have
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
MemberLoginPage.new(self).log_in(email, password)
|
54
|
+
```
|
55
|
+
|
56
|
+
or whichever structure you care to think of.
|
57
|
+
|
58
|
+
All this actually does is enable you to write lines of capybara test code in another class, and share it between test files, reducing LOC and increasing sharing.
|
59
|
+
|
60
|
+
The trick is executing that code in the context of the capybara session, not the object holding the helpers. That's why you pass the session in when initialising the object, and why you write workflow blocks rather than method definitions.
|
61
|
+
|
62
|
+
|
63
|
+
### Defining workflows
|
64
|
+
|
65
|
+
For simplicity you may want to start writing these class definitions directly into your test files, just to get started. See Loading workflows for some ideas how to reorganise later.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class MemberWorkflows < Capybara::Workflows::WorkflowSet
|
69
|
+
# sign in
|
70
|
+
workflow :login_with do |email, password|
|
71
|
+
visit '/member'
|
72
|
+
fill_in("member_email", :with => email)
|
73
|
+
fill_in("member_password", :with => password)
|
74
|
+
click_button("member_submit")
|
75
|
+
end
|
76
|
+
|
77
|
+
workflow :logout do
|
78
|
+
visit '/member'
|
79
|
+
click_on "Sign out"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
Here's something a little more complex, which tracks previous logins (if made through the same object's interface). The optional workflow parameter gives access to instance variables and other workflow definitions. It's passed to your block as its final argument.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
class MemberWorkflows < Capybara::Workflows::WorkflowSet
|
88
|
+
attr_accessor :logged_in, :email, :password
|
89
|
+
def initialize(session, email, password)
|
90
|
+
self.email = email
|
91
|
+
self.password = password
|
92
|
+
self.logged_in = false
|
93
|
+
super(session)
|
94
|
+
end
|
95
|
+
|
96
|
+
# sign in
|
97
|
+
workflow :login do |workflow|
|
98
|
+
unless workflow.logged_in
|
99
|
+
visit '/member'
|
100
|
+
fill_in("member_email", with: workflow.email)
|
101
|
+
fill_in("member_password", with: workflow.password)
|
102
|
+
click_button("member_submit")
|
103
|
+
workflow.logged_in = true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
workflow :logout do |workflow|
|
108
|
+
visit '/member'
|
109
|
+
click_on "Sign out"
|
110
|
+
workflow.logged_in = false
|
111
|
+
end
|
112
|
+
|
113
|
+
workflow :post_article do |title, body, workflow|
|
114
|
+
workflow.login unless workflow.logged_in
|
115
|
+
visit new_article_path
|
116
|
+
fill_in "Title", with: title
|
117
|
+
fill_in "Body", with: body
|
118
|
+
click_on "Post article"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
### Cucumber
|
126
|
+
|
127
|
+
Below demonstrates using workflows to help manage state between steps.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
Given(/^I am in a group$/) do
|
131
|
+
@group = member.groups.make
|
132
|
+
gm = @group.group_managers.make
|
133
|
+
@group_manager = GroupManagerWorkflows.new(self, gm.email, gm.password)
|
134
|
+
end
|
135
|
+
|
136
|
+
Then(/^my teacher can't monitor my progress$/) do
|
137
|
+
@group_manager.view_student_progress(@member.email)
|
138
|
+
expect(page).to have_content("has not given you permission to monitor their progress. Please ask them to add you to their supervisor list in their account settings page.")
|
139
|
+
end
|
140
|
+
|
141
|
+
or
|
142
|
+
|
143
|
+
When(/^I go to my account page$/) do
|
144
|
+
MemberWorkflows.new(self).login_with(@member.email, @member.password)
|
145
|
+
ensure_on edit_member_path
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
### RSpec
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
describe "doing stuff" do
|
153
|
+
let(:member) {Member.make}
|
154
|
+
before(:each) do
|
155
|
+
MemberWorkflows.new(self).login_with(@member.email, @member.password)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
### Loading workflows
|
161
|
+
|
162
|
+
Define workflow classes in spec/support, feature/support, or whichever directory you prefer that will be loaded before your tests run. Or require them explicitly in your tests.
|
163
|
+
|
164
|
+
One approach is to put the following snippet into spec/support/load_shared_test_lib.rb for RSpec, and features/support/load_shared_test_lib.rb for Cucumber
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
# -*- encoding : utf-8 -*-
|
168
|
+
Dir[
|
169
|
+
File.expand_path(
|
170
|
+
Rails.root.join 'test_helper_lib', '**', '*.rb'
|
171
|
+
)
|
172
|
+
].each {|f| require f}
|
173
|
+
```
|
174
|
+
|
175
|
+
We use:
|
176
|
+
|
177
|
+
```
|
178
|
+
-|
|
179
|
+
|- feature
|
180
|
+
|- spec
|
181
|
+
|- test_helper_lib
|
182
|
+
|- workflows
|
183
|
+
|- member_workflows.rb
|
184
|
+
|- etc
|
185
|
+
```
|
186
|
+
|
187
|
+
## State encapsulation
|
188
|
+
|
189
|
+
Managing state, or context of execution, with shared cucumber steps is not fun. Assigning workflow objects to ivars and letting them track who is logged in, what their attributes are, what they can do, etc, may ease the pain.
|
190
|
+
|
191
|
+
For RSpec state encapsulation may or may not be useful, since test statements share scope and are typically easier to manage than Cucumber. However, when sharing with Cucumber it may be simpler to reuse identical workflows.
|
192
|
+
|
193
|
+
## Contributing
|
194
|
+
|
195
|
+
1. Fork it ( https://github.com/nruth/capybara-workflows/fork )
|
196
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
197
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
198
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
199
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'capybara/workflows/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "capybara-workflows"
|
8
|
+
spec.version = Capybara::Workflows::VERSION
|
9
|
+
spec.authors = ["Nicholas Rutherford"]
|
10
|
+
spec.email = ["nick.rutherford@gmail.com"]
|
11
|
+
spec.summary = %q{Organise your Capybara helper library into by-role workflow sets or page objects}
|
12
|
+
spec.description = ""
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "capybara/workflows/version"
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
module Workflows
|
5
|
+
# for use in capybara integration tests
|
6
|
+
# session : the test session, where capybara and other libraries/helpers are available
|
7
|
+
class WorkflowSet < Struct.new(:session)
|
8
|
+
def self.workflow(name, &block)
|
9
|
+
workflow = Proc.new do |*args| session.instance_exec(*[*args, self], &block) end
|
10
|
+
define_method(name, &workflow)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capybara-workflows
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nicholas Rutherford
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: ''
|
42
|
+
email:
|
43
|
+
- nick.rutherford@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- capybara-workflows.gemspec
|
54
|
+
- lib/capybara/workflows.rb
|
55
|
+
- lib/capybara/workflows/version.rb
|
56
|
+
homepage: ''
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.2.2
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: Organise your Capybara helper library into by-role workflow sets or page
|
80
|
+
objects
|
81
|
+
test_files: []
|