page_magic 1.0.0.alpha10 → 1.0.0.alpha11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6d169c7cf7a4d49cfe0424e561f0a52cc732ec56
4
- data.tar.gz: c8c26faa46d799b27f985e88bbec7ae21839b227
3
+ metadata.gz: df390dca05439be5b971179c257c5b8d6e73ade2
4
+ data.tar.gz: 63e5f1d5579f2981e69ff1dbc8dc31d3505f2e9c
5
5
  SHA512:
6
- metadata.gz: f9c32d2a85aad55ab12396ff2fad7da5b3e8bc319eef54ba34ec27182f24564853ed110b5b450ec8aea3bdeca2a70a2a992336a0e82186a5c9d32d66fa3e478c
7
- data.tar.gz: 002e9bc54cc7e99e4c0d05996d1afeed3a68d141264d44bcef6e1ff47231f1083cc611bc0bb3a8445cbe30d96f37ee5d766a08c79e49df356156bd85bc57b7bf
6
+ metadata.gz: e635b5836e8a2376b28507c87240d09b870a2d6720aa3e94eac6fc5723e1269c85659a935f7dada8b1543afa48d47b0e8c0dcdf87f065c9937523aed73207b63
7
+ data.tar.gz: a710f169e452e3408652064347feedf1f81ddc2d4d9093fd948299f683f51f6fb1a71d00601e71ce7a6508761994206d885922010f257ff22886dd01cc4b1686
data/README.md CHANGED
@@ -4,10 +4,10 @@ PageMagic is an API for testing web applications.
4
4
  It has a simple but powerful DSL which makes modelling and interacting with your pages easy.
5
5
 
6
6
  Wouldn't it be great if there was a framework that could:
7
- - Model your pages
8
- - Define custom wait activity that should occur before or after you interact with a page element at the point the element is defined
9
- - Map the paths to pages so that when you transition from one page to another, you don't have to do awkward things to work out which page object you need to use next?
10
- - Be really really dynamic so that you could do even more things at runtime?
7
+ - [Model your pages](#modelling-pages)
8
+ - [Fluently define interaction hooks / waiters on page elements](#interaction-hooks)
9
+ - [Provide urls to pages to avoid awkward page object switching](#page-mapping)
10
+ - [Be super dynamic](#dynamic-selectors)
11
11
 
12
12
  Well PageMagic might just be the answer!
13
13
 
@@ -58,35 +58,13 @@ Out of the box, PageMagic knows how to work with:
58
58
  - poltergeist
59
59
  - RackTest - Read more on testing rack compliant object's directly later on
60
60
 
61
- Under the hood, PageMagic is using [Capybara](https://github.com/jnicklas/capybara) so you can register any Capybara specific driver you want. See below for how to do this.
61
+ Under the hood, PageMagic is using [Capybara](https://github.com/jnicklas/capybara) so you can register any Capybara specific driver you want. See [below](#registering-a-custom-driver) for how to do this.
62
62
 
63
63
  **Note:** We don't want to impose particular driver versions so PageMagic does not list any as dependencies. Therefore you will need add the requiste gem to your Gemfile.
64
64
 
65
- ## Defining Pages
66
- To define something that PageMagic can work with, simply include PageMagic in to a class. Here are the classes we would need for the example above.
67
- ```ruby
68
- class LoginPage
69
- include PageMagic
70
- end
71
-
72
- class MailBox
73
- include PageMagic
74
- end
75
-
76
- class MessageView
77
- include PageMagic
78
- end
79
- ```
65
+ ## Modeling pages
66
+ To define something that PageMagic can work with, simply include PageMagic in to a class. Your you will also want to model the elements on your page so that you can interact with them. Here are we are modelling the login page we would need for the example above
80
67
 
81
- ## Visiting a page
82
- To use a page ojbect you need to 'visit' it.
83
- ```ruby
84
- session.visit(LoginPage, url: 'https://21st-century-mail.com')
85
- ```
86
- **Note:** soon you won't even have to specify the page class :)
87
-
88
- ##Defining elements
89
- Your pages are going to have elements on them that you will want to interact with. In the case of the Login page, it's easy to imagine that it will have text fields for a username and password and a button to login in with.
90
68
  ```ruby
91
69
  class LoginPage
92
70
  include PageMagic
@@ -95,6 +73,8 @@ class LoginPage
95
73
  button(:login_button, text: 'login')
96
74
  end
97
75
  ```
76
+ In the case of the Login page, it's easy to imagine that it will have text fields for a username and password and a button to login in with.
77
+
98
78
  ##Interacting with elements
99
79
  Elements are defined with a id which is the name of the method you will use to reference it. In the above example, the textfields and button were defined with the id's, `:username`, `:password`, and `:login_button`
100
80
 
@@ -104,7 +84,24 @@ session.username.set 'joe@blogs.com'
104
84
  session.password.set 'passw0rd'
105
85
  session.login_button.click
106
86
  ```
107
- ##Defining helper methods
87
+
88
+ ## Defining Pages
89
+ To define something that PageMagic can work with, simply include PageMagic in to a class. Here are the classes we would need for the example above.
90
+ ```ruby
91
+ class LoginPage
92
+ include PageMagic
93
+ end
94
+
95
+ class MailBox
96
+ include PageMagic
97
+ end
98
+
99
+ class MessageView
100
+ include PageMagic
101
+ end
102
+ ```
103
+
104
+ ## Helper methods
108
105
  Using elements that are defined on a page is great, but if you are enacting a procedure through interacting with a few of them then your code could end up with some pretty repetitive code. In this case you can define helper methods instead.
109
106
 
110
107
  In the above [example](#an example) we used a helper called `login`.
@@ -183,6 +180,24 @@ browser.define_page_mappings %r{/messages/\d+} => MessagePage,
183
180
  ```
184
181
  You can use even use regular expressions to map multiple paths to the same page. In the above example we are mapping paths that that starts with '/messages/' and are followed by one ore more digits to the `MessagePage` class.
185
182
 
183
+ ## Registering a custom driver
184
+ You can register any Capybara compliant driver as follows
185
+
186
+ ```ruby
187
+ #1. Define driver, constructor to PageMagic::Driver takes a list of browser aliases.
188
+ # Selenium Webdriver for example supports driving more than one.
189
+ Webkit = PageMagic::Driver.new(:webkit) do |app, options, browser_alias_chosen|
190
+ # Write the code necessary to initialise the driver you have chosen
191
+ require 'capybara/webkit'
192
+ Capybara::Webkit::Driver.new(app, options)
193
+ end
194
+
195
+ #2. Register driver
196
+ PageMagic.drivers.register Webkit
197
+
198
+ #3. Use registered driver
199
+ session = PageMagic.session(browser: webkit)
200
+ ```
186
201
  ##What else can you do with PageMagic?
187
202
  PageMagic has lots of other useful features. I'm writing up the documentation so check back here soon!
188
203
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.alpha10
1
+ 1.0.0.alpha11
@@ -10,6 +10,7 @@ module PageMagic
10
10
  end
11
11
 
12
12
  class Element
13
+ EVENT_TYPES = [:set, :select, :select_option, :unselect_option, :click]
13
14
  attr_reader :type, :name, :selector, :browser_element
14
15
 
15
16
  include Elements
@@ -26,7 +27,7 @@ module PageMagic
26
27
  end
27
28
 
28
29
  def initialize(name, parent_page_element, options, &block)
29
- options = { type: :element, selector: {}, browser_element: nil }.merge(options)
30
+ options = {type: :element, selector: {}, browser_element: nil}.merge(options)
30
31
  @browser_element = options[:browser_element]
31
32
  @selector = options[:selector]
32
33
 
@@ -67,13 +68,17 @@ module PageMagic
67
68
  @after_hook = block
68
69
  end
69
70
 
70
- def method_missing(method, *args)
71
- element_context(args).send(method, args.first)
72
- rescue ElementMissingException
71
+ def method_missing method, *args, &block
73
72
  begin
74
- @browser_element.send(method, *args)
75
- rescue
76
- super
73
+ ElementContext.new(self, browser_element, self, *args).send(method, args.first, &block)
74
+ rescue ElementMissingException
75
+ if browser_element.respond_to?(method)
76
+ browser_element.send(method, *args, &block)
77
+ elsif @parent_page_element.respond_to?(method)
78
+ @parent_page_element.send(method, *args, &block)
79
+ else
80
+ super
81
+ end
77
82
  end
78
83
  end
79
84
 
@@ -91,34 +96,63 @@ module PageMagic
91
96
  options = selector_copy
92
97
 
93
98
  finder_method, selector_type, selector_arg = case method
94
- when :id
95
- [:find, "##{selector}"]
96
- when :xpath
97
- [:find, :xpath, selector]
98
- when :name
99
- [:find, "*[name='#{selector}']"]
100
- when :css
101
- [:find, :css, selector]
102
- when :label
103
- [:find_field, selector]
104
- when :text
105
- if @type == :link
106
- [:find_link, selector]
107
- elsif @type == :button
108
- [:find_button, selector]
99
+ when :id
100
+ [:find, "##{selector}"]
101
+ when :xpath
102
+ [:find, :xpath, selector]
103
+ when :name
104
+ [:find, "*[name='#{selector}']"]
105
+ when :css
106
+ [:find, :css, selector]
107
+ when :label
108
+ [:find_field, selector]
109
+ when :text
110
+ if @type == :link
111
+ [:find_link, selector]
112
+ elsif @type == :button
113
+ [:find_button, selector]
114
+ else
115
+ fail UnsupportedSelectorException
116
+ end
117
+
109
118
  else
110
119
  fail UnsupportedSelectorException
111
- end
112
-
113
- else
114
- fail UnsupportedSelectorException
115
120
  end
116
121
 
117
122
  finder_args = [selector_type, selector_arg].compact
118
123
  finder_args << options unless options.empty?
119
- @browser_element = @parent_page_element.browser_element.send(finder_method, *finder_args)
124
+ @browser_element = @parent_page_element.browser_element.send(finder_method, *finder_args).tap do |browser_element|
125
+ EVENT_TYPES.each do |action_method|
126
+ apply_hooks(page_element: browser_element,
127
+ capybara_method: action_method,
128
+ before_hook: before,
129
+ after_hook: after)
130
+ end
131
+ end
132
+
120
133
  end
121
- @browser_element
134
+ end
135
+
136
+ def apply_hooks(options)
137
+ _self = self
138
+ page_element = options[:page_element]
139
+ capybara_method = options[:capybara_method]
140
+ if page_element.respond_to?(capybara_method)
141
+ original_method = page_element.method(capybara_method)
142
+
143
+ page_element.define_singleton_method capybara_method do |*arguments, &block|
144
+ _self.call_hook &options[:before_hook]
145
+ original_method.call *arguments, &block
146
+ _self.call_hook &options[:after_hook]
147
+ end
148
+ end
149
+ end
150
+
151
+ def call_hook(&block)
152
+ @executing_hooks = true
153
+ result = instance_exec @browser, &block
154
+ @executing_hooks = false
155
+ result
122
156
  end
123
157
 
124
158
  private
@@ -3,6 +3,8 @@ module PageMagic
3
3
  end
4
4
 
5
5
  class ElementContext
6
+ EVENT_TYPES = [:set, :select, :select_option, :unselect_option, :click]
7
+
6
8
  attr_reader :caller, :page_element
7
9
 
8
10
  def initialize(page_element, browser, caller, *_args)
@@ -11,55 +13,24 @@ module PageMagic
11
13
  @caller = caller
12
14
  end
13
15
 
14
- def method_missing(method, *args)
15
- return @caller.send(method, *args) if @executing_hooks
16
- return @page_element.send(method, *args) if @page_element.methods.include?(method)
16
+ def method_missing(method, *args, &block)
17
+ return page_element.send(method, *args, &block) if page_element.methods.include?(method)
17
18
 
18
- element_locator_factory = @page_element.element_definitions[method]
19
+ element_locator_factory = page_element.element_definitions[method]
19
20
 
20
- fail ElementMissingException, "Could not find: #{method}" unless element_locator_factory
21
+ raise ElementMissingException, "Could not find: #{method}" unless element_locator_factory
21
22
 
22
23
  if args.empty?
23
- element_locator = element_locator_factory.call(@page_element, nil)
24
+ element_locator = element_locator_factory.call(page_element, nil)
24
25
  else
25
- element_locator = element_locator_factory.call(@page_element, *args)
26
- end
27
-
28
- [:set, :select_option, :unselect_option, :click].each do |action_method|
29
- apply_hooks(page_element: element_locator.browser_element,
30
- capybara_method: action_method,
31
- before_hook: element_locator.before,
32
- after_hook: element_locator.after
33
- )
26
+ element_locator = element_locator_factory.call(page_element, *args)
34
27
  end
35
28
 
36
29
  element_locator.section? ? element_locator : element_locator.browser_element
37
30
  end
38
31
 
39
32
  def respond_to?(*args)
40
- @page_element.element_definitions.keys.include?(args.first)
41
- end
42
-
43
- def apply_hooks(options)
44
- _self = self
45
- page_element = options[:page_element]
46
- capybara_method = options[:capybara_method]
47
- if page_element.respond_to?(capybara_method)
48
- original_method = page_element.method(capybara_method)
49
-
50
- page_element.define_singleton_method capybara_method do |*arguments, &block|
51
- _self.call_hook &options[:before_hook]
52
- original_method.call *arguments, &block
53
- _self.call_hook &options[:after_hook]
54
- end
55
- end
56
- end
57
-
58
- def call_hook(&block)
59
- @executing_hooks = true
60
- result = instance_exec @browser, &block
61
- @executing_hooks = false
62
- result
33
+ page_element.element_definitions.keys.include?(args.first)
63
34
  end
64
35
  end
65
36
  end
data/spec/element_spec.rb CHANGED
@@ -1,218 +1,232 @@
1
- describe 'Page elements' do
2
- before :each do
3
- Capybara.app = Class.new(Sinatra::Base) do
4
- get '/' do
5
- <<-HTML
6
- <label>enter text
7
- <input id='field_id' name='field_name' class='input_class' type='text' value='filled in'/>
8
- </label>
9
- <a id=my_link href='#'>my link</a>
10
- <button id=my_button href='#'>my button</button>
11
- HTML
12
- end
13
- end
1
+ module PageMagic
14
2
 
15
- Capybara.current_session.visit('/')
16
- end
3
+ describe Element do
17
4
 
18
- describe 'inheriting' do
19
5
  include_context :webapp
20
6
 
21
- it 'lets you create custom elements' do
22
- custom_element = Class.new(PageMagic::Element) do
23
- selector css: '.form'
24
-
25
- link :form_link, id: 'form_link'
26
- def self.name
27
- 'Form'
28
- end
29
- end
30
-
31
- page = Class.new do
7
+ let(:page_class) do
8
+ Class.new do
32
9
  include PageMagic
33
10
  url '/elements'
34
- section custom_element
35
11
  end
12
+ end
36
13
 
37
- page = page.new
38
- page.visit
39
- page.form.form_link.visible?.should be_true
14
+ let(:page) do
15
+ page_class.new.tap do |page|
16
+ page.visit
17
+ end
40
18
  end
41
- end
42
19
 
43
- it 'should raise an error if a selector has not been specified' do
44
- expect { PageMagic::Element.new(:name, Object.new, type: :element).browser_element }.to raise_error(PageMagic::UndefinedSelectorException)
45
- end
20
+ describe 'inheriting' do
21
+
22
+ it 'lets you create custom elements' do
23
+ custom_element = Class.new(described_class) do
24
+ text_field :form_field, id: 'field_id'
25
+
26
+ def self.name
27
+ 'Form'
28
+ end
29
+ end
46
30
 
47
- describe '#respond_to?' do
48
- subject do
49
- PageMagic::Element.new(:name, Object.new, type: :element, browser_element: double(element_method: '')) do
50
- element :sub_element, css: '.sub-element'
31
+ page_class.class_eval do
32
+ section custom_element, css: '.form'
33
+ end
34
+
35
+ expect(page.form.form_field).to be_visible
51
36
  end
52
37
  end
53
- it 'checks for methods on self' do
54
- expect(subject.respond_to?(:session)).to eq(true)
55
- end
56
38
 
57
- it 'checks against registered elements' do
58
- expect(subject.respond_to?(:sub_element)).to eq(true)
39
+ it 'should raise an error if a selector has not been specified' do
40
+ expect { described_class.new(:name, Object.new, type: :element).browser_element }.to raise_error(PageMagic::UndefinedSelectorException)
59
41
  end
60
42
 
61
- it 'checks for the method of the browser_element' do
62
- expect(subject.respond_to?(:element_method)).to eq(true)
63
- end
64
- end
43
+ describe '#respond_to?' do
44
+ subject do
45
+ described_class.new(:name, Object.new, type: :element, browser_element: double(element_method: '')) do
46
+ element :sub_element, css: '.sub-element'
47
+ end
48
+ end
49
+ it 'checks for methods on self' do
50
+ expect(subject.respond_to?(:session)).to eq(true)
51
+ end
65
52
 
66
- describe '#browser_element' do
67
- let!(:browser) { double('browser') }
68
- let!(:page) do
69
- page_class = Class.new do
70
- include PageMagic
53
+ it 'checks against registered elements' do
54
+ expect(subject.respond_to?(:sub_element)).to eq(true)
71
55
  end
72
- page_class.new
73
- end
74
56
 
75
- context 'options supplied to selector' do
76
- it 'passes them on to the cappybara finder method' do
77
- options = { key: :value }
78
- xpath_selector = '//input'
79
- expect(Capybara.current_session).to receive(:find).with(:xpath, xpath_selector, options)
80
- PageMagic::Element.new(:my_input, page, type: :text_field, selector: { xpath: xpath_selector }.merge(options)).browser_element
57
+ it 'checks for the method of the browser_element' do
58
+ expect(subject.respond_to?(:element_method)).to eq(true)
81
59
  end
82
60
  end
83
61
 
84
- it 'should find by xpath' do
85
- element = PageMagic::Element.new(:my_input, page, type: :text_field, selector: { xpath: '//input' }).browser_element
86
- element.value == 'filled in'
87
- end
62
+ describe '#browser_element' do
63
+ let!(:browser) { double('browser') }
88
64
 
89
- it 'should locate an element using its id' do
90
- element = PageMagic::Element.new(:my_input, page, type: :text_field, selector: { id: 'field_id' }).browser_element
91
- element.value.should == 'filled in'
92
- end
65
+ context 'options supplied to selector' do
66
+ it 'passes them on to the cappybara finder method' do
67
+ options = {count: 1}
68
+ xpath_selector = '//div/input'
69
+ expect(Capybara.current_session).to receive(:find).with(:xpath, xpath_selector, options)
70
+ described_class.new(:my_input, page, type: :text_field, selector: {xpath: xpath_selector}.merge(options)).browser_element
71
+ end
72
+ end
93
73
 
94
- it 'should locate an element using its name' do
95
- element = PageMagic::Element.new(:my_input, page, type: :text_field, selector: { name: 'field_name' }).browser_element
96
- element.value.should == 'filled in'
97
- end
74
+ it 'should find by xpath' do
75
+ element = described_class.new(:my_input, page, type: :text_field, selector: {xpath: '//div/label/input'}).browser_element
76
+ expect(element.value).to eq('filled in')
77
+ end
98
78
 
99
- it 'should locate an element using its label' do
100
- element = PageMagic::Element.new(:my_link, page, type: :link, selector: { label: 'enter text' }).browser_element
101
- element[:id].should == 'field_id'
102
- end
79
+ it 'should locate an element using its id' do
80
+ element = described_class.new(:my_input, page, type: :text_field, selector: {id: 'field_id'}).browser_element
81
+ expect(element.value).to eq('filled in')
82
+ end
103
83
 
104
- it 'should raise an exception when finding another element using its text' do
105
- expect { PageMagic::Element.new(:my_link, page, type: :text_field, selector: { text: 'my link' }).browser_element }.to raise_error(PageMagic::UnsupportedSelectorException)
106
- end
84
+ it 'should locate an element using its name' do
85
+ element = described_class.new(:my_input, page, type: :text_field, selector: {name: 'field_name'}).browser_element
86
+ expect(element.value).to eq('filled in')
87
+ end
107
88
 
108
- it 'should locate an element using css' do
109
- element = PageMagic::Element.new(:my_link, page, type: :link, selector: { css: "input[name='field_name']" }).browser_element
110
- element[:id].should == 'field_id'
111
- end
89
+ it 'should locate an element using its label' do
90
+ element = described_class.new(:my_link, page, type: :link, selector: {label: 'enter text'}).browser_element
91
+ expect(element[:id]).to eq('field_id')
92
+ end
112
93
 
113
- it 'should return a prefetched value' do
114
- PageMagic::Element.new(:help, page, type: :link, browser_element: :prefetched_object).browser_element.should == :prefetched_object
115
- end
94
+ it 'should raise an exception when finding another element using its text' do
95
+ expect { described_class.new(:my_link, page, type: :text_field, selector: {text: 'my link'}).browser_element }.to raise_error(PageMagic::UnsupportedSelectorException)
96
+ end
116
97
 
117
- it 'should raise errors for unsupported selectors' do
118
- expect { PageMagic::Element.new(:my_link, page, type: :link, selector: { unsupported: '' }).browser_element }.to raise_error(PageMagic::UnsupportedSelectorException)
119
- end
98
+ it 'should locate an element using css' do
99
+ element = described_class.new(:my_link, page, type: :link, selector: {css: "input[name='field_name']"}).browser_element
100
+ expect(element[:id]).to eq('field_id')
101
+ end
120
102
 
121
- context 'text selector' do
122
- it 'should locate a link' do
123
- element = PageMagic::Element.new(:my_link, page, type: :link, selector: { text: 'my link' }).browser_element
124
- element[:id].should == 'my_link'
103
+ it 'should return a prefetched value' do
104
+ described_class.new(:help, page, type: :link, browser_element: :prefetched_object).browser_element.should == :prefetched_object
125
105
  end
126
106
 
127
- it 'should locate a button' do
128
- element = PageMagic::Element.new(:my_button, page, type: :button, selector: { text: 'my button' }).browser_element
129
- element[:id].should == 'my_button'
107
+ it 'should raise errors for unsupported selectors' do
108
+ expect { described_class.new(:my_link, page, type: :link, selector: {unsupported: ''}).browser_element }.to raise_error(PageMagic::UnsupportedSelectorException)
130
109
  end
131
- end
132
- end
133
110
 
134
- describe '#section?' do
135
- context 'element definitions exist' do
136
- subject do
137
- PageMagic::Element.new(:my_link, :page, type: :link, selector: { text: 'my link' }) do
138
- element :thing, text: 'text'
111
+ context 'text selector' do
112
+ it 'should locate a link' do
113
+ element = described_class.new(:my_link, page, type: :link, selector: {text: 'link in a form'}).browser_element
114
+ expect(element[:id]).to eq('form_link')
115
+ end
116
+
117
+ it 'should locate a button' do
118
+ element = described_class.new(:my_button, page, type: :button, selector: {text: 'a button'}).browser_element
119
+ element[:id].should == 'form_button'
139
120
  end
140
- end
141
- it 'returns true' do
142
- expect(subject.section?).to eq(true)
143
121
  end
144
122
  end
145
123
 
146
- context 'method defined' do
147
- subject do
148
- PageMagic::Element.new(:my_link, :page, type: :link, selector: { text: 'my link' }) do
149
- def custom_method
124
+ describe '#section?' do
125
+ context 'element definitions exist' do
126
+ subject do
127
+ described_class.new(:my_link, :page, type: :link, selector: {text: 'my link'}) do
128
+ element :thing, text: 'text'
129
+ end
130
+ end
131
+ it 'returns true' do
132
+ expect(subject.section?).to eq(true)
133
+ end
134
+ end
135
+
136
+ context 'method defined' do
137
+ subject do
138
+ described_class.new(:my_link, :page, type: :link, selector: {text: 'my link'}) do
139
+ def custom_method
140
+ end
150
141
  end
151
142
  end
143
+
144
+ it 'returns true' do
145
+ expect(subject.section?).to eq(true)
146
+ end
152
147
  end
153
148
 
154
- it 'returns true' do
155
- expect(subject.section?).to eq(true)
149
+ context 'neither method or elements defined' do
150
+ subject do
151
+ described_class.new(:my_link, :page, type: :link, selector: {text: 'my link'})
152
+ end
153
+ it 'returns false' do
154
+ expect(subject.section?).to eq(false)
155
+ end
156
156
  end
157
157
  end
158
158
 
159
- context 'neither method or elements defined' do
159
+ describe 'session' do
160
+ it 'should have a handle to the session' do
161
+ expect(described_class.new(:help, page, type: :link, selector: :selector).session).to eq(page.session)
162
+ end
163
+ end
164
+
165
+ describe 'hooks' do
160
166
  subject do
161
- PageMagic::Element.new(:my_link, :page, type: :link, selector: { text: 'my link' })
167
+ described_class.new(:my_button, page, type: :button, selector: {id: 'my_button'}) do
168
+ before do
169
+ call_in_before_hook
170
+ end
171
+ end
162
172
  end
163
- it 'returns false' do
164
- expect(subject.section?).to eq(false)
173
+ context 'method called in before hook' do
174
+ it 'calls methods on the page element' do
175
+ expect(page.browser).to receive(:find).and_return(double('button', click: true))
176
+ expect(subject).to receive(:call_in_before_hook)
177
+ subject.click
178
+ end
165
179
  end
166
- end
167
- end
168
180
 
169
- describe 'session' do
170
- it 'should have a handle to the session' do
171
- page_class = Class.new do
172
- include PageMagic
181
+ context 'method called in before hook' do
182
+ subject do
183
+ described_class.new(:my_button, page, type: :button, selector: {id: 'my_button'}) do
184
+ after do
185
+ call_in_after_hook
186
+ end
187
+ end
188
+ end
189
+ it 'calls methods on the page element' do
190
+ expect(page.browser).to receive(:find).and_return(double('button', click: true))
191
+ expect(subject).to receive(:call_in_after_hook)
192
+ subject.click
193
+ end
173
194
  end
174
- page = page_class.new
175
195
 
176
- PageMagic::Element.new(:help, page, type: :link, selector: :selector).session.should == page.session
177
196
  end
178
- end
179
197
 
180
- context 'tests coppied in from section' do
181
- include_context :webapp
182
-
183
- before :each do
184
- @elements_page = elements_page.new
185
- @elements_page.visit
186
- end
198
+ describe '#method_missing' do
187
199
 
188
- let!(:elements_page) do
189
- Class.new do
190
- include PageMagic
191
- url '/elements'
192
- section :form_by_css do
193
- selector css: '.form'
194
- link(:link_in_form, text: 'a in a form')
200
+ before do
201
+ page_class.class_eval do
202
+ section :form_by_css, css: '.form' do
203
+ link(:link_in_form, text: 'a in a form')
204
+ end
195
205
  end
206
+ end
196
207
 
197
- section :form_by_id do
198
- selector id: 'form'
199
- link(:link_in_form, text: 'a in a form')
200
- end
208
+ it 'can delegate to capybara' do
209
+ expect(page.form_by_css).to be_visible
201
210
  end
202
- end
203
211
 
204
- describe 'method_missing' do
205
- it 'should delegate to capybara' do
206
- @elements_page.form_by_css.visible?.should be(true)
212
+ context 'method not on capybara browser element' do
213
+ it 'uses the parent page element' do
214
+ page_class.class_eval do
215
+ def parent_method
216
+ :called
217
+ end
218
+ end
219
+ expect(page.form_by_css.parent_method).to eq(:called)
220
+ end
207
221
  end
208
222
 
209
- it 'should throw default exception if the method does not exist on the capybara object' do
210
- expect { @elements_page.form_by_css.bobbins }.to raise_exception NoMethodError
223
+ context 'no element definition and not a capybara method' do
224
+ it 'throws and exception' do
225
+ expect { page.form_by_css.bobbins }.to raise_exception NoMethodError
226
+ end
211
227
  end
212
- end
213
228
 
214
- it 'can have elements' do
215
- @elements_page.form_by_css.link_in_form.visible?.should be_true
216
229
  end
230
+
217
231
  end
218
- end
232
+ end
@@ -1,126 +1,72 @@
1
- describe PageMagic::ElementContext do
2
- include_context :webapp
1
+ module PageMagic
3
2
 
4
- let!(:page1) do
5
- Class.new do
6
- include PageMagic
7
- url '/page1'
8
- link(:next, text: 'next page')
3
+ describe ElementContext do
4
+ include_context :webapp
5
+
6
+ let!(:elements_page) do
7
+ Class.new do
8
+ include PageMagic
9
+ url '/elements'
10
+ link(:a_link, text: 'a link')
11
+ end
9
12
  end
10
- end
11
13
 
12
- let!(:elements_page) do
13
- Class.new do
14
- include PageMagic
15
- url '/elements'
16
- link(:a_link, text: 'a link')
14
+ let!(:session) do
15
+ double('session', raw_session: double('browser'))
17
16
  end
18
- end
19
17
 
20
- let!(:session) do
21
- double('session', raw_session: double('browser'))
22
- end
18
+ describe '#method_missing' do
23
19
 
24
- describe 'resolving field definitions' do
25
- it 'should only evaluate the targeted field definition' do
26
- page1.class_eval do
27
- link(:link, :selector) do
28
- fail('should not have been evaluated')
20
+ let(:page) do
21
+ elements_page.new.tap do |page|
22
+ page.visit
29
23
  end
30
24
  end
31
- page = page1.new
32
- page.visit
33
-
34
- described_class.new(page, page.browser, self).next
35
- end
36
- end
37
-
38
- it 'should raise an error if an element is not found' do
39
- expect { described_class.new(page1.new(session), session, self).missing_thing }.to raise_error PageMagic::ElementMissingException
40
- end
41
25
 
42
- it 'should attempt to execute method on page object it is defined' do
43
- page1.class_eval do
44
- def page_method
45
- :called
26
+ context 'neither a method or page element are defined' do
27
+ it 'raises an error' do
28
+ expect { described_class.new(page, page.browser, self).missing_thing }.to raise_error PageMagic::ElementMissingException
29
+ end
46
30
  end
47
- end
48
-
49
- described_class.new(page1.new(session), session, self).page_method.should == :called
50
- end
51
31
 
52
- describe 'retrieving elements' do
53
- it 'should give the capybara object' do
54
- page = elements_page.new
55
- page.visit
32
+ context 'method is a element defintion' do
33
+ it 'returns the sub page element' do
34
+ element = described_class.new(page, page.browser, self).a_link
35
+ #TODO - returns the capybara object. maybe we should think about wrapping this.
36
+ expect(element.text).to eq('a link')
37
+ end
56
38
 
57
- element = described_class.new(page, page.browser, self).a_link
58
- element.text.should == 'a link'
59
- end
60
- end
39
+ it 'does not evaluate any of the other definitions' do
40
+ elements_page.class_eval do
41
+ link(:another_link, :selector) do
42
+ fail('should not have been evaluated')
43
+ end
44
+ end
61
45
 
62
- describe 'accessing page sections' do
63
- it 'should go through page sections' do
64
- elements_page.class_eval do
65
- section :form do
66
- selector css: '.form'
67
- link :form_link, text: 'in a form'
46
+ described_class.new(page, page.browser, self).a_link
68
47
  end
69
48
  end
70
49
 
71
- page = elements_page.new
72
- page.visit
73
-
74
- described_class.new(page, page.browser, self).form
75
- end
76
-
77
- it 'should delegate to page element if method not found' do
78
- # TODO: call page method, look for subelement, delagate to capybara object
79
- end
80
- end
81
-
82
- describe 'hooks' do
83
- subject(:page) do
84
- elements_page.new.tap(&:visit)
85
- end
86
-
87
- before do
88
- browser = page.browser
89
- browser.should_receive(:call_in_before_hook)
90
- browser.should_receive(:call_in_after_before_hook)
91
- end
92
-
93
- context 'section' do
94
- it 'applies the hooks' do
95
- elements_page.section(:form, id: 'form') do
96
- link :form_link, id: 'form_link'
50
+ context 'method found on page_element' do
51
+ it 'calls page_element method' do
52
+ elements_page.class_eval do
53
+ def page_method
54
+ :called
55
+ end
56
+ end
97
57
 
98
- before(&:call_in_before_hook)
99
-
100
- after(&:call_in_after_before_hook)
58
+ expect(described_class.new(page, :browser, self).page_method).to eq(:called)
101
59
  end
102
-
103
- described_class.new(page, page.browser, self).form.click
104
60
  end
105
61
  end
106
62
 
107
- it 'should execute a before and after action that gives access to the browser' do
108
- elements_page.link(:create, text: 'a link') do
109
- before(&:call_in_before_hook)
110
-
111
- after(&:call_in_after_before_hook)
63
+ describe '#respond_to?' do
64
+ subject do
65
+ described_class.new(elements_page.new(session), session, self)
66
+ end
67
+ it 'checks against the names of the elements passed in' do
68
+ expect(subject.respond_to?(:a_link)).to eq(true)
112
69
  end
113
-
114
- described_class.new(page, page.browser, self).create.click
115
- end
116
- end
117
-
118
- describe '#respond_to?' do
119
- subject do
120
- described_class.new(page1.new(session), session, self)
121
- end
122
- it 'checks against the names of the elements passed in' do
123
- expect(subject.respond_to?(:next)).to eq(true)
124
70
  end
125
71
  end
126
- end
72
+ end
@@ -118,7 +118,7 @@ describe PageMagic::Elements do
118
118
  describe 'location' do
119
119
  context 'a prefetched object' do
120
120
  it 'should add a section' do
121
- expected_section = PageMagic::Element.new(:element, parent_page_element, type: :section, browser_element: :object)
121
+ expected_section = PageMagic::Element.new(:page_section, parent_page_element, type: :element, browser_element: :object)
122
122
  page_elements.element :page_section, :object
123
123
  expected_section.should == page_elements.elements(parent_page_element).first
124
124
  end
data/spec/spec_helper.rb CHANGED
@@ -12,6 +12,7 @@ require 'helpers/capybara'
12
12
 
13
13
  shared_context :files do
14
14
  require 'tmpdir'
15
+
15
16
  def scratch_dir
16
17
  @dir ||= Dir.mktmpdir
17
18
  end
@@ -40,19 +41,20 @@ RSpec.configure do
40
41
  end
41
42
  end
42
43
  alias_method :initialize_backup, :initialize
44
+
43
45
  def initialize(*args, &block)
44
46
  initialize_backup *args, &block
45
- @before_hook = self.class.default_before_hook
46
- @after_hook = self.class.default_after_hook
47
+ # @before_hook = self.class.default_before_hook
48
+ # @after_hook = self.class.default_after_hook
47
49
  end
48
50
 
49
51
  def ==(page_element)
50
52
  page_element.is_a?(Element) &&
51
- @type == page_element.type &&
52
- @name == page_element.name &&
53
- @selector == page_element.selector
54
- @before_hook == page_element.before &&
55
- @after_hook == page_element.after
53
+ @type == page_element.type &&
54
+ @name == page_element.name &&
55
+ @selector == page_element.selector
56
+ # @before_hook == page_element.before &&
57
+ # @after_hook == page_element.after
56
58
  end
57
59
  end
58
60
  end
@@ -72,11 +74,16 @@ RSpec.configure do
72
74
  get '/elements' do
73
75
  <<-ELEMENTS
74
76
  <a href='#'>a link</a>
75
- <input type='submit' value='a button'/>
77
+
76
78
 
77
79
  <div id='form' class="form">
78
- <a id='form_link' href='/page2'>a in a form</a>
80
+ <a id='form_link' href='/page2'>link in a form</a>
81
+ <label>enter text
82
+ <input id='field_id' name='field_name' class='input_class' type='text' value='filled in'/>
83
+ </label>
84
+ <input id='form_button' type='submit' value='a button'/>
79
85
  </form>
86
+
80
87
  ELEMENTS
81
88
  end
82
89
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: page_magic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha10
4
+ version: 1.0.0.alpha11
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-09-29 00:00:00.000000000 Z
11
+ date: 2015-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara