dkastner-capybara-wheel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 48f3c56080572f38abc650588314ebc0335646c9
4
+ data.tar.gz: 86b2298ebc7e77c2970c0c0d7c4d7d9ab91aa2e4
5
+ SHA512:
6
+ metadata.gz: a090305573a3ae190140824d8596274db2c9fe94d71c253cbaff6ab22062ff002624d561a189b939ceb49bf73ecc770941e36ed3c6653795fed4391a5e4bf507
7
+ data.tar.gz: daf6887577eb28636cd9afc594bb2ed8057c7710d4e036b351a8e39a607e852ad455548dfd5df8afb6f17c3b49541546868b32c4cc306874557febc514d97c35
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in capybara-wheel.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Gabriel Rotbart
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,260 @@
1
+ # Capybara::Wheel
2
+ > Keeping the rodent on track
3
+
4
+ Capybara wheel is a page model framework which natively and (hopefully) easily enforces stability coventions:
5
+
6
+ - No memoization. Every action or query relating to the page should make a new find callback to the actual page.
7
+ - Enforces native Capybara wait time when interacting with the page if the element is not there (yet) or changed.
8
+
9
+ - No access to capybara directly from the specs.
10
+ - Enforces single point of reference to selectors / elements.
11
+ - Also helps reducing memoizations.
12
+
13
+ - Element hierarchy structure to scope finds to a specific section of the page.
14
+ - Reduces ambiguity.
15
+
16
+ *A special thank you to @woollyams for the initial concept*
17
+
18
+ ## Why Wheel?
19
+
20
+ Browser driven acceptance tests are notorious for being unstable and hard to maintain. The main culprits are:
21
+
22
+ 1. Timing issues which result in unstable waits and "is the page loaded?" queries accross the specs.
23
+
24
+ 2. Memoizing the state of the page (e.g. `search_result = Capybara.find('li')` ) at a certain time. Each spec run might memoize a different state, leading to unstable tests.
25
+
26
+ 3. No convention around page interactions (e.g. sometimes calling a page model, sometimes a native find with a selector).
27
+
28
+ Wheel solves all these by forcing the spec to always act or query the currect state of the page.
29
+ If the page is not in a state that the spec expects, the native Capybara wait will be used until it is; removing the need to `sleep` or build mechanics to test for page loads.
30
+
31
+ Specs are always written in one uniform, clean, way - always calling the same model when dealing with the same page / element. No more hunting multiple specs to change a selector.
32
+
33
+ The Element model DSL is still eaily customisable just like "normal" page model classes so domain specfic applications are just as easy, resulting in descriptive, easy to read specs.
34
+
35
+ ## Example spec:
36
+
37
+ feature "Supervillan Console" do
38
+
39
+ let(:supervillan_console) { SuperVillanConsole.new }
40
+
41
+ it 'can destroy the world with the push of a button' do
42
+ supervillan_console.visit do |page|
43
+ page.button_of_doom.should be_present
44
+ page.button_of_doom.click
45
+
46
+ # assert that world was destroyed
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ More spec goodness below.
53
+
54
+ ## Installation
55
+
56
+ Add this line to your application's Gemfile:
57
+
58
+ gem 'capybara-wheel'
59
+
60
+ And then execute:
61
+
62
+ $ bundle
63
+
64
+ Or install it yourself as:
65
+
66
+ $ gem install capybara-wheel
67
+
68
+ ## Usage
69
+
70
+ In spec_helper.rb:
71
+
72
+ $ require 'capybara/wheel'
73
+
74
+ **Important: Capybara Wheel overrides Capybara native `feature` method to inject new behavior. This means it should be required instead or Capybara**
75
+
76
+ ## Modeling
77
+
78
+ ### Page Model
79
+
80
+
81
+ To model a new page:
82
+
83
+ class NewPage < Capybara::Wheel::Page
84
+
85
+ A page needs to implement two methods:
86
+
87
+ def path
88
+ # implament to support visiting the page directly
89
+ # Rails apps can include Rails.application.routes.url_helpers to access the url helpers
90
+ # Other applications should implament a relative url
91
+ end
92
+
93
+ and
94
+
95
+ def on_page?
96
+ # Capybara Wheel calls this method before excuting the page block (see Specs section below below)
97
+ # Recommended: Use Wheel native Page method has_title?('Title')
98
+ # e.g. has_title?('Login')
99
+
100
+ # Or: Use Capybara.find(any selector you expect would be on a loaded page)
101
+ # e.g. Capybara.find('h1', text: 'Login Page')
102
+ end
103
+
104
+ **_Example:_**
105
+
106
+ class SuperVillanConsole << Capybara::Wheel::Page
107
+
108
+ def path
109
+ super_villan_console_path
110
+ end
111
+
112
+ def on_page?
113
+ has_title?('Destroy all humans')
114
+ end
115
+ end
116
+
117
+ ***
118
+
119
+ ### Element model
120
+
121
+ #### Element
122
+
123
+ Once inside a Page model, it has access to the `element` method.
124
+
125
+ element 'ElementName', 'selector' *optional block*
126
+
127
+ # Wheel recommends using a name that follows the class constant name convention (i.e CamelCase)
128
+ # as an object will be created and assigned this name (see below)
129
+
130
+ The `element` method does several important things:
131
+
132
+ 1. It defines a Page method element_name which allows access and initializes...
133
+ 2. an Element model
134
+
135
+ Out of the box, Element accepts all the old familar Capybara Element actions / queries (e.g. click, set, text, visible?). Once an action or query is sent to a Wheel element it then finds the native Capybara element and passes it on. This ensures that each method call is executed on the newset version of the element.
136
+
137
+ Passing a block to element gives access to the Element object for the purpose of implamenting a subelement (see below) or rolling your own customised methods:
138
+
139
+ **The following messages are delegated to the native Capybara element callback.**
140
+
141
+ ```
142
+ #find, #click, #has_content?, #checked?, #text, #visible?, #present?, #selected?, #disabled?, #tag_name, #value, #set, #select_option, #unselect_option, #hover
143
+ ```
144
+
145
+ **_Example:_**
146
+
147
+ element 'ButtonOfDoom', '#doom-button' do
148
+
149
+ def armed?
150
+ capybara_element.text == 'Armed'
151
+ end
152
+
153
+ end
154
+
155
+ element 'MissleTracker', '.missle-tracker'
156
+
157
+
158
+ #=> SuperVillanConsole.new.button_of_doom.armed?
159
+
160
+ #=> SuperVillanConsole.new.missle_tracker.visible?
161
+
162
+
163
+
164
+ #### (Sub)Element
165
+
166
+ An element block also accepts the `element` method.
167
+
168
+ element 'SubElementName', 'selector' *optional block*
169
+
170
+ When called inside an element block, the element behaves like an Element but is now scoped to the containing (or parent) element, which reduces ambiguity.
171
+
172
+ **_Example:_**
173
+
174
+ Two buttons have an `li` element with the `.key` class. We want to be able to find one and turn it without accidently causing world peace:
175
+
176
+ element 'ButtonOfDoom', '#doom-button' do
177
+
178
+ # reference to this key is scoped inside the #doom-button element
179
+ element 'ArmingKey', 'li.key' do
180
+
181
+ def turn
182
+ click
183
+ end
184
+
185
+ end
186
+ end
187
+
188
+ element 'ButtonOfWorldPeace', '#peace-button' do
189
+
190
+ # reference to this key is scoped inside the #peace-button element
191
+ element 'ArmingKey', 'li.key' do
192
+
193
+ def turn
194
+ click
195
+ end
196
+
197
+ end
198
+ end
199
+
200
+ #=> SuperVillanConsole.new.button_of_world_peace.arming_key.turn
201
+ #=> SuperVillanConsole.new.button_of_doom.arming_key.turn
202
+
203
+ ## Specs
204
+
205
+ Wheel specs are written to always refer to the models and to never refer to Capybara directly. The page methods we implemented above allows us the do:
206
+
207
+ let(:some_page) { SomePageModel.new }
208
+
209
+ it 'can visit a page' do
210
+ some_page.visit
211
+ end
212
+
213
+ The visit page would use the `on_page?` method to determine if we are indeed on the page. It will use Capyara's internal wait to poll the page until it is ready. We can then even excute within the scope of the page:
214
+
215
+ it 'can visit a page and pass a block to execute' do
216
+ some_page.visit do | page |
217
+ page.some_element.should be_visible
218
+ end
219
+ end
220
+
221
+ it 'can also just check if we're on the page without visiting it'
222
+ some_page.on do | page |
223
+ page.some_element.should be_visible
224
+ end
225
+ end
226
+
227
+
228
+ **_Example:_**
229
+
230
+ feature "Supervillan Console" do
231
+
232
+ let(:supervillan_console) { SuperVillanConsole.new }
233
+
234
+ before :each do
235
+ supervillan_console.visit
236
+ end
237
+
238
+ scenario 'can arm doom button' do
239
+ supervillan_console.on do | con |
240
+ con.button_of_doom.arming_key.turn
241
+ con.button_of_doom.armed?.should be_true
242
+ end
243
+ end
244
+
245
+
246
+ end
247
+
248
+ ***
249
+ ***
250
+ ***
251
+
252
+
253
+
254
+ ## Contributing
255
+
256
+ 1. Fork it
257
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
258
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
259
+ 4. Push to the branch (`git push origin my-new-feature`)
260
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'capybara/wheel/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dkastner-capybara-wheel"
8
+ spec.version = Capybara::Wheel::VERSION
9
+ spec.authors = ["@gabrielrotbart"]
10
+ spec.email = ["gabe@hooroo.com"]
11
+ spec.description = %q{Keeping the rodent on track}
12
+ spec.summary = %q{Creating (yet another) page model gem based around making capybara tests more stable with no need for waits}
13
+ spec.homepage = "http://github.com/hooroo/capybara-wheel"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
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_dependency "capybara", "~> 2.1"
22
+ spec.add_dependency "rspec"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "selenium-webdriver", "~> 2.0"
27
+ spec.add_development_dependency "sinatra", "~> 1.0"
28
+ spec.add_development_dependency "pry"
29
+ end
@@ -0,0 +1,34 @@
1
+ Dir.glob(File.join(File.dirname(__FILE__), 'wheel', '*.rb')).each {|file| require file}
2
+ require 'capybara'
3
+ require 'capybara/dsl'
4
+ require 'rspec'
5
+
6
+ module Capybara
7
+ module Wheel
8
+ # main mixin to access wheel
9
+
10
+ def self.included(base)
11
+ base.instance_eval do
12
+ alias :background :before
13
+ alias :scenario :it
14
+ alias :given :let
15
+ alias :given! :let!
16
+ end
17
+ end
18
+
19
+ module FeatureOverride
20
+ def feature(*args, &block)
21
+ options = {
22
+ type: :wheel_feature,
23
+ caller: caller
24
+ }
25
+ options.merge!(args.pop) if args.last.is_a?(Hash)
26
+ describe(*args, options, &block)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ extend Capybara::Wheel::FeatureOverride
34
+ RSpec.configuration.include Capybara::Wheel, wheel_feature: true
@@ -0,0 +1,96 @@
1
+ require 'capybara/wheel/includes'
2
+ require 'forwardable'
3
+
4
+ module Capybara
5
+ module Wheel
6
+ class Element
7
+
8
+ extend Forwardable
9
+ include Capybara::Wheel::Includes
10
+ extend Capybara::Wheel::Includes::ClassIncludes
11
+
12
+ attr_reader :scope
13
+
14
+ def initialize(selector = nil, scope = nil)
15
+ @selector = selector if selector
16
+ @scope = scope
17
+ end
18
+
19
+ def_delegators :capybara_element,
20
+ :find,
21
+ :click,
22
+ :has_content?,
23
+ :checked?,
24
+ :text,
25
+ :visible?,
26
+ :present?,
27
+ :selected?,
28
+ :disabled?,
29
+ :tag_name,
30
+ :value,
31
+ :set,
32
+ :select_option,
33
+ :unselect_option,
34
+ :hover,
35
+ :[]
36
+
37
+
38
+
39
+ def present?
40
+ capybara_element.visible?
41
+ rescue Capybara::ElementNotFound => e
42
+ puts "#{e} on #{Time.now.strftime("%H:%I:%S:%L")}"
43
+ false
44
+ end
45
+
46
+ def visible?
47
+ capybara_element.visible?
48
+ rescue Capybara::ElementNotFound => e
49
+ puts "#{e} on #{Time.now.strftime("%H:%I:%S:%L")}"
50
+ false
51
+ end
52
+
53
+ def self.element(name, selector, block = nil)
54
+ subelement_factory = lambda do |parent_element|
55
+ Capybara::Wheel::ElementFactory.create_element(selector, parent_element, block)
56
+ end
57
+
58
+ define_method(underscore(name).to_sym) { subelement_factory.call(self) }
59
+ self
60
+ end
61
+
62
+ def element(name, selector, &block)
63
+ self.class.element(name, selector, block)
64
+ end
65
+
66
+ #TODO: deprecated in 0.0.5
67
+ def subelement(name, selector, &block)
68
+ puts "subelement will be deprecated in future versions."
69
+ puts "Calling element inside an element block will scope it to the parent element"
70
+ element(name, selector, block)
71
+ end
72
+
73
+ def self.subelement(name, selector, &block)
74
+ puts "subelement will be deprecated in future versions."
75
+ puts "Calling element inside an element block will scope it to the parent element"
76
+ element(name, selector, &block)
77
+ end
78
+
79
+ def selector
80
+ @selector
81
+ end
82
+
83
+ private
84
+
85
+ # Finds a capybara element representing this thing
86
+ def capybara_element
87
+ scope_capybara.find(selector, options)
88
+ end
89
+
90
+ def scope_capybara
91
+ scope.nil? ? capybara : scope.send(:capybara_element)
92
+ end
93
+
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,33 @@
1
+ require 'capybara/wheel'
2
+
3
+ module Capybara
4
+ module Wheel
5
+ class ElementFactory
6
+
7
+ def self.create_element_klass(selector, options = {}, block = nil)
8
+ subclass = Class.new(Capybara::Wheel::Element)
9
+
10
+ _selector = selector
11
+ _options = options
12
+
13
+ subclass.class_exec do
14
+ define_method(:selector) { @selector = _selector }
15
+ define_method(:options) { @options = _options }
16
+ end
17
+
18
+ subclass.class_eval(&block) if block
19
+
20
+ subclass
21
+ end
22
+
23
+ #TODO: Pass object not an instance
24
+ def self.create_element(selector, parent_element, block = nil)
25
+ subelement = Capybara::Wheel::Element.new(selector, parent_element)
26
+ subelement.instance_eval(&block) if block
27
+
28
+ subelement
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ require 'capybara/wheel'
2
+ require 'capybara'
3
+ require 'capybara/dsl'
4
+ require 'rspec'
5
+
6
+ module Capybara
7
+ module Wheel
8
+ module Includes
9
+
10
+ include Capybara::DSL
11
+
12
+ def capybara
13
+ Capybara.current_session
14
+ end
15
+
16
+ module ClassIncludes
17
+ def underscore(string)
18
+ string.gsub(/::/, '/').
19
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
20
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
21
+ tr("-", "_").
22
+ downcase
23
+ end
24
+
25
+ def make_const(string)
26
+
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,59 @@
1
+ require 'capybara/wheel/includes'
2
+
3
+ module Capybara
4
+ module Wheel
5
+ class Page
6
+
7
+ include Capybara::Wheel::Includes
8
+ extend Capybara::Wheel::Includes::ClassIncludes
9
+
10
+ # actively visits page and executes block in context
11
+ def visit(&block)
12
+ capybara.visit(path)
13
+ if block_given?
14
+ on(&block)
15
+ else
16
+ on_page?
17
+ end
18
+ return self
19
+ end
20
+
21
+ # execute a block in the context of this page
22
+ def on
23
+ unless on_page?
24
+ raise "We don't appear to be on the #{self.class}"
25
+ end
26
+ yield self if block_given?
27
+ self
28
+ end
29
+
30
+ # Returns the path (relative URI) of this page
31
+ def path
32
+ raise NotImplementedError, "implement to support page.visit"
33
+ end
34
+
35
+ # Return true if the browser is on this page
36
+ def on_page?
37
+ raise NotImplementedError, "implement me, e.g. using #has_title?"
38
+ end
39
+
40
+ def has_title?(expected_title)
41
+ capybara.has_css?("head title", text: expected_title)
42
+ end
43
+
44
+ def self.element(name, selector, options = {}, &block)
45
+ begin
46
+ element_klass = const_set("#{name}", Capybara::Wheel::ElementFactory.create_element_klass(selector, options, block))
47
+ rescue NameError
48
+ puts "We recommend using capitalized element and subelement names"
49
+ name = name.capitalize!
50
+ retry
51
+ end
52
+
53
+ define_method(underscore(name).to_sym) { element_klass.new(selector) }
54
+ self
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,5 @@
1
+ module Capybara
2
+ module Wheel
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'ElementFactory' do
4
+ let(:subject) { Capybara::Wheel::ElementFactory }
5
+ let(:selector) { '#rad-selector'}
6
+ let(:created_element_klass) { subject.create_element_klass(selector) }
7
+
8
+
9
+ it 'creates an element' do
10
+ created_element_klass.superclass.should == Capybara::Wheel::Element
11
+ end
12
+
13
+ it 'allows access to the selector' do
14
+ created_element_klass.new.selector.should == selector
15
+ end
16
+
17
+ it 'generated instance evalutes block' do
18
+ test_block = Proc.new do
19
+ def evaled_method
20
+ end
21
+ end
22
+
23
+ subject.create_element_klass(selector, test_block).new.should respond_to(:evaled_method)
24
+ end
25
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Element' do
4
+ let(:element_selector) { '#some-selector' }
5
+ let(:element) { Capybara::Wheel::Element }
6
+ let(:element_instance) { element.new(element_selector) }
7
+
8
+ it 'has access to capybara' do
9
+ element_instance.methods.include?(:capybara).should be_true
10
+ end
11
+
12
+ it 'has delegators for Capybara actions' do
13
+ pending 'grab all the actions from Capybara and ensure delegators are implemented'
14
+ end
15
+
16
+ context 'self.element' do
17
+ let(:element_selector) { '#rad-parent-selector' }
18
+
19
+ let(:subelement_name) { 'RadSubElement' }
20
+ let(:subelement_selector) { '#rad-sub-selector' }
21
+
22
+ before do
23
+ element_instance.instance_eval do
24
+ element('RadSubElement', '#rad-sub-selector')
25
+ end
26
+ end
27
+
28
+ it 'created a method for calling the element' do
29
+ element_instance.should respond_to(:rad_sub_element)
30
+ end
31
+
32
+ it 'create a (sub)element with parent element context' do
33
+ element_instance.send(:rad_sub_element).scope.should == element_instance
34
+ end
35
+
36
+ it 'the find would be scoped to parent' do
37
+ subelement = element_instance.send(:rad_sub_element)
38
+ mock_capybara_session = mock(Capybara::Session)
39
+ mock_capybara_element = mock('Capybara::Element')
40
+ Capybara.stub!(:current_session).and_return(mock_capybara_session)
41
+ mock_capybara_session.stub(:find).with(element_selector).and_return(mock_capybara_element)
42
+ mock_capybara_element.stub(:find).with(subelement_selector).and_return(mock_capybara_element)
43
+
44
+ element_instance.should_receive(:capybara_element).once.and_return(mock_capybara_element)
45
+
46
+ subelement.send(:capybara_element)
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.configure do |config|
4
+ config.before(:each, :some_hook) do
5
+ @hook_passed_on = true
6
+ end
7
+ end
8
+
9
+ feature 'runs as a wheel feature', :some_hook do
10
+
11
+ it 'should pass' do
12
+ end
13
+
14
+ it 'should be set as a wheel feature' do
15
+ example.metadata[:type].should == :wheel_feature
16
+ end
17
+
18
+ it 'should pass the right hook' do
19
+ @hook_passed_on.should be_true
20
+ end
21
+ end
data/spec/page_spec.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Page' do
4
+ let(:page) { Capybara::Wheel::Page }
5
+
6
+ subject { page.new }
7
+ it { is_expected.to respond_to(:capybara) }
8
+
9
+ describe '.element' do
10
+
11
+ context 'element with no options' do
12
+ subject { page.element('RadElement', '#rad-selector').new }
13
+
14
+ it { is_expected.to respond_to(:rad_element) }
15
+ end
16
+
17
+ context 'element with extra options' do
18
+ subject { page.element('OptionalElement', '#opt-selector', visible: false).new }
19
+
20
+ it { is_expected.to respond_to(:optional_element) }
21
+
22
+ it 'has options' do
23
+ expect(subject.optional_element.options).to eq(visible: false)
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,7 @@
1
+ require 'capybara/wheel'
2
+ require 'rspec'
3
+ require 'pry'
4
+
5
+ RSpec.configure do |config|
6
+ config.treat_symbols_as_metadata_keys_with_true_values = true
7
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dkastner-capybara-wheel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - "@gabrielrotbart"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capybara
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: selenium-webdriver
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sinatra
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Keeping the rodent on track
112
+ email:
113
+ - gabe@hooroo.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - Gemfile
120
+ - LICENSE.txt
121
+ - README.md
122
+ - Rakefile
123
+ - capybara-wheel.gemspec
124
+ - lib/capybara/wheel.rb
125
+ - lib/capybara/wheel/element.rb
126
+ - lib/capybara/wheel/element_factory.rb
127
+ - lib/capybara/wheel/includes.rb
128
+ - lib/capybara/wheel/page.rb
129
+ - lib/capybara/wheel/version.rb
130
+ - spec/element_factory_spec.rb
131
+ - spec/element_spec.rb
132
+ - spec/feature_spec.rb
133
+ - spec/page_spec.rb
134
+ - spec/spec_helper.rb
135
+ homepage: http://github.com/hooroo/capybara-wheel
136
+ licenses:
137
+ - MIT
138
+ metadata: {}
139
+ post_install_message:
140
+ rdoc_options: []
141
+ require_paths:
142
+ - lib
143
+ required_ruby_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ required_rubygems_version: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ requirements: []
154
+ rubyforge_project:
155
+ rubygems_version: 2.2.2
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: Creating (yet another) page model gem based around making capybara tests
159
+ more stable with no need for waits
160
+ test_files:
161
+ - spec/element_factory_spec.rb
162
+ - spec/element_spec.rb
163
+ - spec/feature_spec.rb
164
+ - spec/page_spec.rb
165
+ - spec/spec_helper.rb