bret-watircraft 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|