bret-watircraft 0.4.0
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.
- data/BUGS.txt +11 -0
- data/History.txt +209 -0
- data/Manifest.txt +103 -0
- data/README.rdoc +75 -0
- data/VERSION.yml +4 -0
- data/app_generators/watircraft/USAGE +11 -0
- data/app_generators/watircraft/templates/config.yml.erb +3 -0
- data/app_generators/watircraft/templates/feature_helper.rb +12 -0
- data/app_generators/watircraft/templates/initialize.rb.erb +10 -0
- data/app_generators/watircraft/templates/rakefile.rb +3 -0
- data/app_generators/watircraft/templates/script/console +5 -0
- data/app_generators/watircraft/templates/script/console.cmd +1 -0
- data/app_generators/watircraft/templates/site_start.rb.erb +12 -0
- data/app_generators/watircraft/templates/spec_helper.rb +9 -0
- data/app_generators/watircraft/templates/spec_initialize.rb +16 -0
- data/app_generators/watircraft/templates/world.rb +12 -0
- data/app_generators/watircraft/watircraft_generator.rb +108 -0
- data/bin/watircraft +17 -0
- data/lib/extensions/array.rb +10 -0
- data/lib/extensions/hash.rb +5 -0
- data/lib/extensions/object.rb +24 -0
- data/lib/extensions/string.rb +17 -0
- data/lib/extensions/watir.rb +41 -0
- data/lib/taza/browser.rb +45 -0
- data/lib/taza/entity.rb +34 -0
- data/lib/taza/fixture.rb +66 -0
- data/lib/taza/flow.rb +40 -0
- data/lib/taza/page.rb +259 -0
- data/lib/taza/settings.rb +80 -0
- data/lib/taza/site.rb +227 -0
- data/lib/taza/tasks.rb +30 -0
- data/lib/taza.rb +35 -0
- data/lib/watircraft/generator_helper.rb +27 -0
- data/lib/watircraft/table.rb +56 -0
- data/lib/watircraft/version.rb +3 -0
- data/lib/watircraft.rb +1 -0
- data/spec/array_spec.rb +16 -0
- data/spec/browser_spec.rb +68 -0
- data/spec/entity_spec.rb +9 -0
- data/spec/fake_table.rb +34 -0
- data/spec/fixture_spec.rb +34 -0
- data/spec/fixtures_spec.rb +21 -0
- data/spec/hash_spec.rb +12 -0
- data/spec/object_spec.rb +29 -0
- data/spec/page_generator_spec.rb +111 -0
- data/spec/page_spec.rb +342 -0
- data/spec/project_generator_spec.rb +103 -0
- data/spec/sandbox/config/config.yml +1 -0
- data/spec/sandbox/config/environments.yml +4 -0
- data/spec/sandbox/config/simpler.yml +1 -0
- data/spec/sandbox/config/simpler_site.yml +2 -0
- data/spec/sandbox/config.yml +2 -0
- data/spec/sandbox/fixtures/examples.yml +8 -0
- data/spec/sandbox/fixtures/users.yml +2 -0
- data/spec/sandbox/flows/batman.rb +5 -0
- data/spec/sandbox/flows/robin.rb +4 -0
- data/spec/sandbox/pages/foo/bar_page.rb +9 -0
- data/spec/sandbox/pages/foo/partials/partial_the_reckoning.rb +2 -0
- data/spec/settings_spec.rb +103 -0
- data/spec/site_generator_spec.rb +62 -0
- data/spec/site_spec.rb +249 -0
- data/spec/spec_generator_helper.rb +40 -0
- data/spec/spec_generator_spec.rb +24 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/steps_generator_spec.rb +29 -0
- data/spec/string_spec.rb +17 -0
- data/spec/table_spec.rb +32 -0
- data/spec/taza_spec.rb +12 -0
- data/spec/watircraft_bin_spec.rb +14 -0
- data/watircraft.gemspec +53 -0
- data/watircraft_generators/page/USAGE +11 -0
- data/watircraft_generators/page/page_generator.rb +65 -0
- data/watircraft_generators/page/templates/page.rb.erb +8 -0
- data/watircraft_generators/site/site_generator.rb +51 -0
- data/watircraft_generators/site/templates/environments.yml.erb +4 -0
- data/watircraft_generators/site/templates/site.rb.erb +10 -0
- data/watircraft_generators/spec/USAGE +8 -0
- data/watircraft_generators/spec/spec_generator.rb +54 -0
- data/watircraft_generators/spec/templates/spec.rb.erb +17 -0
- data/watircraft_generators/steps/USAGE +13 -0
- data/watircraft_generators/steps/steps_generator.rb +62 -0
- data/watircraft_generators/steps/templates/steps.rb.erb +12 -0
- metadata +229 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
# instance_exec comes with >1.8.7 thankfully
|
2
|
+
if VERSION <= '1.8.6'
|
3
|
+
class Object
|
4
|
+
module InstanceExecHelper; end
|
5
|
+
include InstanceExecHelper
|
6
|
+
# instance_exec method evaluates a block of code relative to the specified object, with parameters whom come from outside the object.
|
7
|
+
def instance_exec(*args, &block)
|
8
|
+
begin
|
9
|
+
old_critical, Thread.critical = Thread.critical, true
|
10
|
+
n = 0
|
11
|
+
n += 1 while respond_to?(mname="__instance_exec#{n}")
|
12
|
+
InstanceExecHelper.module_eval{ define_method(mname, &block) }
|
13
|
+
ensure
|
14
|
+
Thread.critical = old_critical
|
15
|
+
end
|
16
|
+
begin
|
17
|
+
ret = send(mname, *args)
|
18
|
+
ensure
|
19
|
+
InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
|
20
|
+
end
|
21
|
+
ret
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'activesupport'
|
3
|
+
|
4
|
+
class String
|
5
|
+
# pluralizes a string and turns it into a symbol
|
6
|
+
# Example:
|
7
|
+
# "apple".pluralize_to_sym # => :apples
|
8
|
+
def pluralize_to_sym
|
9
|
+
self.pluralize.to_sym
|
10
|
+
end
|
11
|
+
# Opposite of humanize. Converts to lower case and converts spaces to underscores.
|
12
|
+
# Example:
|
13
|
+
# "Add Book".computerize # => "add_book"
|
14
|
+
def computerize
|
15
|
+
self.underscore.downcase.gsub ' ', '_'
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# TODO: support radiogroup
|
2
|
+
# TODO: migrate this code into Watir
|
3
|
+
# TODO: also handle FireWatir classes
|
4
|
+
module Watir
|
5
|
+
class TextField # includes Hidden
|
6
|
+
def display_value
|
7
|
+
value
|
8
|
+
end
|
9
|
+
end
|
10
|
+
class FileField
|
11
|
+
def display_value
|
12
|
+
value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class CheckBox
|
16
|
+
# returns a boolean
|
17
|
+
def display_value
|
18
|
+
checked?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
class SelectList
|
22
|
+
# Note: currently works for single-select only
|
23
|
+
def display_value
|
24
|
+
getSelectedItems[0]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
class Button
|
28
|
+
def display_value
|
29
|
+
value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
class Element
|
33
|
+
def display_value
|
34
|
+
text
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class B < NonControlElement
|
39
|
+
TAG = 'B'
|
40
|
+
end
|
41
|
+
end
|
data/lib/taza/browser.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Taza
|
2
|
+
class Browser
|
3
|
+
|
4
|
+
# Create a browser instance depending on configuration. Configuration should be read in via Taza::Settings.config.
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
# browser = Taza::Browser.create(Taza::Settings.config)
|
8
|
+
#
|
9
|
+
def self.create(params={})
|
10
|
+
self.send("create_#{params[:driver]}".to_sym,params)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def self.create_watir(params)
|
16
|
+
require 'watir'
|
17
|
+
if params[:browser] == :ie
|
18
|
+
require 'watir/ie'
|
19
|
+
require 'extensions/watir'
|
20
|
+
end
|
21
|
+
Watir::Browser.default = params[:browser].to_s
|
22
|
+
Watir::Browser.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.create_selenium(params)
|
26
|
+
require 'selenium'
|
27
|
+
Selenium::SeleniumDriver.new(params[:server_ip],params[:server_port],'*' + params[:browser].to_s,params[:timeout])
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.create_fake(params)
|
31
|
+
FakeBrowser.new
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class FakeBrowser
|
37
|
+
def goto(*args)
|
38
|
+
end
|
39
|
+
def close
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
data/lib/taza/entity.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Taza
|
2
|
+
class Entity
|
3
|
+
#Creates a entity, pass in a hash to be methodized and the fixture to look up other fixtures (not entirely happy with this abstraction)
|
4
|
+
def initialize(hash,fixture)
|
5
|
+
@hash = hash
|
6
|
+
@fixture = fixture
|
7
|
+
define_methods_for_hash_keys
|
8
|
+
end
|
9
|
+
|
10
|
+
#This method converts hash keys into methods onto the entity
|
11
|
+
def define_methods_for_hash_keys
|
12
|
+
@hash.keys.each do |key|
|
13
|
+
create_method(key) do
|
14
|
+
get_value_for_entry(key)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
#This method will lookup another fixture if a pluralized fixture exists otherwise return the value in the hash
|
20
|
+
def get_value_for_entry(key) # :nodoc:
|
21
|
+
if @fixture.pluralized_fixture_exists?(key)
|
22
|
+
@fixture.get_fixture_entity(key.pluralize_to_sym,@hash[key])
|
23
|
+
else
|
24
|
+
@hash[key]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def create_method(name, &block) # :nodoc:
|
30
|
+
self.class.send(:define_method, name, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/taza/fixture.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Taza
|
2
|
+
class Fixture # :nodoc:
|
3
|
+
|
4
|
+
def initialize # :nodoc:
|
5
|
+
@fixtures = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def load_all # :nodoc:
|
9
|
+
Dir.glob(fixtures_pattern) do |file|
|
10
|
+
entitized_fixture = {}
|
11
|
+
YAML.load_file(file).each do |key, value|
|
12
|
+
entitized_fixture[key] = value.convert_hash_keys_to_methods(self)
|
13
|
+
end
|
14
|
+
@fixtures[File.basename(file,'.yml').to_sym] = entitized_fixture
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def fixture_names # :nodoc:
|
19
|
+
@fixtures.keys
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_fixture_entity(fixture_file_key,entity_key) # :nodoc:
|
23
|
+
@fixtures[fixture_file_key][entity_key]
|
24
|
+
end
|
25
|
+
|
26
|
+
def pluralized_fixture_exists?(singularized_fixture_name) # :nodoc:
|
27
|
+
fixture_names.include?(singularized_fixture_name.pluralize_to_sym)
|
28
|
+
end
|
29
|
+
|
30
|
+
def fixtures_pattern # :nodoc:
|
31
|
+
File.join(base_path, 'fixtures','*.yml')
|
32
|
+
end
|
33
|
+
|
34
|
+
def base_path # :nodoc:
|
35
|
+
File.join('.','spec')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# The module that will mixin methods based on the fixture files in your 'spec/fixtures'
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
# describe "something" do
|
43
|
+
# it "should test something" do
|
44
|
+
# users(:jane_smith).first_name.should eql("jane")
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# where there is a spec/fixtures/users.yml file containing a entry of:
|
49
|
+
# jane_smith:
|
50
|
+
# first_name: jane
|
51
|
+
# last_name: smith
|
52
|
+
module Fixtures
|
53
|
+
def Fixtures.included(other_module) # :nodoc:
|
54
|
+
fixture = Fixture.new
|
55
|
+
fixture.load_all
|
56
|
+
fixture.fixture_names.each do |fixture_name|
|
57
|
+
self.class_eval do
|
58
|
+
define_method(fixture_name) do |entity_key|
|
59
|
+
fixture.get_fixture_entity(fixture_name,entity_key.to_s)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/taza/flow.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Taza
|
2
|
+
# Flows provide a way to write and manage common actions on a site.
|
3
|
+
# For instance, on an e-commerce site you may have multiple tests where a user is supposed to create a
|
4
|
+
# new account and add a product to the shopping bag. In this case you could have two flows. create_an_account
|
5
|
+
# and add_product_to_bag.
|
6
|
+
#
|
7
|
+
# Here's how you would get this started where your site is called Widgets of the Future:
|
8
|
+
# $ ./script/generate flow create_an_account widgets_of_the_future
|
9
|
+
# $ ./script/generate flow add_product_to_bag widgets_of_the_future
|
10
|
+
#
|
11
|
+
# This will generate flows for you in lib/sites/widgets_of_the_future/flows/
|
12
|
+
#
|
13
|
+
# From here you can create the logic needed to perform these flows without ever referencing a browser object:
|
14
|
+
#
|
15
|
+
# module WidgetsOfTheFuture
|
16
|
+
# class WidgetsOfTheFuture < Taza::Site
|
17
|
+
# def create_an_account_flow(params={})
|
18
|
+
# home_page.create_an_account_link.click
|
19
|
+
# create_an_account_page do |cap|
|
20
|
+
# cap.email.set params[:email]
|
21
|
+
# cap.password.set params[:password]
|
22
|
+
# cap.submit.click
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
#
|
29
|
+
# Then inside a spec or test you could run this flow like:
|
30
|
+
#
|
31
|
+
# describe "Widgets of the Future" do
|
32
|
+
# it "should do widgety things so that we can make more monies" do
|
33
|
+
# WidgetsOfTheFuture.new do |w|
|
34
|
+
# w.create_an_account_flow :email => "i.am@the.widget.store.com", :password => "secret"
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
class Flow
|
39
|
+
end
|
40
|
+
end
|
data/lib/taza/page.rb
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
require 'extensions/string'
|
2
|
+
require 'watir/exceptions' # so we can trap them
|
3
|
+
require 'watircraft/table'
|
4
|
+
|
5
|
+
module Taza
|
6
|
+
# An abstraction of a web page, place the elements you care about accessing in here as well as specify the filters that apply when trying to access the element.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# require 'taza'
|
10
|
+
# class HomePage < Taza::Page
|
11
|
+
# element(:foo) {browser.element_by_xpath('some xpath')}
|
12
|
+
# filter :title_given, :foo
|
13
|
+
#
|
14
|
+
# def title_given
|
15
|
+
# browser.title.nil?
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# homepage.foo will return the element specified in the block if the filter returned true
|
20
|
+
class Page
|
21
|
+
attr_accessor :browser, :site
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
def elements # :nodoc:
|
26
|
+
@elements ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def filters # :nodoc:
|
30
|
+
@filters ||= Hash.new { [] }
|
31
|
+
end
|
32
|
+
|
33
|
+
def fields # :nodoc:
|
34
|
+
@fields ||= []
|
35
|
+
end
|
36
|
+
|
37
|
+
def url string=nil
|
38
|
+
if string.nil?
|
39
|
+
@url
|
40
|
+
else
|
41
|
+
@url = string
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# An element on a page
|
46
|
+
#
|
47
|
+
# Watir Example:
|
48
|
+
# class HomePage < Taza::Page
|
49
|
+
# element(:next_button) {browser.button(:value, 'Next'}
|
50
|
+
# end
|
51
|
+
# home_page.next_button.click
|
52
|
+
def element(name, &block)
|
53
|
+
name = name.to_s.computerize.to_sym
|
54
|
+
elements[name] = block
|
55
|
+
end
|
56
|
+
|
57
|
+
# An element on a page that has a value.
|
58
|
+
# Use #field for input elements and data elements.
|
59
|
+
#
|
60
|
+
# class HomePage < Taza::Page
|
61
|
+
# field(:name) {browser.text_field(:name, 'user_name')}
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# home_page.name_field # returns the text_field element
|
65
|
+
# home_page.name_field.exists?
|
66
|
+
# home_page.name = "Fred" # calls the #set method on the text_field
|
67
|
+
# home_page.name # returns the current value (display_value) of the text_field
|
68
|
+
#
|
69
|
+
# The following Watir elements provide both #set and #display_value methods
|
70
|
+
# text_field (both text boxes and text areas)
|
71
|
+
# hidden
|
72
|
+
# file_field
|
73
|
+
# select_list
|
74
|
+
# checkbox
|
75
|
+
# (radios are the obvious item missing from this list -- we're working on it.)
|
76
|
+
#
|
77
|
+
# The following Watir elements provide #display_value methods (but not #set methods).
|
78
|
+
# button
|
79
|
+
# cell
|
80
|
+
# hidden
|
81
|
+
# all non-control elements, including divs, spans and most other elements.
|
82
|
+
def field(name, suffix='field', &block)
|
83
|
+
name = name.to_s.computerize.to_sym
|
84
|
+
fields << name
|
85
|
+
element_name = "#{name}_#{suffix}"
|
86
|
+
elements[element_name] = block
|
87
|
+
define_method(name) do
|
88
|
+
send(element_name).display_value
|
89
|
+
end
|
90
|
+
define_method("#{name}=") do |value|
|
91
|
+
send(element_name).set value
|
92
|
+
end
|
93
|
+
element_name
|
94
|
+
end
|
95
|
+
|
96
|
+
# A filter for element(s) on a page
|
97
|
+
# Example:
|
98
|
+
# class HomePage < Taza::Page
|
99
|
+
# element(:foo) {browser.element_by_xpath('some xpath')}
|
100
|
+
# filter :title_given, :foo
|
101
|
+
# #a filter will apply to all elements if none are specified
|
102
|
+
# filter :some_filter
|
103
|
+
# #a filter will also apply to all elements if the symbol :all is given
|
104
|
+
# filter :another_filter, :all
|
105
|
+
#
|
106
|
+
# def some_filter
|
107
|
+
# true
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# def some_filter
|
111
|
+
# true
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# def title_given
|
115
|
+
# browser.title.nil?
|
116
|
+
# end
|
117
|
+
# end
|
118
|
+
def filter(method_name, *elements)
|
119
|
+
elements = [:all] if elements.empty?
|
120
|
+
elements.each do |element|
|
121
|
+
self.filters[element] = self.filters[element] << method_name
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Provides access to a WatirCraft::Table.
|
126
|
+
#
|
127
|
+
# Requires that an element also be declared on the page that directly
|
128
|
+
# wraps the table element itself.
|
129
|
+
#
|
130
|
+
# Example definition
|
131
|
+
#
|
132
|
+
# class YourCartPage < ::Taza::Page
|
133
|
+
# element(:items_table) {@browser.table(:index, 1)}
|
134
|
+
# table(:items) do
|
135
|
+
# field(:quantity) {@row.cell(:index, 1)}
|
136
|
+
# field(:description) {@row.cell(:index, 2)}
|
137
|
+
# end
|
138
|
+
# field(:total) {@browser.cell(:id, 'totalcell')}
|
139
|
+
#
|
140
|
+
# Example usage
|
141
|
+
#
|
142
|
+
# your_cart_page.items.row(:description => 'Pragmatic Project Automation').quantity.should == '1'
|
143
|
+
#
|
144
|
+
# Technical details: this method creates a
|
145
|
+
# subclass and then allows its class methods to define fields and
|
146
|
+
# elements on the table.
|
147
|
+
def table(name, &block)
|
148
|
+
# create subclass for the table
|
149
|
+
sub_class = Class.new(WatirCraft::Table)
|
150
|
+
sub_class.class_eval &block
|
151
|
+
# add method to the page, it returns an instance of the table subclass
|
152
|
+
define_method(name) do
|
153
|
+
sub_class.new send("#{name}_table")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def initialize
|
159
|
+
add_element_methods
|
160
|
+
@active_filters = []
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_element_methods # :nodoc:
|
164
|
+
self.class.elements.each do |element_name,element_block|
|
165
|
+
filters = self.class.filters[element_name] + self.class.filters[:all]
|
166
|
+
add_element_method(:filters => filters, :element_name => element_name, :element_block => element_block)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def add_element_method(params) # :nodoc:
|
171
|
+
self.class.class_eval do
|
172
|
+
define_method(params[:element_name]) do |*args|
|
173
|
+
check_filters(params)
|
174
|
+
self.instance_exec(*args,¶ms[:element_block])
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def check_filters(params) # :nodoc:
|
180
|
+
params[:filters].each do |filter_method|
|
181
|
+
unless @active_filters.include?(filter_method)
|
182
|
+
@active_filters << filter_method
|
183
|
+
raise FilterError, "#{filter_method} returned false for #{params[:element_name]}" unless send(filter_method)
|
184
|
+
@active_filters.delete(filter_method)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Go to this page. Url is computed based the page url and the url from the
|
190
|
+
# Site & Settings.
|
191
|
+
def goto
|
192
|
+
@site.goto self.class.url
|
193
|
+
end
|
194
|
+
|
195
|
+
# Return the full url expected for the page, taking into account the Site
|
196
|
+
# and settings.
|
197
|
+
def full_url
|
198
|
+
File.join(@site.origin, self.class.url)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Enter values into fields on the page using a hash, using the key of
|
202
|
+
# each pair to name the field.
|
203
|
+
def populate hash
|
204
|
+
hash.each do |key, value|
|
205
|
+
send "#{key}=", value
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Verify that the fields specified by the keys in the hash correspond to the
|
210
|
+
# provided values.
|
211
|
+
def validate hash
|
212
|
+
hash.each do |key, value|
|
213
|
+
send(key).should == value
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Return the names of the elements defined for the page.
|
218
|
+
def elements
|
219
|
+
self.class.elements.keys.map &:to_s
|
220
|
+
end
|
221
|
+
|
222
|
+
# Return the names of the fields defined for the page.
|
223
|
+
def fields
|
224
|
+
self.class.fields.map &:to_s
|
225
|
+
end
|
226
|
+
|
227
|
+
# Returns a hash with the names and values of the specified fields.
|
228
|
+
# If no fields are specifieds, all fields on the page are used.
|
229
|
+
def values field_names=fields
|
230
|
+
result = {}
|
231
|
+
field_names.each { |name| result[name.to_sym] = send(name)}
|
232
|
+
result
|
233
|
+
end
|
234
|
+
|
235
|
+
include Watir::Exception
|
236
|
+
def element_exist? name
|
237
|
+
begin
|
238
|
+
send(name).exist?
|
239
|
+
rescue UnknownFrameException, UnknownObjectException,
|
240
|
+
UnknownFormException, UnknownCellException
|
241
|
+
false
|
242
|
+
end
|
243
|
+
end
|
244
|
+
alias :element_exists? :element_exist?
|
245
|
+
|
246
|
+
def elements_exist? element_names=elements
|
247
|
+
result = {}
|
248
|
+
element_names.each do |element|
|
249
|
+
result[element.to_sym] = element_exist?(element)
|
250
|
+
end
|
251
|
+
result
|
252
|
+
end
|
253
|
+
alias :elements_exists? :elements_exist?
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
class FilterError < StandardError; end
|
258
|
+
|
259
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'activesupport'
|
2
|
+
|
3
|
+
module Taza
|
4
|
+
class Settings
|
5
|
+
# The config settings from the site.yml and config.yml files.
|
6
|
+
# ENV variables will override the settings.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# Taza::Settings.config('google')
|
10
|
+
def self.config(site_name=nil)
|
11
|
+
env_settings = {}
|
12
|
+
keys = %w(browser driver timeout server_ip server_port)
|
13
|
+
keys.each do |key|
|
14
|
+
env_settings[key.to_sym] = ENV[key.upcase] if ENV[key.upcase]
|
15
|
+
end
|
16
|
+
|
17
|
+
default_settings = {:browser => :firefox, :driver => :watir}
|
18
|
+
|
19
|
+
# Because of the way #merge works, the settings at the bottom of the list
|
20
|
+
# trump those at the top.
|
21
|
+
settings = environment_settings.merge(
|
22
|
+
default_settings.merge(
|
23
|
+
config_file.merge(
|
24
|
+
env_settings)))
|
25
|
+
|
26
|
+
settings[:browser] = settings[:browser].to_sym
|
27
|
+
settings[:driver] = settings[:driver].to_sym
|
28
|
+
settings
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a hash corresponding to the project config file.
|
32
|
+
def self.config_file
|
33
|
+
if File.exists?(config_file_path)
|
34
|
+
hash = YAML.load_file(config_file_path)
|
35
|
+
else
|
36
|
+
hash = {}
|
37
|
+
end
|
38
|
+
self.convert_string_keys_to_symbols hash
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.config_file_path # :nodoc:
|
42
|
+
File.join(path, 'config', 'config.yml')
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a hash for the currently specified test environment
|
46
|
+
def self.environment_settings # :nodoc:
|
47
|
+
file = File.join(path, environment_file)
|
48
|
+
hash_of_hashes = YAML.load_file(file)
|
49
|
+
unless hash_of_hashes.has_key? environment
|
50
|
+
raise "Environment #{environment} not found in #{file}"
|
51
|
+
end
|
52
|
+
convert_string_keys_to_symbols hash_of_hashes[environment]
|
53
|
+
end
|
54
|
+
|
55
|
+
@@root = nil
|
56
|
+
|
57
|
+
def self.path # :nodoc:
|
58
|
+
@@root || APP_ROOT
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.path= path
|
62
|
+
@@root = path
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.environment
|
66
|
+
ENV['ENVIRONMENT'] || 'test'
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.convert_string_keys_to_symbols hash
|
70
|
+
returning Hash.new do |new_hash|
|
71
|
+
hash.each_pair {|k, v| new_hash[k.to_sym] = v}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def self.environment_file
|
77
|
+
'config/environments.yml'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|