page_magic 1.0.0.alpha13 → 1.0.0.alpha17

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/.simplecov +3 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +15 -10
  6. data/VERSION +1 -1
  7. data/lib/page_magic/drivers.rb +2 -2
  8. data/lib/page_magic/element/method_observer.rb +13 -0
  9. data/lib/page_magic/element/query.rb +38 -0
  10. data/lib/page_magic/element/selector.rb +40 -0
  11. data/lib/page_magic/element/selector_methods.rb +10 -0
  12. data/lib/page_magic/element.rb +65 -104
  13. data/lib/page_magic/element_context.rb +3 -8
  14. data/lib/page_magic/elements.rb +31 -31
  15. data/lib/page_magic/exceptions.rb +9 -0
  16. data/lib/page_magic/page_magic.rb +7 -8
  17. data/lib/page_magic/session.rb +30 -35
  18. data/lib/page_magic.rb +14 -20
  19. data/spec/element_spec.rb +53 -37
  20. data/spec/page_magic/driver_spec.rb +3 -4
  21. data/spec/page_magic/element/query_spec.rb +76 -0
  22. data/spec/page_magic/element/selector_spec.rb +109 -0
  23. data/spec/page_magic/element_context_spec.rb +5 -9
  24. data/spec/page_magic/elements_spec.rb +150 -147
  25. data/spec/page_magic/page_magic_spec.rb +51 -8
  26. data/spec/page_magic/session_spec.rb +69 -51
  27. data/spec/page_magic_spec.rb +64 -6
  28. data/spec/spec_helper.rb +4 -96
  29. data/spec/support/shared_contexts/files_context.rb +7 -0
  30. data/spec/support/shared_contexts/rack_application_context.rb +9 -0
  31. data/spec/support/shared_contexts/webapp_context.rb +37 -0
  32. data/spec/support/shared_contexts.rb +3 -0
  33. metadata +13 -8
  34. data/lib/ext/string.rb +0 -9
  35. data/spec/helpers/capybara.rb +0 -10
  36. data/spec/page_magic/usage/defining_pages_spec.rb +0 -81
  37. data/spec/page_magic/usage/include_page_magic_spec.rb +0 -18
  38. data/spec/page_magic/usage/interacting_with_pages_spec.rb +0 -54
  39. data/spec/page_magic/usage/starting_a_session_spec.rb +0 -35
@@ -1,202 +1,205 @@
1
- describe PageMagic::Elements do
2
- let(:page_elements) do
3
- Class.new do
4
- extend(PageMagic::Elements)
1
+ # rubocop:disable Metrics/ModuleLength
2
+ module PageMagic
3
+ describe Elements do
4
+ let(:page_elements) do
5
+ Class.new.tap do |clazz|
6
+ clazz.extend(described_class)
7
+ end
5
8
  end
6
- end
7
-
8
- let(:selector) { {id: 'id'} }
9
- let(:browser_element) { double('browser_element', find: :browser_element) }
10
- let(:parent_page_element) do
11
- double('parent_page_element', browser_element: browser_element)
12
- end
13
9
 
14
- describe 'adding elements' do
10
+ let(:selector) { { id: 'id' } }
11
+ let(:browser_element) { double('browser_element', find: :browser_element) }
12
+ let(:parent_page_element) do
13
+ double('parent_page_element', browser_element: browser_element)
14
+ end
15
15
 
16
- context 'using a selector' do
17
- it 'should add an element' do
18
- expected_element = PageMagic::Element.new(:name, parent_page_element, type: :text_field, selector: selector)
19
- page_elements.text_field :name, selector
20
- page_elements.element_definitions[:name].call(parent_page_element).should == expected_element
16
+ describe 'adding elements' do
17
+ context 'using a selector' do
18
+ it 'should add an element' do
19
+ expected_element = Element.new(:name, parent_page_element, type: :text_field, selector: selector)
20
+ page_elements.text_field :name, selector
21
+ expect(page_elements.element_definitions[:name].call(parent_page_element)).to eq(expected_element)
22
+ end
21
23
  end
22
- end
23
24
 
24
- it 'uses the supplied name' do
25
- page_elements.text_field :alias, selector
26
- expect(page_elements.elements(parent_page_element).first.name).to eq(:alias)
27
- end
25
+ it 'uses the supplied name' do
26
+ page_elements.text_field :alias, selector
27
+ expect(page_elements.elements(parent_page_element).first.name).to eq(:alias)
28
+ end
28
29
 
29
- context 'complex elements' do
30
- let!(:section_class) do
31
- Class.new(PageMagic::Element) do
32
- def ==(other)
33
- other.name == name &&
30
+ context 'complex elements' do
31
+ let!(:section_class) do
32
+ Class.new(Element) do
33
+ def ==(other)
34
+ other.name == name &&
34
35
  other.browser_element == browser_element
36
+ end
35
37
  end
36
38
  end
37
- end
38
39
 
39
- context 'using a predefined class' do
40
+ context 'using a predefined class' do
41
+ it 'should add an element using that class section' do
42
+ expected_section = section_class.new(:page_section, parent_page_element, type: :section, selector: selector)
40
43
 
41
- it 'should add an element using that class section' do
42
- expected_section = section_class.new(:page_section, parent_page_element, type: :section, selector: selector)
43
-
44
- page_elements.section section_class, :page_section, selector
45
- page_elements.elements(parent_page_element).first.should == expected_section
46
- end
44
+ page_elements.element section_class, :page_section, selector
45
+ expect(page_elements.elements(parent_page_element).first).to eq(expected_section)
46
+ end
47
47
 
48
- context 'with no selector supplied' do
49
- it 'defaults the selector to the one on the class' do
50
- section_class.selector selector
51
- page_elements.section section_class, :alias
52
- expect(page_elements.elements(parent_page_element).first.selector).to eq(selector)
48
+ context 'with no selector supplied' do
49
+ it 'defaults the selector to the one on the class' do
50
+ section_class.selector selector
51
+ page_elements.element section_class, :alias
52
+ expect(page_elements.elements(parent_page_element).first.selector).to eq(selector)
53
+ end
53
54
  end
54
- end
55
55
 
56
- context 'with no name supplied' do
57
- it 'should default to the name of the class if one is not supplied' do
58
- section_class.stub(:name).and_return('PageSection')
59
- page_elements.section section_class, selector
60
- page_elements.elements(parent_page_element).first.name.should == :page_section
56
+ context 'with no name supplied' do
57
+ it 'should default to the name of the class if one is not supplied' do
58
+ allow(section_class).to receive(:name).and_return('PageSection')
59
+ page_elements.element section_class, selector
60
+ expect(page_elements.elements(parent_page_element).first.name).to eq(:page_section)
61
+ end
61
62
  end
62
63
  end
63
64
  end
64
- end
65
65
 
66
- context 'using a block' do
67
- context 'browser_element' do
68
- before :each do
69
- @browser = double('browser')
70
- @element = double('element')
71
- @parent_page_element = double('parent_page_element')
72
- @parent_page_element.stub(:browser_element).and_return(@browser)
73
- @browser.should_receive(:find).with(:css, :selector).and_return(@element)
74
- end
66
+ context 'using a block' do
67
+ context 'browser_element' do
68
+ before :each do
69
+ @browser = double('browser')
70
+ @element = double('element')
71
+ @parent_page_element = double('parent_page_element')
72
+ allow(@parent_page_element).to receive(:browser_element).and_return(@browser)
73
+ expect(@browser).to receive(:find).with(:selector).and_return(@element)
74
+ end
75
75
 
76
- it 'should be assigned when selector is passed to section method' do
77
- element = @element
76
+ it 'should be assigned when selector is passed to section method' do
77
+ element = @element
78
78
 
79
- page_elements.section :page_section, css: :selector do
80
- browser_element.should == element
79
+ page_elements.element :page_section, css: :selector do
80
+ extend RSpec::Matchers
81
+ expect(browser_element).to eq(element)
82
+ end
83
+
84
+ page_elements.element_definitions[:page_section].call(@parent_page_element)
81
85
  end
82
86
 
83
- page_elements.element_definitions[:page_section].call(@parent_page_element)
84
- end
87
+ it 'should be assigned when selector is defined in the block passed to the section method' do
88
+ element = @element
85
89
 
86
- it 'should be assigned when selector is defined in the block passed to the section method' do
87
- element = @element
90
+ page_elements.element :page_section do
91
+ selector css: :selector
92
+ extend RSpec::Matchers
93
+ expect(browser_element).to eq(element)
94
+ end
88
95
 
89
- page_elements.section :page_section do
90
- selector css: :selector
91
- browser_element.should == element
96
+ page_elements.elements(@parent_page_element, nil)
92
97
  end
93
-
94
- page_elements.elements(@parent_page_element, nil)
95
98
  end
96
- end
97
99
 
98
- it 'should pass args through to the block' do
99
- page_elements.section :page_section, css: '.blah' do |arg|
100
- arg[:passed_through] = true
101
- end
100
+ it 'should pass args through to the block' do
101
+ page_elements.element :page_section, css: '.blah' do |arg|
102
+ arg[:passed_through] = true
103
+ end
102
104
 
103
- arg = {}
104
- browser = double('browser', find: :browser_element)
105
- parent_page_element = double('parent_browser_element', browser_element: browser)
106
- page_elements.elements(parent_page_element, arg)
107
- arg[:passed_through].should be_true
108
- end
105
+ arg = {}
106
+ browser = double('browser', find: :browser_element)
107
+ parent_page_element = double('parent_browser_element', browser_element: browser)
108
+ page_elements.elements(parent_page_element, arg)
109
+ expect(arg[:passed_through]).to eq(true)
110
+ end
109
111
 
110
- it 'should return your a copy of the core definition' do
111
- page_elements.element :page_section, selector
112
- first = page_elements.element_definitions[:page_section].call(parent_page_element)
113
- second = page_elements.element_definitions[:page_section].call(parent_page_element)
114
- first.should_not equal(second)
112
+ it 'should return your a copy of the core definition' do
113
+ page_elements.element :page_section, selector
114
+ first = page_elements.element_definitions[:page_section].call(parent_page_element)
115
+ second = page_elements.element_definitions[:page_section].call(parent_page_element)
116
+ expect(first).to_not equal(second)
117
+ end
115
118
  end
116
- end
117
119
 
118
- describe 'location' do
119
- context 'a prefetched object' do
120
- it 'should add a section' do
121
- expected_section = PageMagic::Element.new(:page_section, parent_page_element, type: :element, browser_element: :object)
122
- page_elements.element :page_section, :object
123
- expected_section.should == page_elements.elements(parent_page_element).first
120
+ describe 'location' do
121
+ context 'a prefetched object' do
122
+ it 'should add a section' do
123
+ expected_section = Element.new(:page_section, parent_page_element, type: :element, browser_element: :object)
124
+ page_elements.element :page_section, :object
125
+ expect(expected_section).to eq(page_elements.elements(parent_page_element).first)
126
+ end
124
127
  end
125
128
  end
126
- end
127
129
 
128
- describe 'session handle' do
129
- it 'should be on instances created from a class' do
130
- browser_element = double(:browser_element, find: :browser_element)
131
- parent = double('parent', session: :current_session, browser_element: browser_element)
132
- page_elements.element :page_section, selector
130
+ describe 'session handle' do
131
+ it 'should be on instances created from a class' do
132
+ browser_element = double(:browser_element, find: :browser_element)
133
+ parent = double('parent', session: :current_session, browser_element: browser_element)
134
+ page_elements.element :page_section, selector
133
135
 
134
- section = page_elements.element_definitions[:page_section].call(parent)
136
+ section = page_elements.element_definitions[:page_section].call(parent)
135
137
 
136
- section.session.should == :current_session
137
- end
138
+ expect(section.session).to eq(:current_session)
139
+ end
138
140
 
139
- it 'should be on instances created dynamically using the section method' do
140
- browser_element = double('browser_element')
141
- browser_element.stub(:find)
142
- parent = double('parent', session: :current_session, browser_element: browser_element)
141
+ it 'should be on instances created dynamically using the section method' do
142
+ browser_element = double('browser_element')
143
+ allow(browser_element).to receive(:find)
144
+ parent = double('parent', session: :current_session, browser_element: browser_element)
143
145
 
144
- page_elements.section :page_section, css: :selector do
145
- end
146
+ page_elements.element :page_section, css: :selector do
147
+ end
146
148
 
147
- section = page_elements.element_definitions[:page_section].call(parent)
148
- section.session.should == :current_session
149
+ section = page_elements.element_definitions[:page_section].call(parent)
150
+ expect(section.session).to eq(:current_session)
151
+ end
149
152
  end
150
153
  end
151
- end
152
154
 
153
- describe 'retrieving element definitions' do
154
- it 'should return your a copy of the core definition' do
155
- page_elements.text_field :name, selector
156
- first = page_elements.element_definitions[:name].call(parent_page_element)
157
- second = page_elements.element_definitions[:name].call(parent_page_element)
158
- first.should_not equal(second)
155
+ describe 'retrieving element definitions' do
156
+ it 'should return your a copy of the core definition' do
157
+ page_elements.text_field :name, selector
158
+ first = page_elements.element_definitions[:name].call(parent_page_element)
159
+ second = page_elements.element_definitions[:name].call(parent_page_element)
160
+ expect(first).to_not equal(second)
161
+ end
159
162
  end
160
- end
161
163
 
162
- describe 'restrictions' do
163
- it 'should not allow method names that match element names' do
164
- expect do
165
- page_elements.class_eval do
166
- link(:hello, text: 'world')
164
+ describe 'restrictions' do
165
+ it 'should not allow method names that match element names' do
166
+ expect do
167
+ page_elements.class_eval do
168
+ link(:hello, text: 'world')
167
169
 
168
- def hello
170
+ def hello
171
+ end
169
172
  end
170
- end
171
- end.to raise_error(PageMagic::Elements::InvalidMethodNameException)
172
- end
173
+ end.to raise_error(InvalidMethodNameException)
174
+ end
173
175
 
174
- it 'should not allow element names that match method names' do
175
- expect do
176
- page_elements.class_eval do
177
- def hello
176
+ it 'should not allow element names that match method names' do
177
+ expect do
178
+ page_elements.class_eval do
179
+ def hello
180
+ end
181
+
182
+ link(:hello, text: 'world')
178
183
  end
184
+ end.to raise_error(InvalidElementNameException)
185
+ end
179
186
 
180
- link(:hello, text: 'world')
181
- end
182
- end.to raise_error(PageMagic::Elements::InvalidElementNameException)
183
- end
187
+ it 'should not allow duplicate element names' do
188
+ expect do
189
+ page_elements.class_eval do
190
+ link(:hello, text: 'world')
191
+ link(:hello, text: 'world')
192
+ end
193
+ end.to raise_error(InvalidElementNameException)
194
+ end
184
195
 
185
- it 'should not allow duplicate element names' do
186
- expect do
196
+ it 'should not evaluate the elements when applying naming checks' do
187
197
  page_elements.class_eval do
188
- link(:hello, text: 'world')
189
- link(:hello, text: 'world')
190
- end
191
- end.to raise_error(PageMagic::Elements::InvalidElementNameException)
192
- end
193
-
194
- it 'should not evaluate the elements when applying naming checks' do
195
- page_elements.class_eval do
196
- link(:link1, :selector) do
197
- fail('should not have been evaluated')
198
+ link(:link1, :selector) do
199
+ fail('should not have been evaluated')
200
+ end
201
+ link(:link2, :selector)
198
202
  end
199
- link(:link2, :selector)
200
203
  end
201
204
  end
202
205
  end
@@ -1,19 +1,62 @@
1
1
  describe PageMagic do
2
- context '#respond_to?' do
3
- subject do
4
- page_class = Class.new do
5
- include PageMagic
6
- element :sub_element, id: 'sub-element'
7
- end
8
- page_class.new
2
+ include_context :webapp_fixture
3
+ subject do
4
+ described_class = described_class()
5
+ page_class = Class.new do
6
+ include described_class
7
+ url '/page1'
8
+ link(:next_page, text: 'next page')
9
9
  end
10
+ page_class.new.tap(&:visit)
11
+ end
10
12
 
13
+ context '#respond_to?' do
11
14
  it 'checks self' do
12
15
  expect(subject.respond_to?(:visit)).to eq(true)
13
16
  end
14
17
 
15
18
  it 'checks the current page' do
16
- expect(subject.respond_to?(:sub_element)).to eq(true)
19
+ expect(subject.respond_to?(:next_page)).to eq(true)
20
+ end
21
+ end
22
+
23
+ describe 'visit' do
24
+ it 'goes to the class define url' do
25
+ expect(subject.session.current_path).to eq('/page1')
26
+ end
27
+ end
28
+
29
+ describe 'session' do
30
+ it 'gives access to the page magic object wrapping the user session' do
31
+ expect(subject.session.raw_session).to be(Capybara.current_session)
32
+ end
33
+ end
34
+
35
+ describe 'text_on_page?' do
36
+ it 'returns true if the text is present' do
37
+ expect(subject.text_on_page?('next page')).to eq(true)
38
+ end
39
+
40
+ it 'returns false if the text is not present' do
41
+ expect(subject.text_on_page?('not on page')). to eq(false)
42
+ end
43
+ end
44
+
45
+ describe 'title' do
46
+ it 'returns the title' do
47
+ expect(subject.title).to eq('page1')
48
+ end
49
+ end
50
+
51
+ describe 'text' do
52
+ it 'returns the text on the page' do
53
+ expect(subject.text).to eq('next page')
54
+ end
55
+ end
56
+
57
+ describe 'method_missing' do
58
+ it 'gives access to the elements defined on your page classes' do
59
+ expect(subject.next_page.tag_name).to eq('a')
17
60
  end
18
61
  end
19
62
  end
@@ -1,15 +1,16 @@
1
+ # rubocop:disable Metrics/ModuleLength
1
2
  module PageMagic
2
3
  describe Session do
3
4
  let(:page) do
4
5
  Class.new do
5
6
  include PageMagic
6
- url '/page1'
7
7
  end
8
8
  end
9
9
 
10
10
  subject { described_class.new(browser) }
11
11
 
12
- let(:browser) { double('browser', current_url: 'url', visit: nil, current_path: :current_path) }
12
+ let(:url) { 'http://url.com' }
13
+ let(:browser) { double('browser', current_url: url, visit: nil, current_path: :current_path) }
13
14
 
14
15
  describe '#current_url' do
15
16
  it "returns the browser's current url" do
@@ -33,7 +34,7 @@ module PageMagic
33
34
 
34
35
  before do
35
36
  subject.define_page_mappings another_page_class.url => another_page_class
36
- subject.visit(page)
37
+ subject.visit(page, url: url)
37
38
  end
38
39
 
39
40
  context 'page url has not changed' do
@@ -77,64 +78,81 @@ module PageMagic
77
78
  end
78
79
 
79
80
  describe '#visit' do
80
-
81
81
  let(:session) do
82
- PageMagic::Session.new(browser)
82
+ allow(browser).to receive(:visit)
83
+ PageMagic::Session.new(browser, url)
83
84
  end
84
85
 
85
- context 'page supplied' do
86
- context 'url supplied' do
87
- it 'uses this url instead of the one defined on the page class' do
88
- expect(browser).to receive(:visit).with(:custom_url)
89
- session.visit(page, url: :custom_url)
90
- expect(session.current_page).to be_a(page)
91
- end
86
+ it 'sets the current page' do
87
+ session.define_page_mappings '/page' => page
88
+ session.visit(page)
89
+ expect(session.current_page).to be_a(page)
90
+ end
91
+
92
+ it 'uses the current url and the path in the page mappings' do
93
+ session.define_page_mappings '/page' => page
94
+ expect(browser).to receive(:visit).with("#{browser.current_url}/page")
95
+ session.visit(page)
96
+ end
97
+
98
+ context 'no mappings found' do
99
+ it 'raises an error' do
100
+ expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::URL_MISSING_MSG
92
101
  end
102
+ end
93
103
 
94
- context 'url defined on page_class' do
95
- it 'visits the url on defined on the page class' do
96
- browser.should_receive(:visit).with(page.url)
97
- session.visit(page)
98
- expect(session.current_page).to be_a(page)
99
- end
104
+ context 'mapping is a regular expression' do
105
+ it 'raises an error' do
106
+ session.define_page_mappings(/mapping/ => page)
107
+ expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::REGEXP_MAPPING_MSG
108
+ end
109
+ end
110
+
111
+ context 'url supplied' do
112
+ it 'visits that url' do
113
+ expected_url = 'http://url.com/page'
114
+ expect(browser).to receive(:visit).with(expected_url)
115
+ session.visit(url: expected_url)
100
116
  end
117
+ end
118
+ end
119
+
120
+ describe '#url' do
121
+ let!(:base_url) { 'http://example.com' }
122
+ let!(:path) { 'home' }
123
+ let!(:expected_url) { "#{base_url}/#{path}" }
101
124
 
102
- context 'url not specified' do
103
- context 'url not specified on page class' do
104
- before do
105
- page.instance_variable_set(:@url, nil)
106
- end
107
- it 'uses the current url and the path in the page mappings' do
108
- session.define_page_mappings '/page' => page
109
- expect(browser).to receive(:visit).with("#{browser.current_url}/page")
110
- session.visit(page)
111
- end
112
-
113
- context 'no mappings found' do
114
- it 'raises an error' do
115
- expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::URL_MISSING_MSG
116
- end
117
- end
118
-
119
- context 'mapping is a regular expression' do
120
- it 'raises an error' do
121
- session.define_page_mappings %r{mapping} => page
122
- expect { session.visit(page) }.to raise_exception InvalidURLException, described_class::REGEXP_MAPPING_MSG
123
- end
124
- end
125
+ context 'base_url has a / on the end' do
126
+ before do
127
+ base_url << '/'
128
+ end
129
+
130
+ context 'path has / at the beginning' do
131
+ it 'produces compound url' do
132
+ expect(subject.url(base_url, path)).to eq(expected_url)
125
133
  end
126
134
  end
127
135
 
128
- context 'url supplied' do
129
- it 'visits that url' do
130
- expected_url = 'http://url.com'
131
- expect(browser).to receive(:visit).with(expected_url)
132
- session.visit(expected_url)
136
+ context 'path does not have / at the beginning' do
137
+ it 'produces compound url' do
138
+ expect(subject.url(base_url, "/#{path}")).to eq(expected_url)
133
139
  end
134
140
  end
135
141
  end
136
142
 
143
+ context 'current_url does not have a / on the end' do
144
+ context 'path has / at the beginning' do
145
+ it 'produces compound url' do
146
+ expect(subject.url(base_url, "/#{path}")).to eq(expected_url)
147
+ end
148
+ end
137
149
 
150
+ context 'path does not have / at the beginning' do
151
+ it 'produces compound url' do
152
+ expect(subject.url(base_url, path)).to eq(expected_url)
153
+ end
154
+ end
155
+ end
138
156
  end
139
157
 
140
158
  context '#method_missing' do
@@ -145,15 +163,15 @@ module PageMagic
145
163
  end
146
164
  end
147
165
 
148
- session = PageMagic::Session.new(browser).visit(page)
149
- session.my_method.should be(:called)
166
+ session = PageMagic::Session.new(browser).visit(page, url: url)
167
+ expect(session.my_method).to be(:called)
150
168
  end
151
169
  end
152
170
 
153
171
  context '#respond_to?' do
154
172
  subject do
155
173
  PageMagic::Session.new(browser).tap do |s|
156
- s.current_page = page.new
174
+ allow(s).to receive(:current_page).and_return(page.new)
157
175
  end
158
176
  end
159
177
  it 'checks self' do
@@ -162,11 +180,11 @@ module PageMagic
162
180
 
163
181
  it 'checks the current page' do
164
182
  page.class_eval do
165
- def my_method;
183
+ def my_method
166
184
  end
167
185
  end
168
186
  expect(subject.respond_to?(:my_method)).to eq(true)
169
187
  end
170
188
  end
171
189
  end
172
- end
190
+ end