insite 0.0.6 → 0.0.7

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.
@@ -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