insite 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ class OverwrittenSelector < MatChip
2
+ select_by! class: "overwritten"
3
+ end
@@ -0,0 +1,2 @@
1
+ class Pluralizes < MaterialAngularIO::Component
2
+ end
@@ -5,10 +5,19 @@ end
5
5
 
6
6
  # Require hand-crafted artisanal components.
7
7
  %w(example_viewer mat_chip_list mat_chip mat_icon mat_form_field
8
- mat_input mat_option mat_select_content mat_select no_selector).each do |c|
8
+ mat_input mat_option mat_select_content mat_select no_selector
9
+ overwritten_selector pluralized_name_test).each do |c|
9
10
  require "insite/examples/material_angular_io/components/#{c}"
10
11
  end
11
12
 
13
+ class OneVarTemplatePage < MaterialAngularIO::Page
14
+ set_url "/components/chips/overview/{var1}"
15
+ end
16
+
17
+ class TwoVarTemplatePage < MaterialAngularIO::Page
18
+ set_url "/components/chips/overview/{var1}/{var2}"
19
+ end
20
+
12
21
  # Most of the pages for material.angular.io are auto-generated because
13
22
  # their URLs match a pattern. But some custom page definitions are included
14
23
  # below. This first overwrites the auto-generated page definition for
@@ -17,9 +26,10 @@ end
17
26
  class ChipsOverviewPage < MaterialAngularIO::Page
18
27
  set_url "/components/chips/overview"
19
28
 
20
- no_selector :test_no_selector
21
29
  no_selector :test_no_selector_with_args, tag_name: :div, index: 3
22
30
 
31
+ overwritten_selector :overwritten_selector
32
+
23
33
  elements :mat_examples_collection, tag_name: 'example-viewer'
24
34
  elements :modified_mat_examples_collection, tag_name: 'example-viewer' do
25
35
  def test_method
data/lib/insite/insite.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'timeout'
2
+ require_relative 'methods/common_methods'
2
3
 
3
4
  # Usage:
4
5
  # require 'insite'
@@ -7,17 +8,20 @@ require 'timeout'
7
8
  # include Insite
8
9
  # end
9
10
  module Insite
10
- attr_reader :base_url, :unique_methods, :browser_type
11
+ attr_reader :base_url, :unique_methods, :browser_type, :site
11
12
  attr_accessor :pages, :browser, :arguments, :most_recent_page
12
13
 
14
+ include CommonMethods
15
+
13
16
  def self.class_to_tag(klass)
14
17
  if klass.respond_to?(:collection) && klass.collection?
15
- Watir.tag_to_class.key(klass) ||
16
- Watir.tag_to_class.key(CLASS_MAP.key(klass)) ||
17
- Watir.tag_to_class.key(CLASS_MAP.key(klass.collection_member_class))
18
+ (
19
+ Watir.tag_to_class.key(klass) ||
20
+ Watir.tag_to_class.key(CLASS_MAP.key(klass)) ||
21
+ Watir.tag_to_class.key(CLASS_MAP.key(klass.collection_member_class))
22
+ )
18
23
  else
19
- Watir.tag_to_class.key(klass) ||
20
- Watir.tag_to_class.key(CLASS_MAP.key(klass))
24
+ Watir.tag_to_class.key(klass) || Watir.tag_to_class.key(CLASS_MAP.key(klass))
21
25
  end
22
26
  end
23
27
 
@@ -64,31 +68,6 @@ module Insite
64
68
  @browser.close if browser?
65
69
  end
66
70
 
67
- def describe
68
- puts <<-EOF
69
- Wrapper class for all pages defined for the site.
70
- Site:\t#{self.class} (#{__FILE__})
71
- Base URL:\t#{@base_url}
72
- Browser:\t#{@browser}
73
- Current Page:\t#{page.class}
74
-
75
- Page Accessor Methods (Use '?' with name to check for presence.)
76
- -----------------------------------------------------------------
77
- #{
78
- tmp = []
79
- max = pages.map(&:to_s).max { |x| x.length }
80
- if max.length > 40
81
- pages.map(&:to_s).sort.map(&:underscore).join("\n")
82
- else
83
- pages.map(&:to_s).sort.map(&:underscore).each_slice(2) do |arr|
84
- tmp << arr[0].to_s.ljust(40) + arr[1].to_s.ljust(40)
85
- end
86
- tmp.join("\n")
87
- end
88
- }
89
- EOF
90
- end
91
-
92
71
  # Returns a Selenium driver object.
93
72
  def driver
94
73
  @browser.driver
@@ -99,23 +78,24 @@ EOF
99
78
  browser?
100
79
  end
101
80
 
102
- def generate_tag_classes
103
- tags = []
104
- cli = Highline.new
105
-
106
- loop do
107
- tags = (tags + find_non_standard_tags).uniq.sort
108
- cli.choose do |menu|
109
- menu.prompt "Found #{tags.length} non-standard tags. Choose one of the following options:"
110
- menu.choice(:list_tags) { puts tags.join(",\n") + "\n" }
111
- menu.choice(:continue) {}
112
- menu.choice(:write_to_console) do
113
- end
114
- menu.choice(:exist_without_writing) { break }
81
+ # def generate_tag_classes
82
+ # tags = []
83
+ # cli = Highline.new
84
+ #
85
+ # loop do
86
+ # tags = (tags + find_non_standard_tags).uniq.sort
87
+ # cli.choose do |menu|
88
+ # menu.prompt "Found #{tags.length} non-standard tags. Choose one of the following options:"
89
+ # menu.choice(:list_tags) { puts tags.join(",\n") + "\n" }
90
+ # menu.choice(:continue) {}
91
+ # menu.choice(:write_to_console) do
92
+ # end
93
+ # menu.choice(:exist_without_writing) { break }
94
+ #
95
+ # end
96
+ # end
97
+ # end
115
98
 
116
- end
117
- end
118
- end
119
99
  # Creates a site object, which will have accessor methods for all pages that
120
100
  # you have defined for the site. This object takes a hash argument. There is
121
101
  # only one required value (the base_url for the site.) Example:
@@ -137,13 +117,18 @@ EOF
137
117
  # => 1
138
118
  # TODO: Sort args.
139
119
  def initialize(base_url = nil, hsh={})
140
- @arguments = hsh.with_indifferent_access
141
- @base_url = base_url
142
- @browser_type = (@arguments[:browser] ? @arguments[:browser].to_sym : nil)
143
- @pages = self.class::DefinedPage.descendants.reject { |p| p.page_template? }
120
+ @site = self
121
+ @arguments = hsh.with_indifferent_access
122
+ @base_url = base_url
123
+ @browser_type = (@arguments[:browser] ? @arguments[:browser].to_sym : nil)
124
+
125
+ # Cull templates from array of pages that gets returned (since templates
126
+ # should never be used directly.)
127
+ @pages = self.class::DefinedPage.descendants.reject do |pg|
128
+ pg.page_template?
129
+ end
144
130
 
145
- # Build generic components for custom tags, which are defined
146
- # using Site.custom_tags.
131
+ # Builds generic components for custom tags.
147
132
  if self.class.custom_tags
148
133
  self.class.custom_tags.each do |tag|
149
134
  # TODO: Ditch string interpolation.
@@ -182,6 +167,14 @@ EOF
182
167
  end
183
168
  end
184
169
 
170
+ # Sort templates by variable count: Templates with more vars will be
171
+ # prioritized. This will partially eliminate the potential for a match on
172
+ # the wrong template when there are two or more templates that match the
173
+ # URL.
174
+ @pages = @pages.sort do |pg1, pg2|
175
+ pg1.url_template.variables.length <=> pg2.url_template.variables.length
176
+ end
177
+
185
178
  visited = Set.new
186
179
  tmp = @pages.map {|p| p.instance_methods }.flatten
187
180
  tmp.each do |element|
@@ -205,6 +198,10 @@ EOF
205
198
  end.uniq.sort
206
199
  end
207
200
 
201
+ def html
202
+ @browser.html
203
+ end
204
+
208
205
  def html_tags
209
206
  %i(html title head body) + Insite::METHOD_MAP.values.flatten.each do |mth|
210
207
  elem = @browser.send(mth)
@@ -227,10 +224,12 @@ EOF
227
224
  # what was attempted.
228
225
  def method_missing(mth, *args, &block)
229
226
  original_page = @most_recent_page
227
+
230
228
  if original_page.respond_to?(mth)
231
229
  original_page.public_send(mth, *args, &block)
232
230
  else
233
231
  new_page = page
232
+
234
233
  if new_page.respond_to?(mth)
235
234
  page.public_send(mth, *args, &block)
236
235
  elsif !new_page.defined?
@@ -322,15 +321,54 @@ EOF
322
321
  # URL in the browser.
323
322
  #
324
323
  # If a matching page can't be found then Insite will return an "undefined page"
325
- # object. See the Un class for more details.
324
+ # object. See the UndefinedPage class for more details.
326
325
  def page
326
+ # 1.)
327
+ # Before anything else, look to see if it's the most recent page:
327
328
  return @most_recent_page if @most_recent_page && @most_recent_page.on_page?
329
+ process_browser
328
330
  url = @browser.url
331
+
329
332
  found_page = nil
333
+ # 2.)
334
+ # Ensure that static templates are always prioritized when attempting to
335
+ # match, which will prevent the wrong template from getting matched in this
336
+ # scenario:
337
+ # - "/accounts/{account_code}"
338
+ # - "/accounts/new"
339
+ #
340
+ # Start by working through the array from FRONT to BACK, since any static
341
+ # templates will be at the front of the array. Stop when we start to see
342
+ # templates whth vars (These will get handled in the next statement.)
330
343
  @pages.each do |pg|
344
+ break if pg.url_template.variables.length > 0
345
+
346
+ if pg.url_matcher && pg.url_matcher =~ url
347
+ found_page = pg
348
+ elsif pg.url_template.match(url)
349
+ found_page = pg
350
+ else
351
+ next
352
+ end
353
+
354
+ break if found_page
355
+ end
356
+
357
+ # 3.) Now we've reached the templates that include one or more variables.
358
+ # For these, we want to try to match on the templates with more variables.
359
+ # This prevents an invalid match in the following situation and removes the
360
+ # need to provide a URL matcher to override the URL template:
361
+ # - "/accounts/{account_code}/edit"
362
+ # - "/accounts/{account_code}"
363
+ # Now work through all the array from BACK to FRONT, stopping when we reach
364
+ # the point where we see templates without a var (since those were already
365
+ # handled above.)
366
+ @pages.reverse.each do |pg|
367
+ break if pg.url_template.variables.length == 0
368
+
331
369
  if pg.url_matcher && pg.url_matcher =~ url
332
370
  found_page = pg
333
- elsif !pg.url_matcher && pg.url_template.match(url)
371
+ elsif pg.url_template.match(url)
334
372
  found_page = pg
335
373
  else
336
374
  next
@@ -12,10 +12,6 @@ module Insite
12
12
  end
13
13
  alias nokogiri document
14
14
 
15
- # Returns a string representation of the page.
16
- def inspect
17
- "#<#{self.class.name}:#{object_id} @url=#{@browser.url}>"
18
- end
19
15
 
20
16
  private
21
17
  def process_browser
@@ -29,8 +25,6 @@ module Insite
29
25
  "Browser check failed. The browser is no longer present.\n\n"
30
26
  )
31
27
  end
32
- rescue(Insite::Errors::BrowserNotOpenError) => e
33
- raise e
34
28
  rescue => e
35
29
  raise(
36
30
  Insite::Errors::BrowserResponseError,
@@ -57,6 +51,46 @@ module Insite
57
51
 
58
52
  end
59
53
  public
54
+ # private
55
+ # def process_browser
56
+ # if @site.browser.is_a?(Watir::Browser)
57
+ # begin
58
+ # if @site.browser.exists?
59
+ # return @site.browser
60
+ # else
61
+ # raise(
62
+ # Insite::Errors::BrowserClosedError,
63
+ # "Browser check failed. The browser is no longer present.\n\n"
64
+ # )
65
+ # end
66
+ # rescue(Insite::Errors::BrowserNotOpenError) => e
67
+ # raise e
68
+ # rescue => e
69
+ # raise(
70
+ # Insite::Errors::BrowserResponseError,
71
+ # <<~eos
72
+ # Browser check failed. The browser returned an #{e.class} (#{e}) when it was queried.
73
+ # Backtrace for the error:
74
+ # #{e.backtrace.join("\n")}
75
+ #
76
+ # eos
77
+ # )
78
+ # end
79
+ # elsif @site.browser.nil?
80
+ # raise(
81
+ # Insite::Errors::BrowserNotOpenError,
82
+ # "A browser has not been defined for the site. Try using Site#open to " \
83
+ # "start a browser.\n\n"
84
+ # )
85
+ # else
86
+ # raise(
87
+ # Insite::Errors::BrowserNotValidError,
88
+ # "Expected: Watir::Browser. Actual: #{@site.browser.class}.\n\n"
89
+ # )
90
+ # end
91
+ #
92
+ # end
93
+ # public
60
94
 
61
95
  def update_object(hash_args = {})
62
96
  rescues = [
@@ -12,27 +12,9 @@ module Insite
12
12
  alias_method :update_page, :update_object
13
13
 
14
14
  class << self
15
- attr_reader :has_fragment, :page_attributes, :page_elements, :page_features, :page_url, :url_matcher, :url_template
15
+ attr_reader :has_fragment, :page_attributes, :page_elements, :page_features, :page_url, :url_matcher, :url_hash, :url_template
16
16
  attr_accessor :component_elements
17
17
 
18
- def describe
19
- puts <<-EOF
20
- Page Class:\t#{name} (#{__FILE__})
21
- URL Template:\t#{@url_template.pattern}"
22
- URL Matcher:\t#{@url_matcher || 'Not specified.'}
23
-
24
- Contains user-defined logic for a single page.
25
-
26
- Page Elements:\n#{@page_elements.sort.map { |x| " #{x} #{x.class.to_s.methodize}\n" }.join }
27
-
28
- Components:\n#{@component_elements.sort.map { |x| " #{x} #{x.class.to_s.methodize}\n" }.join }
29
-
30
- Features:\n#{@component_elements.sort.map { |x| " #{x} #{x.class.to_s.methodize}\n" }.join }
31
-
32
- EOF
33
-
34
- end
35
-
36
18
  # Allows you to set special page attributes that affect page behavior. The two page
37
19
  # attributes currently supported are :navigation_disabled and :page_template:
38
20
  #
@@ -220,39 +202,20 @@ module Insite
220
202
  regexp ? @url_matcher = regexp : nil
221
203
  end
222
204
 
223
- # Used to import page features for use within the page. Example:
224
- #
225
- # class ConfigPage < MySite::Page
226
- # use_features :footer, :sidebar
227
- # end
228
- #
229
- # Then, once the page object has been initialized:
205
+ # def component_method(method_name, component_symbol, component_method, target_element)
206
+ # @component_methods ||= []
207
+ # @component_methods << method_name.to_sym unless @component_methods.include?(method_name.to_sym)
230
208
  #
231
- # site.config_page.footer.about.click
232
- #
233
- # Use the PageFeature class to define page features.
234
- def use_features(*args)
235
- if @page_features
236
- @page_feature += args
237
- else
238
- @page_features = args
239
- end
240
- end
241
-
242
- def component_method(method_name, component_symbol, component_method, target_element)
243
- @component_methods ||= []
244
- @component_methods << method_name.to_sym unless @component_methods.include?(method_name.to_sym)
245
-
246
- define_method(method_name) do |*args, &block|
247
- self.class.const_get(component_symbol.to_s.camelize)
248
- .new(@site, @site.send(target_element))
249
- .send(component_method, *args, &block)
250
- end
251
- end
209
+ # define_method(method_name) do |*args, &block|
210
+ # self.class.const_get(component_symbol.to_s.camelize)
211
+ # .new(@site, @site.send(target_element))
212
+ # .send(component_method, *args, &block)
213
+ # end
214
+ # end
252
215
  end # Self.
253
216
 
254
- def describe
255
- self.class.describe
217
+ def browser?
218
+ @site.browser?
256
219
  end
257
220
 
258
221
  def defined?
@@ -263,6 +226,10 @@ module Insite
263
226
  @browser.driver
264
227
  end
265
228
 
229
+ def driver?
230
+ browser?
231
+ end
232
+
266
233
  def html
267
234
  @browser.html
268
235
  end
@@ -499,7 +466,6 @@ module Insite
499
466
  end
500
467
 
501
468
  @site.most_recent_page = self
502
- self
503
469
  end
504
470
  end
505
471
  end
@@ -12,27 +12,6 @@ module Insite
12
12
  false
13
13
  end
14
14
 
15
- def describe
16
- puts <<-EOF
17
- Page Class:\t#{name} (#{__FILE__})
18
- URL Template:\tNA
19
- URL Matcher:\tNA
20
-
21
- Page class for any page that hasn't been defined (or that Insite doesn't recognize.)
22
-
23
- Note: If there is a page class that is defined for this page that isn't getting
24
- loaded, try the following:
25
- - Review the pages URL template for problems. A URL template is *not* an interpolated
26
- string -- it just looks like one. See the documentation for more details.
27
- - If the URL template seems to be designed correctly for loading the page, but the
28
- page's URL changes after the load, you will need to look at adding a URL matcher,
29
- which overrides the URL template for purposes of checking whether the page object
30
- is matching the currently displayed page after it has been loaded.
31
-
32
- Page Elements:\tNA
33
- EOF
34
- end
35
-
36
15
  def driver
37
16
  @browser.driver
38
17
  end
@@ -50,13 +29,13 @@ module Insite
50
29
  # TODO: Do the same cache check that's done for a defined page and reapply the
51
30
  # method if the cache is updated and the new page DOES respond to the method.
52
31
  def method_missing(mth, *args, &block)
53
- raise NoMethodError, "Could not apply #{mth}. The current page could not be " \
54
- "recognized. Current URL #{@browser.url}"
32
+ raise NoMethodError, "Could not apply #{mth}. The current page couldn't " \
33
+ "be recognized. Current URL #{@browser.url}"
55
34
  end
56
35
 
57
36
  # Returns a Nokogiri object for the page HTML.
58
37
  def nokogiri
59
- @site.nokogiri
38
+ Nokogiri::HTML(html)
60
39
  end
61
40
 
62
41
  # Similar to the method that you can call on a page object you've defined (but always