Class: Insite::DefinedPage
- Inherits:
-
Object
- Object
- Insite::DefinedPage
- Extended by:
- ComponentMethods, DOMMethods
- Includes:
- CommonMethods, ComponentInstanceMethods
- Defined in:
- lib/insite/page/defined_page.rb
Class Attribute Summary collapse
-
.component_elements ⇒ Object
Returns the value of attribute component_elements.
-
.has_fragment ⇒ Object
readonly
Returns the value of attribute has_fragment.
-
.page_attributes ⇒ Object
readonly
Returns the value of attribute page_attributes.
-
.page_elements ⇒ Object
readonly
Returns the value of attribute page_elements.
-
.page_features ⇒ Object
readonly
Returns the value of attribute page_features.
-
.page_url ⇒ Object
readonly
Returns the value of attribute page_url.
-
.url_matcher ⇒ Object
readonly
Returns the value of attribute url_matcher.
-
.url_template ⇒ Object
readonly
Returns the value of attribute url_template.
Instance Attribute Summary collapse
-
#arguments ⇒ Object
readonly
Returns the value of attribute arguments.
-
#browser ⇒ Object
readonly
Returns the value of attribute browser.
-
#component_elements ⇒ Object
readonly
Returns the value of attribute component_elements.
-
#has_fragment ⇒ Object
readonly
Returns the value of attribute has_fragment.
-
#page_attributes ⇒ Object
readonly
Returns the value of attribute page_attributes.
-
#page_elements ⇒ Object
readonly
Returns the value of attribute page_elements.
-
#page_features ⇒ Object
readonly
Returns the value of attribute page_features.
-
#page_url ⇒ Object
readonly
Returns the value of attribute page_url.
-
#query_arguments ⇒ Object
readonly
Returns the value of attribute query_arguments.
-
#required_arguments ⇒ Object
readonly
Returns the value of attribute required_arguments.
-
#site ⇒ Object
readonly
Returns the value of attribute site.
-
#url_matcher ⇒ Object
readonly
Returns the value of attribute url_matcher.
-
#url_template ⇒ Object
readonly
Returns the value of attribute url_template.
Class Method Summary collapse
- .component_method(method_name, component_symbol, component_method, target_element) ⇒ Object
- .describe ⇒ Object
- .page_template? ⇒ Boolean
- .query_arguments ⇒ Object
-
.required_arguments ⇒ Object
Returns an array of symbols representing the required arguments for the page’s page URL.
-
.set_attributes(*args) ⇒ Object
Allows you to set special page attributes that affect page behavior.
-
.set_url(url) ⇒ Object
Used to define the full or relative URL to the page.
-
.set_url_matcher(regexp) ⇒ Object
Optional.
- .set_url_template(base_url) ⇒ Object
-
.use_features(*args) ⇒ Object
Used to import page features for use within the page.
Instance Method Summary collapse
- #defined? ⇒ Boolean
-
#describe ⇒ Object
Self.
- #driver ⇒ Object
- #html ⇒ Object
-
#initialize(site, args = nil) ⇒ DefinedPage
constructor
Initializes a new page object.
-
#inspect ⇒ Object
Custom inspect method so that console output doesn’t get in the way when debugging.
- #navigation_disabled? ⇒ Boolean
- #on_page? ⇒ Boolean
-
#refresh ⇒ Object
Refreshes the page.
-
#title ⇒ Object
Returns the page title displayed by the browser.
-
#visit ⇒ Object
Reloads the page (No need to call this method for initial navigation, which happens automatically when the page is first initialized.).
Methods included from CommonMethods
Constructor Details
#initialize(site, args = nil) ⇒ DefinedPage
Initializes a new page object. There’s no need to ever call this method directly. Your site class (the one that includes the Insite module) will handle this for you
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
# File 'lib/insite/page/defined_page.rb', line 273 def initialize(site, args = nil) @site = site @browser = process_browser @component_elements = self.class.component_elements ||= [] @browser = @site.browser @page_attributes = self.class.page_attributes @page_url = self.class.page_url @page_elements = self.class.page_elements # TODO: Clean this up @page_features = self.class.instance_variable_get(:@page_features) @required_arguments = self.class.required_arguments @url_matcher = self.class.url_matcher @url_template = self.class.url_template @query_arguments = self.class.query_arguments @has_fragment = self.class.has_fragment # Try to expand the URL template if the URL has parameters. @arguments = {}.with_indifferent_access # Stores the param list that will expand the url_template after examining the arguments used to initialize the page. match = @url_template.match(@browser.url) if @required_arguments.present? && !args @required_arguments.each do |arg| if match && match.keys.include?(arg.to_s) @arguments[arg] = match[arg.to_s] elsif @site.arguments[arg] @arguments[arg] = @site.arguments[arg] elsif @site.respond_to?(arg) && @site.public_send(arg) @arguments[arg] = @site.public_send(arg) else raise( Insite::Errors::PageInitError, "No arguments provided when attempting to initialize #{self.class.name}. " \ "This page object requires the following arguments for initialization: "\ ":#{@required_arguments.join(', :')}.\n\n#{caller.join("\n")}" ) end end elsif @required_arguments.present? @required_arguments.each do |arg| # Try to extract each URL argument from the hash or object provided, OR from the site object. if args.is_a?(Hash) && args.present? args = args.with_indifferent_access if args[arg] #The hash has the required argument. @arguments[arg]= args[arg] elsif match && match.keys.include?(arg.to_s) @arguments[arg] = match[arg.to_s] elsif @site.respond_to?(arg) @arguments[arg] = site.public_send(arg) else raise( Insite::Errors::PageInitError, "A required page argument is missing. #{args.class} was provided, " \ "but this object did not respond to :#{arg}, which is necessary to " \ "build a URL for the #{self.class.name} page.\n\n#{caller.join("\n")}" ) end elsif args # Some non-hash object was provided. if args.respond_to?(arg) #The hash has the required argument. @arguments[arg]= args.public_send(arg) elsif @site.respond_to?(arg) @arguments[arg]= site.public_send(arg) else raise( Insite::Errors::PageInitError, "A required page argument is missing. #{args.class} was provided, but " \ "this object did not respond to :#{arg}, which is necessary to build " \ "a URL for the #{self.class.name} page.\n\n#{caller.join("\n")}" ) end else # Do nothing here yet. end end elsif @required_arguments.empty? && args # If there are no required arguments then nothing should be provided. raise( Insite::Errors::PageInitError, "#{args.class} was provided as a #{self.class.name} initialization argument, " \ "but the page URL doesn't require any arguments.\n\n#{caller.join("\n")}" ) else # Do nothing here yet. end @url = @url_template.(@arguments).to_s @page_features ||= [] @page_features.each do |fname| begin klass = fname.to_s.camelize.constantize rescue NameError => e klass = self.class.const_get fname.to_s.camelize end self.class_eval do #klass = fname.to_s.camelize.constantize if klass.alias define_method(klass.alias) do klass.new(self) end else define_method(fname) do klass.new(self) end end end end @site.most_recent_page = self unless on_page? if raise( Insite::Errors::PageNavigationNotAllowedError, "Navigation is intentionally disabled for the #{self.class.name} page. " \ "You can only call the accessor method for this page when it's already " \ "being displayed in the browser.\n\nCurrent URL:" \ "\n------------\n#{@site.browser.url}\n\n#{caller.join("\n")}" ) end visit end end |
Class Attribute Details
.component_elements ⇒ Object
Returns the value of attribute component_elements.
16 17 18 |
# File 'lib/insite/page/defined_page.rb', line 16 def component_elements @component_elements end |
.has_fragment ⇒ Object (readonly)
Returns the value of attribute has_fragment.
15 16 17 |
# File 'lib/insite/page/defined_page.rb', line 15 def has_fragment @has_fragment end |
.page_attributes ⇒ Object (readonly)
Returns the value of attribute page_attributes.
15 16 17 |
# File 'lib/insite/page/defined_page.rb', line 15 def page_attributes @page_attributes end |
.page_elements ⇒ Object (readonly)
Returns the value of attribute page_elements.
15 16 17 |
# File 'lib/insite/page/defined_page.rb', line 15 def page_elements @page_elements end |
.page_features ⇒ Object (readonly)
Returns the value of attribute page_features.
15 16 17 |
# File 'lib/insite/page/defined_page.rb', line 15 def page_features @page_features end |
.page_url ⇒ Object (readonly)
Returns the value of attribute page_url.
15 16 17 |
# File 'lib/insite/page/defined_page.rb', line 15 def page_url @page_url end |
.url_matcher ⇒ Object (readonly)
Returns the value of attribute url_matcher.
15 16 17 |
# File 'lib/insite/page/defined_page.rb', line 15 def url_matcher @url_matcher end |
.url_template ⇒ Object (readonly)
Returns the value of attribute url_template.
15 16 17 |
# File 'lib/insite/page/defined_page.rb', line 15 def url_template @url_template end |
Instance Attribute Details
#arguments ⇒ Object (readonly)
Returns the value of attribute arguments.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def arguments @arguments end |
#browser ⇒ Object (readonly)
Returns the value of attribute browser.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def browser @browser end |
#component_elements ⇒ Object (readonly)
Returns the value of attribute component_elements.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def component_elements @component_elements end |
#has_fragment ⇒ Object (readonly)
Returns the value of attribute has_fragment.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def has_fragment @has_fragment end |
#page_attributes ⇒ Object (readonly)
Returns the value of attribute page_attributes.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def page_attributes @page_attributes end |
#page_elements ⇒ Object (readonly)
Returns the value of attribute page_elements.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def page_elements @page_elements end |
#page_features ⇒ Object (readonly)
Returns the value of attribute page_features.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def page_features @page_features end |
#page_url ⇒ Object (readonly)
Returns the value of attribute page_url.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def page_url @page_url end |
#query_arguments ⇒ Object (readonly)
Returns the value of attribute query_arguments.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def query_arguments @query_arguments end |
#required_arguments ⇒ Object (readonly)
Returns the value of attribute required_arguments.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def required_arguments @required_arguments end |
#site ⇒ Object (readonly)
Returns the value of attribute site.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def site @site end |
#url_matcher ⇒ Object (readonly)
Returns the value of attribute url_matcher.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def url_matcher @url_matcher end |
#url_template ⇒ Object (readonly)
Returns the value of attribute url_template.
5 6 7 |
# File 'lib/insite/page/defined_page.rb', line 5 def url_template @url_template end |
Class Method Details
.component_method(method_name, component_symbol, component_method, target_element) ⇒ Object
242 243 244 245 246 247 248 249 250 251 |
# File 'lib/insite/page/defined_page.rb', line 242 def component_method(method_name, component_symbol, component_method, target_element) @component_methods ||= [] @component_methods << method_name.to_sym unless @component_methods.include?(method_name.to_sym) define_method(method_name) do |*args, &block| self.class.const_get(component_symbol.to_s.camelize) .new(@site, @site.send(target_element)) .send(component_method, *args, &block) end end |
.describe ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/insite/page/defined_page.rb', line 18 def describe puts <<-EOF Page Class:\t#{name} (#{__FILE__}) URL Template:\t#{@url_template.pattern}" URL Matcher:\t#{@url_matcher || 'Not specified.'} Contains user-defined logic for a single page. Page Elements:\n#{@page_elements.sort.map { |x| " #{x} #{x.class.to_s.methodize}\n" }.join } Components:\n#{@component_elements.sort.map { |x| " #{x} #{x.class.to_s.methodize}\n" }.join } Features:\n#{@component_elements.sort.map { |x| " #{x} #{x.class.to_s.methodize}\n" }.join } EOF end |
.page_template? ⇒ Boolean
84 85 86 87 |
# File 'lib/insite/page/defined_page.rb', line 84 def page_template? @page_attributes ||= [] @page_attributes.include? :page_template end |
.query_arguments ⇒ Object
94 95 96 |
# File 'lib/insite/page/defined_page.rb', line 94 def query_arguments required_arguments.find { |x| @url_template.pattern =~ /\?.*#{x}=*/ } end |
.required_arguments ⇒ Object
Returns an array of symbols representing the required arguments for the page’s page URL.
90 91 92 |
# File 'lib/insite/page/defined_page.rb', line 90 def required_arguments @arguments ||= @url_template.keys.map { |k| k.to_sym } end |
.set_attributes(*args) ⇒ Object
Allows you to set special page attributes that affect page behavior. The two page attributes currently supported are :navigation_disabled and :page_template:
-
When :navigation_disabled is specified as a page attribute, all automatic and manual browser navigation is disabled. If you call the page’s page methods automatic navigation is turned off – it won’t automatically load the page for you. And it the method will raise a Insite::Errors::PageNavigationNotAllowedError if you call the page’s accessor method while you aren’t actually on the page. And finally, the page’s visit method is disabled. This attribute is useful only when you have a page that can’t be automatically navigated to, in which case all of the navigation features described above wouldn’t work anyway.
-
When :page_template is specified as a page attribute, the site object won’t create an accessor method for the page when initializing and also won’t include the page when calling the site object’s pages method. This allows you to define a page object for inheritance purposes only. The idea behind this is to put common features one or more of these templates, which won’t get used directly. Then your other page objects that you actually do want to use can inherit from one of the templates, gaining all of its features. For example, you can put things like a logout link or common menus into a template and then have all of the page objects that need those features inherit from the template and get those features automatically.
If an unsupported attribute is specified a Insite::Errors::PageConfigError will be raised.
Usage:
set_attributes :attr1, :attr2
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/insite/page/defined_page.rb', line 63 def set_attributes(*args) @page_attributes ||= [] args.each do |arg| case arg when :navigation_disabled @navigation_disabled = true when :page_template @page_template = true else raise( Insite::Errors::PageConfigError, "Unsupported page attribute argument: #{arg} for #{self} page definition. " \ "Argument class: #{arg.class}. Arguments must be one or more of the following " \ "symbols: :navigation_disabled, :template." ) end end @page_attributes = args end |
.set_url(url) ⇒ Object
Used to define the full or relative URL to the page. Typically, you will almost always want to use this method when defining a page object (but see notes below.) The URL can be defined in a number of different ways. Here are some examples using Google News:
Relative URL
set_url "/nwshp?hl=en"
Relative URLs are most commonly used when defining page objects. The idea here is that you can change the base_url when calling the site object, which allows you to use the same code across multiple test environments by changing the base_url as you initialize a site object.
Relative URL with URL Templating
set_url "/nwshp?hl={language}"
This takes the relative URL example one step further, allowing you to set the page’s parameters. Note that the the language specified in the first relative URL example (‘en’) was replaced by ‘language’ in this one. Insite uses the Addressable library, which supports this kind of templating. When you template a value in the URL, the page object will allow you to specify the templated value when it’s being initialized. Here’s an example of how this works using a news site. Here’s the base site class:
class NewsSite
include Insite
end
Here’s a page object for the news page, templating the language value in the URL:
class NewsPage < NewsSite::Page
set_url "/news?l={language}"
end
After you’ve initialized the site object you can load the Spanish or French versions of the page by changing the hash argument used to call the page from the site object:
site = NewsSite.new(base_url: "http://news.somesite.com")
site.news_page(language: 'es')
site.news_page(language: 'fr')
In addition to providing a hash of templated values when initializing a page you can also use an object, as long as that object responds to all of the templated arguments in the page’s URL definition. Here’s a simple class that has a language method that we can use for the news page described above:
class Country
attr_reader :language
def initialize(lang)
@language = lang
end
end
In the example below, the Country class is used to create a new new country object called ‘c’. This object has been initialized with a Spanish language code and the news page will load the spanish version of the page when it’s called with the country object.
site = NewsSite.new(base_url: "http://news.somesite.com")
c = Country.new('es')
=> <Country:0x007fcb0dc67f98 @language="es">
c.language
=> 'es'
site.news_page(c)
=> <NewsPage:0x003434546566>
If one or more URL parameters are missing when the page is getting initialized then the page will look at the hash arguments used to initialize the site. If the argument the page needs is defined in the site’s initialization arguments it will use that. For example, if the site is initialized with a port, subdomain, or any other argument you can use those values when defining a page URL. Example:
class ConfigPage < MySite::Page
set_url "/foo/{subdomain}/config"
end
site = MySite.new(subdomain: 'foo')
=> <MySite:0x005434546511>
site.configuration_page # No need to provide a subdomain here as long as the site has it.
=> <ConfigPage:0x705434546541>
Full URL
set_url "http://news.google.com/nwshp?hl=en"
Every once in a while you may not want to use a base URL that has been defined. This allows you to do that. Just define a complete URL for that page object and that’s what will get used; the base_url will be ignored.
No URL
The set_url method is not mandatory. when defining a page. If you don’t use set_url in the page definition then the page will defined the base_url as the page’s URL.
188 189 190 |
# File 'lib/insite/page/defined_page.rb', line 188 def set_url(url) url ? @page_url = url.gsub(/(?<!:)\/\/+/, '/') : nil end |
.set_url_matcher(regexp) ⇒ Object
Optional. Allows you to specify a fallback mechanism for checking to see if the correct page is being displayed. This only gets used in cases where the primary mechanism for checking a page (the URL template defined by Page#set_url) fails to match the current browser URL. When that happens the regular expression defined here will be applied and the navigation check will pass if the regular expression matches the current browser URL.
In most cases, you won’t need to define a URL matcher and should just rely on the default page matching that uses the page’s URL template. The default matching should work fine for most cases.
219 220 221 |
# File 'lib/insite/page/defined_page.rb', line 219 def set_url_matcher(regexp) regexp ? @url_matcher = regexp : nil end |
.set_url_template(base_url) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/insite/page/defined_page.rb', line 192 def set_url_template(base_url) case @page_url when nil, '' @url_template = Addressable::Template.new(base_url) when /(http:\/\/|https:\/\/)/i @url_template = Addressable::Template.new( @page_url.gsub(/(?<!:)\/\/+/, '/') ) else @url_template = Addressable::Template.new( Addressable::URI.parse( "#{base_url}#{@page_url}".gsub(/(?<!:)\/\/+/, '/') ) ) end @has_fragment = @url_template.pattern =~ /#/ end |
.use_features(*args) ⇒ Object
Used to import page features for use within the page. Example:
class ConfigPage < MySite::Page
use_features :footer, :sidebar
end
Then, once the page object has been initialized:
site.config_page..about.click
Use the PageFeature class to define page features.
234 235 236 237 238 239 240 |
# File 'lib/insite/page/defined_page.rb', line 234 def use_features(*args) if @page_features @page_feature += args else @page_features = args end end |
Instance Method Details
#defined? ⇒ Boolean
258 259 260 |
# File 'lib/insite/page/defined_page.rb', line 258 def defined? true end |
#describe ⇒ Object
Self.
254 255 256 |
# File 'lib/insite/page/defined_page.rb', line 254 def describe self.class.describe end |
#driver ⇒ Object
262 263 264 |
# File 'lib/insite/page/defined_page.rb', line 262 def driver @browser.driver end |
#html ⇒ Object
266 267 268 |
# File 'lib/insite/page/defined_page.rb', line 266 def html @browser.html end |
#inspect ⇒ Object
Custom inspect method so that console output doesn’t get in the way when debugging.
397 398 399 |
# File 'lib/insite/page/defined_page.rb', line 397 def inspect "#<#{self.class.name}:#{object_id} @url_template=#{@url_template.inspect}>" end |
#navigation_disabled? ⇒ Boolean
401 402 403 |
# File 'lib/insite/page/defined_page.rb', line 401 def @page_attributes.include? :navigation_disabled end |
#on_page? ⇒ Boolean
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
# File 'lib/insite/page/defined_page.rb', line 405 def on_page? url = @browser.url if @url_matcher if @url_matcher =~ url return true else return false end elsif @url_template.match(url) if @arguments.empty? return true else if pargs = @url_template.extract(Addressable::URI.parse(url)) pargs = pargs.with_indifferent_access @required_arguments.all? do |k| pargs[k] == @arguments[k] || pargs[k] == @arguments[k].to_s || !@arguments[k] && pargs[k] # Don't complain if arg is not explicit. end end end elsif @url_template.match(url.split(/(\?|#|\/$)/)[0]) if @arguments.empty? return true else if pargs = @url_template.extract(Addressable::URI.parse(url)) pargs = pargs.with_indifferent_access @required_arguments.all? { |k| pargs[k] == @arguments[k].to_s } end end else false end end |
#refresh ⇒ Object
Refreshes the page.
442 443 444 445 |
# File 'lib/insite/page/defined_page.rb', line 442 def refresh @browser.refresh self end |
#title ⇒ Object
Returns the page title displayed by the browser.
448 449 450 |
# File 'lib/insite/page/defined_page.rb', line 448 def title @browser.title end |
#visit ⇒ Object
Reloads the page (No need to call this method for initial navigation, which happens automatically when the page is first initialized.)
Raises an Insite::Errors::PageNavigationNotAllowedError when navigation has been disabled for the page.
Raises an Insite::Errors::WrongPageError if the specified page isn’t getting displayed after navigation.
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
# File 'lib/insite/page/defined_page.rb', line 460 def visit if raise( Insite::Errors::PageNavigationNotAllowedError, "Navigation has been disabled for the #{self.class.name} page. This was " \ "done when defining the page's class and usually means that the page can't " \ "be reached directly through a URL and requires some additional work to access." ) end 2.times do begin @browser.goto(@url) break rescue Net::ReadTimeout => e sleep 3 end end if @url_matcher unless on_page? raise( Insite::Errors::WrongPageError, "Navigation check failed after attempting to access the #{self.class.name} page. " \ "This page has a URL matcher (a regular expression) defined for it. When a URL " \ "matcher is defined it is used in place of the URL template that is normally used " \ " to check for page display (URL template was still used for navigation.)" \ "\n\nURL after navigation:\n#{@browser.url}" \ "\n\nPage URL matcher that failed: #{@url_matcher}" ) end else unless on_page? raise( Insite::Errors::WrongPageError, "Navigation check failed after attempting to access the #{self.class.name} page. " \ "Current URL #{@browser.url} did not match #{@url_template.(@arguments)}" ) end end @site.most_recent_page = self self end |