watirmark 5.14.16
Sign up to get free protection for your applications and to get access to all the features.
- data/app_generators/create_project/create_project_generator.rb +115 -0
- data/app_generators/create_project/templates/features/env.rb.erb +8 -0
- data/app_generators/create_project/templates/features/model_steps.rb.erb +9 -0
- data/app_generators/create_project/templates/features/post_error_steps.rb.erb +15 -0
- data/app_generators/create_project/templates/features/sample.feature.erb +5 -0
- data/app_generators/create_project/templates/features/site_steps.rb.erb +7 -0
- data/app_generators/create_project/templates/generators/controller.rb.erb +9 -0
- data/app_generators/create_project/templates/generators/generate.rb.erb +9 -0
- data/app_generators/create_project/templates/generators/model.rb.erb +7 -0
- data/app_generators/create_project/templates/generators/mvc_generator.rb.erb +100 -0
- data/app_generators/create_project/templates/generators/rbeautify.rb.erb +212 -0
- data/app_generators/create_project/templates/generators/view.rb.erb +16 -0
- data/app_generators/create_project/templates/generators/workflow_loader.rb.erb +1 -0
- data/app_generators/create_project/templates/library/base_controller.rb.erb +9 -0
- data/app_generators/create_project/templates/library/base_view.rb.erb +6 -0
- data/app_generators/create_project/templates/library/configuration.rb.erb +6 -0
- data/app_generators/create_project/templates/library/core_libraries.rb.erb +9 -0
- data/app_generators/create_project/templates/library/loader.rb.erb +23 -0
- data/app_generators/create_project/templates/library/page_load_checker.rb.erb +11 -0
- data/app_generators/create_project/templates/library/post_errors_checker.rb.erb +23 -0
- data/app_generators/create_project/templates/library/project_require_file.rb.erb +8 -0
- data/app_generators/create_project/templates/library/search_controller.rb.erb +12 -0
- data/app_generators/create_project/templates/library/workflows.rb.erb +0 -0
- data/app_generators/create_project/templates/project/config.yml.erb +3 -0
- data/app_generators/create_project/templates/project/gemfile.rb.erb +11 -0
- data/app_generators/create_project/templates/project/rakefile.rb.erb +21 -0
- data/bin/etapestry/Gemfile +11 -0
- data/bin/etapestry/config.yml +3 -0
- data/bin/etapestry/features/etapestry_home.feature +5 -0
- data/bin/etapestry/features/step_definitions/model_steps.rb +9 -0
- data/bin/etapestry/features/step_definitions/post_error_steps.rb +15 -0
- data/bin/etapestry/features/step_definitions/site_steps.rb +7 -0
- data/bin/etapestry/features/support/env.rb +8 -0
- data/bin/etapestry/generators/mvc/mvc_generator.rb +100 -0
- data/bin/etapestry/generators/mvc/rbeautify.rb +212 -0
- data/bin/etapestry/generators/mvc/templates/controller.rb.erb +9 -0
- data/bin/etapestry/generators/mvc/templates/model.rb.erb +7 -0
- data/bin/etapestry/generators/mvc/templates/view.rb.erb +16 -0
- data/bin/etapestry/generators/mvc/templates/workflow_loader.rb.erb +1 -0
- data/bin/etapestry/lib/etapestry.rb +8 -0
- data/bin/etapestry/lib/etapestry/checkers/page_load_checker.rb +11 -0
- data/bin/etapestry/lib/etapestry/checkers/post_errors_checker.rb +23 -0
- data/bin/etapestry/lib/etapestry/configuration.rb +6 -0
- data/bin/etapestry/lib/etapestry/core_libraries.rb +9 -0
- data/bin/etapestry/lib/etapestry/loader.rb +23 -0
- data/bin/etapestry/lib/etapestry/site/base_controller.rb +9 -0
- data/bin/etapestry/lib/etapestry/site/base_view.rb +6 -0
- data/bin/etapestry/lib/etapestry/site/search_controller.rb +12 -0
- data/bin/etapestry/lib/etapestry/workflows.rb +0 -0
- data/bin/etapestry/rakefile.rb +21 -0
- data/bin/etapestry/script/generate.rb +9 -0
- data/bin/twitter/features/hashtag_search.feature +93 -0
- data/bin/twitter/features/step_definitions/hashtag_steps.rb +9 -0
- data/bin/twitter/lib/twitter/workflows/search/result_controller.rb +13 -0
- data/bin/twitter/lib/twitter/workflows/search/result_model.rb +5 -0
- data/bin/twitter/lib/twitter/workflows/search/result_view.rb +19 -0
- data/bin/watirmark +10 -0
- data/lib/watirmark.rb +26 -0
- data/lib/watirmark/at_exit.rb +13 -0
- data/lib/watirmark/configuration.rb +201 -0
- data/lib/watirmark/controller/actions.rb +172 -0
- data/lib/watirmark/controller/assertions.rb +116 -0
- data/lib/watirmark/controller/controller.rb +191 -0
- data/lib/watirmark/controller/dialogs.rb +33 -0
- data/lib/watirmark/controller/matcher.rb +19 -0
- data/lib/watirmark/cucumber/cuke_helper.rb +150 -0
- data/lib/watirmark/cucumber/email_helper.rb +103 -0
- data/lib/watirmark/cucumber/env.rb +9 -0
- data/lib/watirmark/cucumber/hooks.rb +16 -0
- data/lib/watirmark/cucumber/model_helper.rb +34 -0
- data/lib/watirmark/cucumber/transforms.rb +55 -0
- data/lib/watirmark/exceptions.rb +15 -0
- data/lib/watirmark/extensions/ruby_extensions.rb +129 -0
- data/lib/watirmark/extensions/webdriver_extensions.rb +150 -0
- data/lib/watirmark/formatters/snapshot_formatter.rb +23 -0
- data/lib/watirmark/loader.rb +87 -0
- data/lib/watirmark/model.rb +3 -0
- data/lib/watirmark/models/cucumber_helper.rb +49 -0
- data/lib/watirmark/models/debug_methods.rb +21 -0
- data/lib/watirmark/models/default_values.rb +21 -0
- data/lib/watirmark/models/factory.rb +168 -0
- data/lib/watirmark/models/factory_method_generators.rb +84 -0
- data/lib/watirmark/models/factory_methods.rb +72 -0
- data/lib/watirmark/models/trait.rb +35 -0
- data/lib/watirmark/models/upload_csv.rb +24 -0
- data/lib/watirmark/page/keyed_element.rb +63 -0
- data/lib/watirmark/page/page.rb +50 -0
- data/lib/watirmark/page/page_definition.rb +187 -0
- data/lib/watirmark/page/process_page.rb +112 -0
- data/lib/watirmark/page/radio_maps.rb +53 -0
- data/lib/watirmark/profile.rb +22 -0
- data/lib/watirmark/rake/smoketest.rb +17 -0
- data/lib/watirmark/screenshot.rb +127 -0
- data/lib/watirmark/session.rb +115 -0
- data/lib/watirmark/version.rb +5 -0
- data/spec/assertions_spec.rb +95 -0
- data/spec/config_spec.rb +82 -0
- data/spec/controller_actions_spec.rb +91 -0
- data/spec/controller_spec.rb +426 -0
- data/spec/controllers_and_models_spec.rb +52 -0
- data/spec/model_factory_spec.rb +568 -0
- data/spec/model_traits_spec.rb +141 -0
- data/spec/page_spec.rb +127 -0
- data/spec/process_page_spec.rb +163 -0
- data/spec/spec_helper.rb +17 -0
- metadata +238 -0
@@ -0,0 +1,129 @@
|
|
1
|
+
module Watirmark::MatchMethod
|
2
|
+
def matches(x)
|
3
|
+
self == x
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class String
|
8
|
+
include Watirmark::MatchMethod
|
9
|
+
|
10
|
+
def strip_number_formatting
|
11
|
+
self.gsub!(/\$|,/,'')
|
12
|
+
self.gsub!(/\.00/,'')
|
13
|
+
self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Integer
|
18
|
+
include Watirmark::MatchMethod
|
19
|
+
end
|
20
|
+
|
21
|
+
class TrueClass
|
22
|
+
include Watirmark::MatchMethod
|
23
|
+
end
|
24
|
+
|
25
|
+
class FalseClass
|
26
|
+
include Watirmark::MatchMethod
|
27
|
+
end
|
28
|
+
|
29
|
+
class Regexp
|
30
|
+
def matches(x)
|
31
|
+
self.match(x)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
class Hash
|
37
|
+
# Returns a hash that only contains pairs with the specified keys
|
38
|
+
def extract(*keys)
|
39
|
+
keys = keys[0] if keys[0].is_a?(Array)
|
40
|
+
hash = self.class.new
|
41
|
+
keys.each { |k| hash[k] = self[k] if has_key?(k) }
|
42
|
+
hash
|
43
|
+
end
|
44
|
+
alias :slice :extract
|
45
|
+
end
|
46
|
+
|
47
|
+
class Array
|
48
|
+
def diff(a)
|
49
|
+
ary = dup
|
50
|
+
a.each {|i| ary.delete_at(i) if i == ary.index(i)}
|
51
|
+
ary
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
#############################
|
57
|
+
# From Why's Poignant Guide
|
58
|
+
#############################
|
59
|
+
class Object
|
60
|
+
def meta_class
|
61
|
+
class << self
|
62
|
+
self
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def meta_eval &blk
|
67
|
+
meta_class.instance_eval &blk
|
68
|
+
end
|
69
|
+
|
70
|
+
# Adds methods to a metaclass
|
71
|
+
def meta_def name, &blk
|
72
|
+
meta_eval { define_method name, &blk }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Defines an instance method within a class
|
76
|
+
def class_def name, &blk
|
77
|
+
class_eval { define_method name, &blk }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
# This would be better to be a struct because it would match the models we're
|
83
|
+
# using for inputs to the controllers. The problem is that with legacy code,
|
84
|
+
# we have a lot of input hashes that don't necessarily always have a page
|
85
|
+
# object keyword for every member of the hash. As such I've chosen to use
|
86
|
+
# OpenStruct. Fixing this would be a little hit/miss until all input data uses
|
87
|
+
# models
|
88
|
+
|
89
|
+
require 'ostruct'
|
90
|
+
|
91
|
+
class ModelOpenStruct < OpenStruct
|
92
|
+
def update(x)
|
93
|
+
x.each_pair {|key, value| self.send "#{key}=", value}
|
94
|
+
self
|
95
|
+
end
|
96
|
+
|
97
|
+
def keys
|
98
|
+
self.marshal_dump.keys
|
99
|
+
end
|
100
|
+
alias :keywords :keys
|
101
|
+
|
102
|
+
def has_key?(x)
|
103
|
+
keywords.include? x
|
104
|
+
end
|
105
|
+
alias :key? :has_key?
|
106
|
+
|
107
|
+
def to_h
|
108
|
+
h = {}
|
109
|
+
keywords.each { |name| h[name.to_sym] = self.send name}
|
110
|
+
h
|
111
|
+
end
|
112
|
+
|
113
|
+
# Stub these out so it doesn't find anything
|
114
|
+
def find(model)
|
115
|
+
end
|
116
|
+
|
117
|
+
def search_term
|
118
|
+
end
|
119
|
+
|
120
|
+
def model_class_name
|
121
|
+
'ModelOpenStruct'
|
122
|
+
end
|
123
|
+
|
124
|
+
def inspect
|
125
|
+
Watirmark.logger.info "ModelOpenStruct #{to_h}"
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'watir-webdriver/extensions/select_text'
|
2
|
+
|
3
|
+
Watir::always_locate = false
|
4
|
+
|
5
|
+
module Watir
|
6
|
+
|
7
|
+
class Browser
|
8
|
+
# for modal dialogs that close on submission, these might
|
9
|
+
# fail to run because the window has been destroyed
|
10
|
+
alias :old_run_checkers :run_checkers
|
11
|
+
|
12
|
+
# this is basically a check to make sure we're not
|
13
|
+
# running the checkers on a modal dialog that has closed
|
14
|
+
# by the time the checkers have run
|
15
|
+
def run_checkers
|
16
|
+
@error_checkers.each do |checker|
|
17
|
+
begin
|
18
|
+
checker.call(self)
|
19
|
+
rescue Selenium::WebDriver::Error::UnknownError, Selenium::WebDriver::Error::NoSuchWindowError => e
|
20
|
+
Watirmark.logger.warn "Unable to run checker: #{e.message}"
|
21
|
+
break
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Trigger checkers when manually submitting a form
|
28
|
+
class Form < HTMLElement
|
29
|
+
alias :old_submit :submit
|
30
|
+
def submit
|
31
|
+
old_submit
|
32
|
+
browser.run_checkers
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module Container
|
37
|
+
alias :row :tr
|
38
|
+
alias :cell :td
|
39
|
+
|
40
|
+
class DownloadLink < Anchor
|
41
|
+
def initialize(*args)
|
42
|
+
@dir = File.join(Watirmark::Configuration.instance.projectpath, "reports", "downloads")
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def download(file = nil)
|
47
|
+
click
|
48
|
+
locate_file(file)
|
49
|
+
end
|
50
|
+
|
51
|
+
def locate_file(file = nil)
|
52
|
+
if file
|
53
|
+
new_file = "#{@dir}/#{file}"
|
54
|
+
File.delete(new_file) if File.file?(new_file)
|
55
|
+
File.rename(last_modified_file, new_file)
|
56
|
+
new_file
|
57
|
+
else
|
58
|
+
last_modified_file
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def last_modified_file
|
63
|
+
Dir.new(@dir).select { |f| f!= '.' && f!='..' }.collect { |f| "#{@dir}/#{f}" }.sort { |a, b| File.mtime(b)<=>File.mtime(a) }.first
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def download_link(*args)
|
68
|
+
DownloadLink.new(self, extract_selector(args).merge(:tag_name => "a"))
|
69
|
+
end
|
70
|
+
|
71
|
+
class DownloadLinkCollection < ElementCollection
|
72
|
+
def element_class
|
73
|
+
DownloadLink
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def download_links(*args)
|
78
|
+
DownloadLinkCollection.new(self, extract_selector(args).merge(:tag_name => "a"))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Table < HTMLElement
|
83
|
+
def each
|
84
|
+
rows.each { |x| yield x }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class TableRow < HTMLElement
|
89
|
+
def each
|
90
|
+
cells.each { |x| yield x }
|
91
|
+
end
|
92
|
+
|
93
|
+
def column(what)
|
94
|
+
column = 0
|
95
|
+
parent.th(:text => what).when_present.parent.cells.each do |cell|
|
96
|
+
if what.kind_of? String
|
97
|
+
return self[column] if cell.text == what
|
98
|
+
else
|
99
|
+
return self[column] if cell.text =~ what
|
100
|
+
end
|
101
|
+
column +=1 unless cell.text.strip == ''
|
102
|
+
end
|
103
|
+
raise Watir::Exception::UnknownObjectException, "unable to locate column, using '#{what}'"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class CheckBox < Input
|
108
|
+
alias :value= :set
|
109
|
+
end
|
110
|
+
|
111
|
+
class Radio < Input
|
112
|
+
alias :old_radio_set :set
|
113
|
+
|
114
|
+
def set(value=nil)
|
115
|
+
@selector.update(:value => value.to_s) if value
|
116
|
+
old_radio_set
|
117
|
+
end
|
118
|
+
|
119
|
+
alias :value= :set
|
120
|
+
|
121
|
+
alias :old_radio_set? :set?
|
122
|
+
|
123
|
+
def set?(value=nil)
|
124
|
+
@selector.update(:value => value.to_s) if value
|
125
|
+
old_radio_set?
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class Select
|
130
|
+
alias :value= :select
|
131
|
+
alias :set :select
|
132
|
+
|
133
|
+
def getAllContents
|
134
|
+
options.map(&:text)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
class Element
|
139
|
+
alias :prev_sibling :previous_sibling
|
140
|
+
alias :prevsibling :previous_sibling
|
141
|
+
alias :nextsibling :next_sibling
|
142
|
+
|
143
|
+
def click_if_exists
|
144
|
+
click if exists?
|
145
|
+
end
|
146
|
+
|
147
|
+
alias :click_no_wait :click
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rspec/core/formatters/base_formatter'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Core
|
5
|
+
module Formatters
|
6
|
+
class SnapshotFormatter < BaseFormatter
|
7
|
+
def initialize(output)
|
8
|
+
super
|
9
|
+
@path=output.path + "_dir/"
|
10
|
+
Dir.mkdir(@path) if not File::directory?( @path )
|
11
|
+
end
|
12
|
+
|
13
|
+
def example_failed(example)
|
14
|
+
if Page.browser_exists?
|
15
|
+
append_text = example.description.gsub(/([^\w-])/, "_")
|
16
|
+
snapshot = "#{Time.now.to_i} - #{append_text}.png"
|
17
|
+
Page.browser.screenshot.save "#{@path}/#{snapshot}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Watirmark
|
2
|
+
|
3
|
+
def self.loader &block
|
4
|
+
ActiveSupport::Dependencies.mechanism = :require if defined? ActiveSupport::Dependencies
|
5
|
+
Loader.new.instance_eval &block
|
6
|
+
end
|
7
|
+
|
8
|
+
# This can be used for files that are page classes or flows.
|
9
|
+
# Autoloading them
|
10
|
+
# will not actually 'require' the file until a class in that file is used.
|
11
|
+
# Note that this does not apply to modules so it's most useful for the
|
12
|
+
# page accessors and any files in admin, user, etc.
|
13
|
+
class Loader
|
14
|
+
|
15
|
+
def autoload_files(directory)
|
16
|
+
mod = "Watirmark::#{product}"
|
17
|
+
each_file_in directory do |file|
|
18
|
+
libpath = library_path(file)
|
19
|
+
IO.readlines(file).each do |line|
|
20
|
+
_autoload_(mod, $1, libpath) if line =~ /^\s*class\s+([^<]\S+)[\s<]/
|
21
|
+
_autoload_(mod, $1, libpath) if line =~ /^\s+([A-Z]\S+)\s+=\s+[A-Z]\S+/
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
alias :autoload_file :autoload_files
|
26
|
+
|
27
|
+
def _autoload_(mod, klass, path)
|
28
|
+
return if klass =~ /\./
|
29
|
+
namespaces = mod.split('::')
|
30
|
+
m = Kernel.const_get(namespaces.shift)
|
31
|
+
m = namespaces.inject(m){|result, ns| result.const_get(ns)}
|
32
|
+
m.send(:autoload, klass.to_sym, path)
|
33
|
+
end
|
34
|
+
private :_autoload_
|
35
|
+
|
36
|
+
def load_files(directory) # product not used
|
37
|
+
each_file_in directory do | file |
|
38
|
+
require library_path(file)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def base_directory arg=nil
|
43
|
+
if arg
|
44
|
+
@base_directory = arg
|
45
|
+
elsif @base_directory
|
46
|
+
@base_directory
|
47
|
+
else
|
48
|
+
raise "base_directory not set"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def product arg=nil
|
53
|
+
if arg
|
54
|
+
@product = arg
|
55
|
+
elsif @product
|
56
|
+
@product
|
57
|
+
else
|
58
|
+
raise "product not set"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def module arg=nil
|
63
|
+
if arg
|
64
|
+
@module = arg
|
65
|
+
elseif
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def library_path(file)
|
72
|
+
File.join(File.dirname(file), File.basename(file, '.rb'))
|
73
|
+
end
|
74
|
+
|
75
|
+
def each_file_in(directory)
|
76
|
+
lib_path = File.join(base_directory, directory)
|
77
|
+
if File.directory?(lib_path)
|
78
|
+
files = Dir.glob(File.join(lib_path, '*.rb'))
|
79
|
+
else
|
80
|
+
files = Dir.glob(lib_path)
|
81
|
+
end
|
82
|
+
files.each do |file|
|
83
|
+
yield file unless File.directory? file
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Watirmark
|
2
|
+
module Model
|
3
|
+
|
4
|
+
module CucumberHelper
|
5
|
+
|
6
|
+
def format_value(value)
|
7
|
+
value = insert_model(value)
|
8
|
+
case value
|
9
|
+
when String
|
10
|
+
if value[0, 1].eql?("=") #straight eval
|
11
|
+
eval(value[1..value.length])
|
12
|
+
elsif value == "true"
|
13
|
+
true
|
14
|
+
elsif value == "false"
|
15
|
+
false
|
16
|
+
elsif value.strip == ''
|
17
|
+
nil
|
18
|
+
else
|
19
|
+
value
|
20
|
+
end
|
21
|
+
else
|
22
|
+
value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def insert_model(text)
|
27
|
+
result = text
|
28
|
+
regexp = /\[([^\]]+)\]\.(\w+)/
|
29
|
+
while result =~ regexp #get value from models
|
30
|
+
model_name = $1
|
31
|
+
method = $2
|
32
|
+
value = DataModels[model_name].send method.to_sym
|
33
|
+
result.sub!(regexp, value.to_s)
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
def merge_cucumber_table(cuke_table)
|
39
|
+
cuke_table.rows_hash.each do |key, value|
|
40
|
+
method_chain = key.to_s.split('.')
|
41
|
+
method = method_chain.pop
|
42
|
+
method_chain.inject(self) { |obj, m| obj.send m}.send "#{method}=", format_value(value)
|
43
|
+
end
|
44
|
+
Watirmark.logger.info "Updated #{inspect}"
|
45
|
+
self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|