page_magic 1.0.0.alpha21 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +9 -7
  5. data/README.md +181 -78
  6. data/VERSION +1 -1
  7. data/lib/page_magic/class_methods.rb +8 -7
  8. data/lib/page_magic/driver.rb +7 -7
  9. data/lib/page_magic/drivers.rb +6 -6
  10. data/lib/page_magic/element/locators.rb +24 -0
  11. data/lib/page_magic/element/query.rb +1 -0
  12. data/lib/page_magic/element/selector.rb +11 -9
  13. data/lib/page_magic/element.rb +47 -85
  14. data/lib/page_magic/element_context.rb +25 -5
  15. data/lib/page_magic/element_definition_builder.rb +39 -0
  16. data/lib/page_magic/elements.rb +24 -27
  17. data/lib/page_magic/exceptions.rb +11 -8
  18. data/lib/page_magic/instance_methods.rb +23 -21
  19. data/lib/page_magic/session.rb +43 -44
  20. data/lib/page_magic/session_methods.rb +28 -0
  21. data/lib/page_magic/wait_methods.rb +18 -0
  22. data/lib/page_magic/watcher.rb +41 -0
  23. data/lib/page_magic/watchers.rb +43 -0
  24. data/lib/page_magic.rb +13 -9
  25. data/spec/element_spec.rb +58 -160
  26. data/spec/page_magic/class_methods_spec.rb +7 -6
  27. data/spec/page_magic/driver_spec.rb +14 -13
  28. data/spec/page_magic/drivers_spec.rb +7 -6
  29. data/spec/page_magic/element/locators_spec.rb +33 -0
  30. data/spec/page_magic/element/query_spec.rb +44 -19
  31. data/spec/page_magic/element/selector_spec.rb +45 -3
  32. data/spec/page_magic/element_context_spec.rb +41 -11
  33. data/spec/page_magic/element_definition_builder_spec.rb +76 -0
  34. data/spec/page_magic/elements_spec.rb +94 -141
  35. data/spec/page_magic/instance_methods_spec.rb +15 -10
  36. data/spec/page_magic/session_methods_spec.rb +36 -0
  37. data/spec/page_magic/session_spec.rb +78 -79
  38. data/spec/page_magic/wait_methods_spec.rb +41 -0
  39. data/spec/page_magic/watchers_spec.rb +74 -0
  40. data/spec/page_magic_spec.rb +9 -9
  41. data/spec/spec_helper.rb +1 -0
  42. data/spec/support/shared_contexts/nested_elements_html_context.rb +16 -0
  43. data/spec/support/shared_contexts/{webapp_context.rb → webapp_fixture_context.rb} +0 -0
  44. data/spec/support/shared_examples.rb +25 -0
  45. data/spec/watcher_spec.rb +49 -0
  46. metadata +23 -11
  47. data/lib/page_magic/element/method_observer.rb +0 -20
  48. data/spec/member_methods_spec.rb +0 -2
@@ -12,18 +12,6 @@ module PageMagic
12
12
  let(:url) { 'http://url.com' }
13
13
  let(:browser) { double('browser', current_url: url, visit: nil, current_path: :current_path) }
14
14
 
15
- describe '#current_url' do
16
- it "returns the browser's current url" do
17
- expect(subject.current_url).to eq(browser.current_url)
18
- end
19
- end
20
-
21
- describe '#current_path' do
22
- it "returns the browser's current path" do
23
- expect(subject.current_path).to eq(browser.current_path)
24
- end
25
- end
26
-
27
15
  describe '#current_page' do
28
16
  let(:another_page_class) do
29
17
  Class.new do
@@ -52,6 +40,18 @@ module PageMagic
52
40
  end
53
41
  end
54
42
 
43
+ describe '#current_path' do
44
+ it "returns the browser's current path" do
45
+ expect(subject.current_path).to eq(browser.current_path)
46
+ end
47
+ end
48
+
49
+ describe '#current_url' do
50
+ it "returns the browser's current url" do
51
+ expect(subject.current_url).to eq(browser.current_url)
52
+ end
53
+ end
54
+
55
55
  describe '#find_mapped_page' do
56
56
  subject do
57
57
  described_class.new(nil).tap do |session|
@@ -77,63 +77,42 @@ module PageMagic
77
77
  end
78
78
  end
79
79
 
80
- describe '#wait' do
81
- it 'passes the supplied block to the wait api' do
82
- block = proc { :executed }
83
- allow_any_instance_of(Wait).to receive(:until).and_call_original
84
- expect(subject.wait_until(&block)).to eq(:executed)
80
+ describe '#execute_script' do
81
+ it 'calls the execute script method on the capybara session' do
82
+ expect(browser).to receive(:execute_script).with(:script).and_return(:result)
83
+ expect(subject.execute_script(:script)).to be(:result)
85
84
  end
86
85
  end
87
86
 
88
- describe '#visit' do
89
- let(:session) do
90
- allow(browser).to receive(:visit)
91
- PageMagic::Session.new(browser, url)
92
- end
93
-
94
- context 'page supplied' do
95
- it 'sets the current page' do
96
- session.define_page_mappings '/page' => page
97
- session.visit(page)
98
- expect(session.current_page).to be_a(page)
99
- end
100
-
101
- it 'uses the current url and the path in the page mappings' do
102
- session.define_page_mappings '/page' => page
103
- expect(browser).to receive(:visit).with("#{browser.current_url}/page")
104
- session.visit(page)
105
- end
106
-
107
- context 'no mappings found' do
108
- it 'raises an error' do
109
- expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::URL_MISSING_MSG
87
+ describe '#method_missing' do
88
+ it 'should delegate to current page' do
89
+ page.class_eval do
90
+ def my_method
91
+ :called
110
92
  end
111
93
  end
112
94
 
113
- context 'mapping is a regular expression' do
114
- it 'raises an error' do
115
- session.define_page_mappings(/mapping/ => page)
116
- expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::REGEXP_MAPPING_MSG
117
- end
118
- end
95
+ session = PageMagic::Session.new(browser).visit(page, url: url)
96
+ expect(session.my_method).to be(:called)
97
+ end
98
+ end
119
99
 
120
- it 'calls the onload hook' do
121
- on_load_hook_called = false
122
- page.on_load do
123
- on_load_hook_called = true
124
- end
125
- session.define_page_mappings('/page' => page)
126
- session.visit(page)
127
- expect(on_load_hook_called).to eq(true)
100
+ context '#respond_to?' do
101
+ subject do
102
+ PageMagic::Session.new(browser).tap do |s|
103
+ allow(s).to receive(:current_page).and_return(page.new)
128
104
  end
129
105
  end
106
+ it 'checks self' do
107
+ expect(subject.respond_to?(:current_url)).to eq(true)
108
+ end
130
109
 
131
- context 'url supplied' do
132
- it 'visits that url' do
133
- expected_url = 'http://url.com/page'
134
- expect(browser).to receive(:visit).with(expected_url)
135
- session.visit(url: expected_url)
110
+ it 'checks the current page' do
111
+ page.class_eval do
112
+ def my_method
113
+ end
136
114
  end
115
+ expect(subject.respond_to?(:my_method)).to eq(true)
137
116
  end
138
117
  end
139
118
 
@@ -175,35 +154,55 @@ module PageMagic
175
154
  end
176
155
  end
177
156
 
178
- context '#method_missing' do
179
- it 'should delegate to current page' do
180
- page.class_eval do
181
- def my_method
182
- :called
157
+ describe '#visit' do
158
+ let(:session) do
159
+ allow(browser).to receive(:visit)
160
+ PageMagic::Session.new(browser, url)
161
+ end
162
+
163
+ context 'page supplied' do
164
+ it 'sets the current page' do
165
+ session.define_page_mappings '/page' => page
166
+ session.visit(page)
167
+ expect(session.current_page).to be_a(page)
168
+ end
169
+
170
+ it 'uses the current url and the path in the page mappings' do
171
+ session.define_page_mappings '/page' => page
172
+ expect(browser).to receive(:visit).with("#{browser.current_url}/page")
173
+ session.visit(page)
174
+ end
175
+
176
+ context 'no mappings found' do
177
+ it 'raises an error' do
178
+ expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::URL_MISSING_MSG
183
179
  end
184
180
  end
185
181
 
186
- session = PageMagic::Session.new(browser).visit(page, url: url)
187
- expect(session.my_method).to be(:called)
188
- end
189
- end
182
+ context 'mapping is a regular expression' do
183
+ it 'raises an error' do
184
+ session.define_page_mappings(/mapping/ => page)
185
+ expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::REGEXP_MAPPING_MSG
186
+ end
187
+ end
190
188
 
191
- context '#respond_to?' do
192
- subject do
193
- PageMagic::Session.new(browser).tap do |s|
194
- allow(s).to receive(:current_page).and_return(page.new)
189
+ it 'calls the onload hook' do
190
+ on_load_hook_called = false
191
+ page.on_load do
192
+ on_load_hook_called = true
193
+ end
194
+ session.define_page_mappings('/page' => page)
195
+ session.visit(page)
196
+ expect(on_load_hook_called).to eq(true)
195
197
  end
196
198
  end
197
- it 'checks self' do
198
- expect(subject.respond_to?(:current_url)).to eq(true)
199
- end
200
199
 
201
- it 'checks the current page' do
202
- page.class_eval do
203
- def my_method
204
- end
200
+ context 'url supplied' do
201
+ it 'visits that url' do
202
+ expected_url = 'http://url.com/page'
203
+ expect(browser).to receive(:visit).with(expected_url)
204
+ session.visit(url: expected_url)
205
205
  end
206
- expect(subject.respond_to?(:my_method)).to eq(true)
207
206
  end
208
207
  end
209
208
  end
@@ -0,0 +1,41 @@
1
+ module PageMagic
2
+ describe WaitMethods do
3
+ subject do
4
+ Object.new.tap do |o|
5
+ o.extend(described_class)
6
+ end
7
+ end
8
+
9
+ let(:default_options) { { timeout_after: 0.1, retry_every: 0.05 } }
10
+
11
+ it 'waits until the prescribed thing has happened' do
12
+ expect { subject.wait_until(default_options) { true } }.to_not raise_exception
13
+ end
14
+
15
+ it 'should keep trying for a specified period' do
16
+ start_time = Time.now
17
+
18
+ expect { subject.wait_until(default_options) { false } }.to raise_exception TimeoutException
19
+
20
+ expect(Time.now - default_options[:timeout_after]).to be > start_time
21
+ end
22
+
23
+ context 'timeout_after specified' do
24
+ it 'throws an exception if when the prescribed action does not happen in time' do
25
+ expect { subject.wait_until(default_options) { false } }.to raise_error TimeoutException
26
+ end
27
+ end
28
+
29
+ context 'retry time specified' do
30
+ it 'retries at the given interval' do
31
+ count = 0
32
+ expect do
33
+ subject.wait_until(timeout_after: default_options[:timeout_after] * 2, retry_every: 0.1) do
34
+ count += 1
35
+ end
36
+ end.to raise_exception TimeoutException
37
+ expect(count).to eq(2)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,74 @@
1
+ module PageMagic
2
+ describe Watchers do
3
+ let(:element) { OpenStruct.new(text: :current_value) }
4
+
5
+ subject do
6
+ Object.new.tap do |o|
7
+ o.extend(described_class)
8
+ allow(o).to receive(:my_watcher).and_return(element)
9
+ end
10
+ end
11
+
12
+ describe '#changed?' do
13
+ before do
14
+ subject.watch(:my_watcher, :text)
15
+ end
16
+
17
+ context 'watched element has changed' do
18
+ it 'returns true' do
19
+ element.text = :new_value
20
+ expect(subject.changed?(:my_watcher)).to eq(true)
21
+ end
22
+ end
23
+
24
+ context 'watched element has not changed' do
25
+ it 'returns false' do
26
+ expect(subject.changed?(:my_watcher)).to eq(false)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe '#watch' do
32
+ it 'stores the initial value of the watched element' do
33
+ subject.watch(:my_watcher, :text)
34
+ expect(subject.watcher(:my_watcher).last).to eq(:current_value)
35
+ end
36
+
37
+ context 'element name/ method name supplied' do
38
+ it 'stores the watch instruction' do
39
+ subject.watch(:object_id)
40
+ expect(subject.watcher(:object_id)).to eq(Watcher.new(:object_id))
41
+ end
42
+ end
43
+
44
+ context 'element name and attribute supplied' do
45
+ it 'stores the watch instruction' do
46
+ subject.watch(:my_watcher, :text)
47
+ expect(subject.watcher(:my_watcher)).to eq(Watcher.new(:my_watcher, :text))
48
+ end
49
+ end
50
+
51
+ context 'block supplied' do
52
+ it 'stores the watch instruction' do
53
+ block = proc {}
54
+ subject.watch(:my_watcher, &block)
55
+ expect(subject.watcher(:my_watcher)).to eq(Watcher.new(:my_watcher, &block))
56
+ end
57
+ end
58
+
59
+ context 'watcher defined on element that does not exist' do
60
+ it 'raises an error' do
61
+ expected_message = described_class::ELEMENT_MISSING_MSG % :missing
62
+ expect { subject.watch(:missing, :text) }.to raise_exception(ElementMissingException, expected_message)
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '#watcher' do
68
+ it 'returns the watcher with the given name' do
69
+ subject.watch(:my_watcher, :text)
70
+ expect(subject.watcher(:my_watcher)).to eq(Watcher.new(:my_watcher, :text))
71
+ end
72
+ end
73
+ end
74
+ end
@@ -5,6 +5,14 @@ describe PageMagic do
5
5
  Class.new { include PageMagic }
6
6
  end
7
7
 
8
+ describe '.drivers' do
9
+ it 'returns loaded drivers' do
10
+ expected_drivers = described_class::Drivers.new.tap(&:load)
11
+
12
+ expect(described_class.drivers).to eq(expected_drivers)
13
+ end
14
+ end
15
+
8
16
  describe '.included' do
9
17
  it 'gives a method for defining the url' do
10
18
  subject.url :url
@@ -40,15 +48,7 @@ describe PageMagic do
40
48
  end
41
49
  end
42
50
 
43
- describe '::drivers' do
44
- it 'returns loaded drivers' do
45
- expected_drivers = described_class::Drivers.new.tap(&:load)
46
-
47
- expect(described_class.drivers).to eq(expected_drivers)
48
- end
49
- end
50
-
51
- describe '::session' do
51
+ describe '.session' do
52
52
  let(:url) { 'http://url.com/' }
53
53
  let(:application) { rack_application.new }
54
54
 
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  Bundler.require
2
2
  $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib")
3
3
  require 'support/shared_contexts'
4
+ require 'support/shared_examples'
4
5
 
5
6
  require 'simplecov' if ENV['coverage']
6
7
 
@@ -0,0 +1,16 @@
1
+ shared_context :nested_elements_html do
2
+ require 'sinatra/base'
3
+
4
+ let(:nested_elements_html) do
5
+ <<-HTML
6
+ <div id="parent">
7
+ <div id="child">
8
+ </div>
9
+ </div>
10
+ HTML
11
+ end
12
+
13
+ let(:nested_elements_node) do
14
+ Capybara::Node::Simple.new(nested_elements_html)
15
+ end
16
+ end
@@ -0,0 +1,25 @@
1
+ module PageMagic
2
+ shared_examples 'session accessor' do
3
+ it 'includes session methods' do
4
+ expect(described_class.included_modules).to include(SessionMethods)
5
+ end
6
+ end
7
+
8
+ shared_examples 'element watcher' do
9
+ it 'includes watchers' do
10
+ expect(described_class.included_modules).to include(Watchers)
11
+ end
12
+ end
13
+
14
+ shared_examples 'waiter' do
15
+ it 'includes waiters' do
16
+ expect(described_class.included_modules).to include(WaitMethods)
17
+ end
18
+ end
19
+
20
+ shared_examples 'element locator' do
21
+ it 'includes Locators' do
22
+ expect(described_class.included_modules).to include(Element::Locators)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ module PageMagic
2
+ describe Watcher do
3
+ describe '#initialize' do
4
+ context 'check has not been called yet' do
5
+ subject do
6
+ described_class.new(:custom_watcher)
7
+ end
8
+ it 'it sets last to nil' do
9
+ expect(subject.last).to be_nil
10
+ end
11
+ end
12
+ end
13
+
14
+ describe '#check' do
15
+ context 'method supplied to constructor' do
16
+ subject do
17
+ described_class.new(:object_id)
18
+ end
19
+
20
+ it 'assigns last to be the result of calling the method' do
21
+ subject.check(self)
22
+ expect(subject.last).to eq(object_id)
23
+ end
24
+ end
25
+ context 'name and attribute supplied to constructor' do
26
+ subject do
27
+ described_class.new(:my_button, :text)
28
+ end
29
+
30
+ it 'assigns last to the value of attribute definined in the constructor' do
31
+ browser_element = double(text: :hello)
32
+ page_element = double(my_button: browser_element)
33
+ expect(subject.check(page_element).last).to eq(:hello)
34
+ end
35
+ end
36
+
37
+ context 'block supplied to constructor' do
38
+ subject do
39
+ described_class.new(:custom_watcher) do
40
+ :result
41
+ end
42
+ end
43
+ it 'assigns last to the resut of the block' do
44
+ expect(subject.check.last).to eq(:result)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: page_magic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha21
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leon Davis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-05 00:00:00.000000000 Z
11
+ date: 2015-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: '2'
19
+ version: 2.5.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: '2'
26
+ version: 2.5.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -149,35 +149,47 @@ files:
149
149
  - lib/page_magic/drivers/rack_test.rb
150
150
  - lib/page_magic/drivers/selenium.rb
151
151
  - lib/page_magic/element.rb
152
- - lib/page_magic/element/method_observer.rb
152
+ - lib/page_magic/element/locators.rb
153
153
  - lib/page_magic/element/query.rb
154
154
  - lib/page_magic/element/selector.rb
155
155
  - lib/page_magic/element/selector_methods.rb
156
156
  - lib/page_magic/element_context.rb
157
+ - lib/page_magic/element_definition_builder.rb
157
158
  - lib/page_magic/elements.rb
158
159
  - lib/page_magic/exceptions.rb
159
160
  - lib/page_magic/instance_methods.rb
160
161
  - lib/page_magic/session.rb
162
+ - lib/page_magic/session_methods.rb
163
+ - lib/page_magic/wait_methods.rb
164
+ - lib/page_magic/watcher.rb
165
+ - lib/page_magic/watchers.rb
161
166
  - spec/element_spec.rb
162
- - spec/member_methods_spec.rb
163
167
  - spec/page_magic/class_methods_spec.rb
164
168
  - spec/page_magic/driver_spec.rb
165
169
  - spec/page_magic/drivers/poltergeist_spec.rb
166
170
  - spec/page_magic/drivers/rack_test_spec.rb
167
171
  - spec/page_magic/drivers/selenium_spec.rb
168
172
  - spec/page_magic/drivers_spec.rb
173
+ - spec/page_magic/element/locators_spec.rb
169
174
  - spec/page_magic/element/query_spec.rb
170
175
  - spec/page_magic/element/selector_spec.rb
171
176
  - spec/page_magic/element_context_spec.rb
177
+ - spec/page_magic/element_definition_builder_spec.rb
172
178
  - spec/page_magic/elements_spec.rb
173
179
  - spec/page_magic/instance_methods_spec.rb
180
+ - spec/page_magic/session_methods_spec.rb
174
181
  - spec/page_magic/session_spec.rb
182
+ - spec/page_magic/wait_methods_spec.rb
183
+ - spec/page_magic/watchers_spec.rb
175
184
  - spec/page_magic_spec.rb
176
185
  - spec/spec_helper.rb
177
186
  - spec/support/shared_contexts.rb
178
187
  - spec/support/shared_contexts/files_context.rb
188
+ - spec/support/shared_contexts/nested_elements_html_context.rb
179
189
  - spec/support/shared_contexts/rack_application_context.rb
180
- - spec/support/shared_contexts/webapp_context.rb
190
+ - spec/support/shared_contexts/webapp_fixture_context.rb
191
+ - spec/support/shared_examples.rb
192
+ - spec/watcher_spec.rb
181
193
  homepage: https://github.com/ladtech/page_magic
182
194
  licenses:
183
195
  - ruby
@@ -193,9 +205,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
193
205
  version: '2.1'
194
206
  required_rubygems_version: !ruby/object:Gem::Requirement
195
207
  requirements:
196
- - - ">"
208
+ - - ">="
197
209
  - !ruby/object:Gem::Version
198
- version: 1.3.1
210
+ version: '0'
199
211
  requirements: []
200
212
  rubyforge_project:
201
213
  rubygems_version: 2.2.2
@@ -1,20 +0,0 @@
1
- module PageMagic
2
- class Element
3
- # module MethodObserver - adds methods to check if a methods have been added.
4
- module MethodObserver
5
- # Hook called by ruby when a singleton method is added.
6
- #
7
- # @param [String] arg name of the method added
8
- def singleton_method_added(arg)
9
- @singleton_methods_added = true unless arg == :singleton_method_added
10
- end
11
-
12
- # returns true if a singleton method has been added
13
- #
14
- # @return [Boolean]
15
- def singleton_methods_added?
16
- @singleton_methods_added == true
17
- end
18
- end
19
- end
20
- end
@@ -1,2 +0,0 @@
1
- describe 'member methods' do
2
- end