kuali-test-factory 0.5.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/COPYING +68 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +33 -0
- data/LICENSE +68 -0
- data/README.md +241 -0
- data/lib/test-factory.rb +18 -0
- data/lib/test-factory/collections_factory.rb +67 -0
- data/lib/test-factory/core_ext.rb +133 -0
- data/lib/test-factory/data_factory.rb +334 -0
- data/lib/test-factory/date_factory.rb +158 -0
- data/lib/test-factory/foundry.rb +76 -0
- data/lib/test-factory/gem_ext.rb +224 -0
- data/lib/test-factory/page_factory.rb +238 -0
- data/lib/test-factory/string_factory.rb +167 -0
- data/lib/test-factory/test_factory.rb +16 -0
- data/test-factory.gemspec +13 -0
- metadata +78 -0
@@ -0,0 +1,238 @@
|
|
1
|
+
# Copyright 2012-2014 The rSmart Group, Inc.
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# The PageFactory class provides a set of methods that allow the rapid creation of page element definitions--known
|
16
|
+
# colloquially as "page objects". These elements are defined using Watir syntax. Please see www.watir.com if you are
|
17
|
+
# not familiar with Watir.
|
18
|
+
#
|
19
|
+
class PageFactory
|
20
|
+
|
21
|
+
# As the PageFactory will be the superclass for all your page classes, having this initialize
|
22
|
+
# method here means it's only written once.
|
23
|
+
#
|
24
|
+
def initialize browser, visit = false
|
25
|
+
@browser = browser
|
26
|
+
goto if visit
|
27
|
+
expected_element if respond_to? :expected_element
|
28
|
+
has_expected_title? if respond_to? :has_expected_title?
|
29
|
+
end
|
30
|
+
|
31
|
+
# Catches any "missing" methods and passes them to the browser object--which means
|
32
|
+
# that Watir will take care of parsing them, so the assumption is that the method being
|
33
|
+
# passed is a valid method for the browser object.
|
34
|
+
#
|
35
|
+
def method_missing sym, *args, &block
|
36
|
+
@browser.send sym, *args, &block
|
37
|
+
end
|
38
|
+
|
39
|
+
class << self
|
40
|
+
|
41
|
+
# Define this in a page class and when you use the "visit" method to instantiate the class
|
42
|
+
# it will enter the URL in the browser's address bar.
|
43
|
+
#
|
44
|
+
def page_url url
|
45
|
+
define_method 'goto' do
|
46
|
+
@browser.goto url
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Define this in a page class and when that class is instantiated it will wait until that
|
51
|
+
# element appears on the page before continuing with the script.
|
52
|
+
# @param element_name [Symbol] The method name of the element that must be present on the page
|
53
|
+
#
|
54
|
+
def expected_element element_name, timeout=30
|
55
|
+
define_method 'expected_element' do
|
56
|
+
self.send(element_name).wait_until_present timeout
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Define this in a page class and when the class is instantiated it will verify that
|
61
|
+
# the browser's title matches the expected title. If there isn't a match, it raises an
|
62
|
+
# error and halts the script.
|
63
|
+
# @param expected_title [String] The exact text that is expected to appear in the Browser title when the page loads
|
64
|
+
#
|
65
|
+
def expected_title expected_title
|
66
|
+
define_method 'has_expected_title?' do
|
67
|
+
has_expected_title = expected_title.kind_of?(Regexp) ? expected_title =~ @browser.title : expected_title == @browser.title
|
68
|
+
raise "Expected title '#{expected_title}' instead of '#{@browser.title}'" unless has_expected_title
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# The basic building block for defining and interacting with
|
73
|
+
# elements on a web page. # Use in conjunction with
|
74
|
+
# Watir to define all elements on a given page that are important to validate.
|
75
|
+
#
|
76
|
+
# Methods that take one or more parameters can be built with this as well.
|
77
|
+
#
|
78
|
+
# @example
|
79
|
+
# element(:title) { |b| b.text_field(:id=>"title-id") }
|
80
|
+
# value(:page_header) { |b| b.h3(:class=>"page_header").text }
|
81
|
+
# action(:continue) { |b| b.frm.button(:value=>"Continue").click } => Creates a #continue method that clicks the Continue button
|
82
|
+
# p_element(:select_style) { |stylename, b| b.div(:text=>/#{Regexp.escape(stylename)}/).link(:text=>"Select").click } => #select_style(stylename)
|
83
|
+
#
|
84
|
+
def element name, &block
|
85
|
+
raise "#{name} is being defined twice in #{self}!" if self.instance_methods.include?(name.to_sym)
|
86
|
+
define_method name.to_s do |*thing|
|
87
|
+
Proc.new(&block).call *thing, self
|
88
|
+
end
|
89
|
+
end
|
90
|
+
alias_method :action, :element
|
91
|
+
alias_method :value, :element
|
92
|
+
alias_method :p_element, :element
|
93
|
+
alias_method :p_action, :element
|
94
|
+
alias_method :p_value, :element
|
95
|
+
|
96
|
+
# Use this for links that are safe to define by their text string.
|
97
|
+
# This method will return two methods for interacting with the link:
|
98
|
+
# one that refers to the link itself, and one that clicks on it.
|
99
|
+
# Since it's assumed that the most common thing done with a link is to click it,
|
100
|
+
# the method for clicking it will be named according to the text of the link,
|
101
|
+
# and the method for the link itself will have "_link" appended to it. Any special
|
102
|
+
# characters are stripped from the string. Capital letters are made lower case.
|
103
|
+
# And spaces and dashes are converted to underscores.
|
104
|
+
#
|
105
|
+
# @example
|
106
|
+
# link("Click Me For Fun!") => Creates the methods #click_me_for_fun and #click_me_for_fun_link
|
107
|
+
#
|
108
|
+
# The last parameter in the method is optional. Use it when
|
109
|
+
# you need the method name to be different from the text of
|
110
|
+
# the link--for example if the link text is something unhelpful,
|
111
|
+
# like "here", or else the link text gets updated (e.g., what was
|
112
|
+
# "Log In" is now "Sign In", instead) and you don't
|
113
|
+
# want to have to go through all your data objects and step
|
114
|
+
# definitions to update them to the new method name.
|
115
|
+
#
|
116
|
+
# @example
|
117
|
+
# link("Click Me For Fun!", :click_me) => Creates the methods #click_me and #click_me_link
|
118
|
+
#
|
119
|
+
def link link_text, *alias_name
|
120
|
+
elementize(:link, link_text, *alias_name)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Defines four methods related to Kuali's "Maintainable" fields, which can sometimes be read-only spans.
|
124
|
+
# The id_string parameter must be a String value that matches the element's name attribute value after the
|
125
|
+
# 'document.newMaintainable.' prefix.
|
126
|
+
#
|
127
|
+
# @example
|
128
|
+
# maintainable(:text_field, :chart_code, 'chartOfAccountsCode') => Creates the methods :chart_code, :chart_code_readonly, :chart_code_old, and :chart_code_new
|
129
|
+
def maintainable(watir_element, method_name, id_string)
|
130
|
+
element(method_name) { |b| b.frm.send(watir_element, name: "document.newMaintainableObject.#{id_string}") }
|
131
|
+
value("#{method_name}_readonly".to_sym) { |b| b.frm.span(id: "document.newMaintainableObject.#{id_string}.div").text.strip }
|
132
|
+
value("#{method_name}_old".to_sym) { |b| b.frm.span(id: "document.oldMaintainableObject.#{id_string}.div").text.strip }
|
133
|
+
value("#{method_name}_new".to_sym) { |b|
|
134
|
+
if watir_element==:select
|
135
|
+
b.send(method_name).exists? ? b.send(method_name).selected_options[0].text.strip : b.send("#{method_name}_readonly".to_sym)
|
136
|
+
else
|
137
|
+
b.send(method_name).exists? ? b.send(method_name).value.strip : b.send("#{method_name}_readonly".to_sym)
|
138
|
+
end
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
# Use this for buttons that are safe to define by their value attribute.
|
143
|
+
# This method will return two methods for interacting with the button:
|
144
|
+
# one that refers to the button itself, and one that clicks on it.
|
145
|
+
# Since it's assumed that the most common thing done with a button is to click it,
|
146
|
+
# the method for clicking it will be named according to the value of the button,
|
147
|
+
# and the method for the button itself will have "_button" appended to it. Any special
|
148
|
+
# characters are stripped from the string. Capital letters are made lower case.
|
149
|
+
# And spaces and dashes are converted to underscores.
|
150
|
+
# @param button_text [String] The contents of the button's value tag in the HTML
|
151
|
+
#
|
152
|
+
# @example
|
153
|
+
# button("Click Me For Fun!") => Creates the methods #click_me_for_fun and #click_me_for_fun_button
|
154
|
+
#
|
155
|
+
# The last parameter in the method is optional. Use it when
|
156
|
+
# you need the method name to be different from the text of
|
157
|
+
# the button--for example if the button text is unhelpful, like "Go", or else
|
158
|
+
# it changes (e.g., from "Update" to "Edit") and you don't
|
159
|
+
# want to have to go through all your data objects and step
|
160
|
+
# definitions to update them to the new method name.
|
161
|
+
#
|
162
|
+
# @example
|
163
|
+
# link("Click Me For Fun!", :click_me) => Creates the methods #click_me and #click_me_link
|
164
|
+
#
|
165
|
+
def button button_text, *alias_name
|
166
|
+
elementize(:button, button_text, *alias_name)
|
167
|
+
end
|
168
|
+
|
169
|
+
# TestFactory doesn't allow defining a method in a child class
|
170
|
+
# with the same name as one already defined in a parent class.
|
171
|
+
# The thinking here is: "Out of sight, out of mind." Meaning:
|
172
|
+
# you or a team mate might not know or have forgotten that a given
|
173
|
+
# element is already defined in a parent class, and so define it
|
174
|
+
# again. TestFactory's restriction is there to help prevent this.
|
175
|
+
#
|
176
|
+
# However, in some cases you may have a child page class with a
|
177
|
+
# special circumstance, where the parent class's version of the
|
178
|
+
# method really doesn't apply, and you want to use the same method
|
179
|
+
# name in this child class because, really, no other method name
|
180
|
+
# would fit quite as well.
|
181
|
+
#
|
182
|
+
# The #undefine method is for those rare cases. Note: If you start
|
183
|
+
# using this method a lot then you should consider that a sign
|
184
|
+
# that perhaps you're putting too many method definitions into
|
185
|
+
# parent page classes.
|
186
|
+
#
|
187
|
+
# @example
|
188
|
+
# undefine :status, :doc_id => Undefines the specified methods in the current class
|
189
|
+
#
|
190
|
+
def undefine *methods
|
191
|
+
methods.each{ |m| undef_method m }
|
192
|
+
end
|
193
|
+
|
194
|
+
def inherited klass
|
195
|
+
klass.instance_eval {
|
196
|
+
|
197
|
+
# Creates a method, #wait_for_ajax, usable in your Page Classes, that executes
|
198
|
+
# the 'jQuery.active' Javascript snippet each second until timeout.
|
199
|
+
#
|
200
|
+
# If timeout is exceeded, raises Watir::Wait::TimeoutError exception. The returned error
|
201
|
+
# message is customizable.
|
202
|
+
#
|
203
|
+
define_method 'wait_for_ajax' do |timeout=10, message|
|
204
|
+
timeout.times do
|
205
|
+
sleep 0.3
|
206
|
+
return true if @browser.execute_script('return jQuery.active').to_i == 0
|
207
|
+
sleep 0.7
|
208
|
+
end
|
209
|
+
raise Watir::Wait::TimeoutError, "Ajax calls continued beyond #{timeout} seconds. #{message}"
|
210
|
+
end
|
211
|
+
|
212
|
+
}
|
213
|
+
end
|
214
|
+
|
215
|
+
private
|
216
|
+
# A helper method that converts the passed string into snake case. See the StringFactory
|
217
|
+
# module for more info.
|
218
|
+
#
|
219
|
+
def damballa text
|
220
|
+
StringFactory.damballa(text)
|
221
|
+
end
|
222
|
+
|
223
|
+
def elementize type, text, *alias_name
|
224
|
+
hash={:link=>:text, :button=>:value}
|
225
|
+
if alias_name.empty?
|
226
|
+
el_name=damballa("#{text}_#{type}")
|
227
|
+
act_name=damballa(text)
|
228
|
+
else
|
229
|
+
el_name="#{alias_name[0]}_#{type}".to_sym
|
230
|
+
act_name=alias_name[0]
|
231
|
+
end
|
232
|
+
element(el_name) { |b| b.send(type, hash[type]=>text) }
|
233
|
+
action(act_name) { |b| b.send(type, hash[type]=>text).click }
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
end # PageFactory
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
# Copyright 2012-2014 The rSmart Group, Inc.
|
4
|
+
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
module StringFactory
|
17
|
+
|
18
|
+
LATIN_VOCABULARY = %w{alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat abbas abduco abeo abscido absconditus absens absorbeo absque abstergo absum abundans abutor accedo accendo acceptus accipio accommodo accusator acer acerbitas acervus acidus acies acquiro acsi adamo adaugeo addo adduco ademptio adeo adeptio adfectus adfero adficio adflicto adhaero adhuc adicio adimpleo adinventitias adipiscor adiuvo administratio admiratio admitto admoneo admoveo adnuo adopto adsidue adstringo adsuesco adsum adulatio adulescens adultus aduro advenio adversus advoco aedificium aeger aegre aegrotatio aegrus aeneus aequitas aequus aer aestas aestivus aestus aetas aeternus ager aggero aggredior agnitio agnosco ago ait aiunt alienus alii alioqui aliqua alius allatus alo alter altus alveus amaritudo ambitus ambulo amicitia amiculum amissio amita amitto amo amor amoveo amplexus amplitudo amplus ancilla angelus angulus angustus animadverto animi animus annus anser ante antea antepono antiquus aperio aperte apostolus apparatus appello appono appositus approbo apto aptus apud aqua ara aranea arbitro arbor arbustum arca arceo arcesso arcus argentum argumentum arguo arma armarium armo aro ars articulus artificiose arto arx ascisco ascit asper aspicio asporto assentator astrum atavus ater atqui atrocitas atrox attero attollo attonbitus auctor auctus audacia audax audentia audeo audio auditor aufero aureus auris aurum aut autem autus auxilium avaritia avarus aveho averto avoco baiulus balbus barba bardus basium beatus bellicus bellum bene beneficium benevolentia benigne bestia bibo bis blandior bonus bos brevis cado caecus caelestis caelum calamitas calcar calco calculus callide campana candidus canis canonicus canto capillus capio capitulus capto caput carbo carcer careo caries cariosus caritas carmen carpo carus casso caste casus catena caterva cattus cauda causa caute caveo cavus cedo celebrer celer celo cena cenaculum ceno censura centum cerno cernuus certe certo certus cervus cetera charisma chirographum cibo cibus cicuta cilicium cimentarius ciminatio cinis circumvenio cito civis civitas clam clamo claro clarus claudeo claustrum clementia clibanus coadunatio coaegresco coepi coerceo cogito cognatus cognomen cogo cohaero cohibeo cohors colligo colloco collum colo color coma combibo comburo comedo comes cometes comis comitatus commemoro comminor commodo communis comparo compello complectus compono comprehendo comptus conatus concedo concido conculco condico conduco confero confido conforto confugo congregatio conicio coniecto conitor coniuratio conor conqueror conscendo conservo considero conspergo constans consuasor contabesco contego contigo contra conturbo conventus convoco copia copiose cornu corona corpus correptius corrigo corroboro corrumpo coruscus cotidie crapula cras crastinus creator creber crebro credo creo creptio crepusculum cresco creta cribro crinis cruciamentum crudelis cruentus crur crustulum crux cubicularis cubitum cubo cui cuius culpa culpo cultellus cultura cum cunabula cunae cunctatio cupiditas cupio cuppedia cupressus cur cura curatio curia curiositas curis curo curriculum currus cursim curso cursus curto curtus curvo curvus custodia damnatio damno dapifer debeo debilito decens decerno decet decimus decipio decor decretum decumbo dedecor dedico deduco defaeco defendo defero defessus defetiscor deficio defigo defleo defluo defungo degenero degero degusto deinde delectatio delego deleo delibero delicate delinquo deludo demens demergo demitto demo demonstro demoror demulceo demum denego denique dens denuncio denuo deorsum depereo depono depopulo deporto depraedor deprecator deprimo depromo depulso deputo derelinquo derideo deripio desidero desino desipio desolo desparatus despecto despirmatio infit inflammatio paens patior patria patrocinor patruus pauci paulatim pauper pax peccatus pecco pecto pectus pecunia pecus peior pel ocer socius sodalitas sol soleo solio solitudo solium sollers sollicito solum solus solutio solvo somniculosus somnus sonitus sono sophismata sopor sordeo sortitus spargo speciosus spectaculum speculum sperno spero spes spiculum spiritus spoliatio sponte stabilis statim statua stella stillicidium stipes stips sto strenuus strues studio stultus suadeo suasoria sub subito subiungo sublime subnecto subseco substantia subvenio succedo succurro sufficio suffoco suffragium suggero sui sulum sum summa summisse summopere sumo sumptus supellex super suppellex supplanto suppono supra surculus surgo sursum suscipio suspendo sustineo suus synagoga tabella tabernus tabesco tabgo tabula taceo tactus taedium talio talis talus tam tamdiu tamen tametsi tamisium tamquam tandem tantillus tantum tardus tego temeritas temperantia templum temptatio tempus tenax tendo teneo tener tenuis tenus tepesco tepidus ter terebro teres terga tergeo tergiversatio tergo tergum termes terminatio tero terra terreo territo terror tersus tertius testimonium texo textilis textor textus thalassinus theatrum theca thema theologus thermae thesaurus thesis thorax thymbra thymum tibi timidus timor titulus tolero tollo tondeo tonsor torqueo torrens tot totidem toties totus tracto trado traho trans tredecim tremo trepide tres tribuo tricesimus triduana triginta tripudio tristis triumphus trucido truculenter tubineus tui tum tumultus tunc turba turbo turpe turpis tutamen tutis tyrannus uberrime ubi ulciscor ullus ulterius ultio ultra umbra umerus umquam una unde undique universe unus urbanus urbs uredo usitas usque ustilo ustulo usus uter uterque utilis utique utor utpote utrimque utroque utrum uxor vaco vacuus vado vae valde valens valeo valetudo validus vallum vapulus varietas varius vehemens vel velociter velum velut venia venio ventito ventosus ventus venustas ver verbera verbum vere verecundia vereor vergo veritas vero versus verto verumtamen verus vesco vesica vesper vespillo vester vestigium vestrum vetus via vicinus vicissitudo victoria victus videlicet video viduata viduo vigilo vigor vilicus vilis vilitas villa vinco vinculum vindico vinitor vinum vir virga virgo viridis viriliter virtus vis viscus vita vitiosus vitium vito vivo vix vobis vociferor voco volaticus volo volubilis voluntarius volup volutabrum volva vomer vomica vomito vorago vorax voro vos votum voveo vox vulariter vulgaris vulgivagus vulgo vulgus vulnero vulnus vulpes vulticulus vultuosus xiphias}
|
19
|
+
|
20
|
+
# A random string creator that draws from all printable ASCII characters
|
21
|
+
# from 33 to 128. Default length is 10 characters.
|
22
|
+
# @param length [Integer] The count of characters in the string
|
23
|
+
# @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will
|
24
|
+
# be longer by the size of the pre-pended string.
|
25
|
+
#
|
26
|
+
def random_string(length=10, s="")
|
27
|
+
length.enum_for(:times).inject(s) { s << rand(93) + 33 }
|
28
|
+
end
|
29
|
+
|
30
|
+
# A random string creator that draws from all printable ASCII and High ASCII characters
|
31
|
+
# from 33 to 256. Default length is 10 characters.
|
32
|
+
# @param length [Integer] The count of characters in the string
|
33
|
+
# @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will be
|
34
|
+
# longer by the length of the pre-pended string.
|
35
|
+
#
|
36
|
+
def random_high_ascii(length=10, s="")
|
37
|
+
length.enum_for(:times).inject(s) { s << rand(223) + 33 }
|
38
|
+
end
|
39
|
+
|
40
|
+
# A "friendlier" random string generator. No characters need to be escaped for valid URLs.
|
41
|
+
# Uses no Reserved or "Unsafe" characters.
|
42
|
+
# Also excludes the comma, the @ sign and the plus sign. Default length is 10 characters.
|
43
|
+
#
|
44
|
+
def random_nicelink(length=10)
|
45
|
+
chars = %w{a b c d e f g h j k m n p q r s t u v w x y z A B C D E F G H J K L M N P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 _ - .}
|
46
|
+
(0...length).map { chars[rand(chars.size)]}.join
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns a string that is properly formatted like an email address.
|
50
|
+
# The string returned defaults to 268 characters long.
|
51
|
+
# @param x [Integer] This is not the length of the whole string, but only of the "name" portion of the email, minus 2.
|
52
|
+
#
|
53
|
+
def random_email(x=62)
|
54
|
+
x > 62 ? x=62 : x=x
|
55
|
+
chars = %w{a b c d e f g h j k m n p q r s t u v w x y z A B C D E F G H J K L M N P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % & ' * + - / = ? ^ _ ` { | } ~}
|
56
|
+
random_alphanums(1) + (0...x).map { chars[rand(chars.size)]}.join + random_alphanums(1) + "@" + random_alphanums(60) + ".com"
|
57
|
+
end
|
58
|
+
|
59
|
+
# A random string generator that uses all characters
|
60
|
+
# available on an American Qwerty keyboard.
|
61
|
+
# @param length [Integer] The count of characters in the string
|
62
|
+
# @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will be longer by the length of the pre-pended string.
|
63
|
+
# @example
|
64
|
+
# random_alphanums_plus(20, 'pre-') => 'pre-PUm,Rv:(LUFt4t@u29f%'
|
65
|
+
def random_alphanums_plus(length=10, s="")
|
66
|
+
chars = %w{ a b c d e f g h j k m n p q r s t u v w x y z A B C D E F G H J K L M N P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ` ~ ! @ # $ % ^ & * ( ) _ + - = { } [ ] \\ : " ; ' < > ? , . / }
|
67
|
+
length.times { s << chars[rand(chars.size)] }
|
68
|
+
s.to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
# A random string generator that uses only letters and numbers in the string. Default length is 10 characters.
|
72
|
+
# @param length [Integer] The count of characters in the string
|
73
|
+
# @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will be longer by the length of the pre-pended string.
|
74
|
+
#
|
75
|
+
def random_alphanums(length=10, s="")
|
76
|
+
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
|
77
|
+
length.times { s << chars[rand(chars.size)] }
|
78
|
+
s.to_s
|
79
|
+
end
|
80
|
+
|
81
|
+
# A random string generator that uses only lower case letters.
|
82
|
+
# @param length [Integer] The count of characters in the string
|
83
|
+
# @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will still be as specified
|
84
|
+
#
|
85
|
+
def random_letters(length=10, s="")
|
86
|
+
chars = 'abcdefghjkmnpqrstuvwxyz'
|
87
|
+
length.times { s << chars[rand(chars.size)] }
|
88
|
+
s.to_s
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns a String containing a number with two decimal places, for creation
|
92
|
+
# of dollar values.
|
93
|
+
# @param max [Integer] The highest allowable dollar amount
|
94
|
+
# @example
|
95
|
+
# random_dollar_value(100) => '44.89'
|
96
|
+
#
|
97
|
+
def random_dollar_value(max)
|
98
|
+
"#{rand(max)}.#{'%02d'%rand(99)}"
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns a block of text (of the specified type, see below) containing
|
102
|
+
# the specified number of "words" (each containing between 1 and 16 chars)
|
103
|
+
# randomly spread across the specified number of lines (note that
|
104
|
+
# the method does not allow the line count to be larger than
|
105
|
+
# the word count and will "fix" it if it is).
|
106
|
+
#
|
107
|
+
# @param word_count [Integer] The count of "words" in the string, separated by spaces or line feeds. If no parameters are provided, the method will return two alphanumeric "words" on two lines.
|
108
|
+
# @param line_count [Integer] The count of line feeds that will be randomly placed throughout the string
|
109
|
+
# @param char_type [:symbol] Determines the character content of the string.
|
110
|
+
# :alpha => "Alphanumeric" - Uses the #random_alphanums method
|
111
|
+
# :string => uses the #random_string method, so chars 33 through 128 will be included
|
112
|
+
# :ascii => All ASCII chars from 33 to 256 are fair game -> uses #random_high_ascii
|
113
|
+
# :lorem => Will generate a pseudo-lorem-ipsum block of text using the LATIN_VOCABULARY constant as the source
|
114
|
+
#
|
115
|
+
def random_multiline(word_count=2, line_count=2, char_type=:alpha)
|
116
|
+
char_methods = {:alpha=>"random_alphanums(rand(16)+1)", :string=>"random_string(rand(16)+1)", :ascii=>"random_high_ascii(rand(16)+1)", :lorem=>"LATIN_VOCABULARY[rand(LATIN_VOCABULARY.length)]"}
|
117
|
+
if line_count > word_count
|
118
|
+
line_count = word_count - 1
|
119
|
+
end
|
120
|
+
words = []
|
121
|
+
non_words = []
|
122
|
+
word_count.times { words << eval(char_methods[char_type]) } # creating the words, adding to the array
|
123
|
+
(line_count - 1).times { non_words << "\n" } # adding the number of line feeds
|
124
|
+
unless word_count==line_count
|
125
|
+
(word_count - line_count - 1).times { non_words << " " } # adding the right number of spaces
|
126
|
+
end
|
127
|
+
non_words.shuffle! # Have to shuffle the line feeds around!
|
128
|
+
array = words.zip(non_words)
|
129
|
+
array.flatten!
|
130
|
+
array.join("")
|
131
|
+
end
|
132
|
+
|
133
|
+
# Picks at random from the list of XSS test strings, using
|
134
|
+
# the provided number as size of the list to choose from.
|
135
|
+
# It will randomly pre-pend the string with HTML closing tags.
|
136
|
+
#
|
137
|
+
# The strings are organized by length, with the shorter ones
|
138
|
+
# first. There are 102 strings.
|
139
|
+
# @param number [Integer] Should be a number between 1 and 102
|
140
|
+
#
|
141
|
+
def random_xss_string(number=102)
|
142
|
+
number > 102 ? number = 102 : number
|
143
|
+
xss = ["<PLAINTEXT>", "\\\";alert('XSS');//", "'';!--\"<XSS>=&{()}", "<IMG SRC=\"mocha:alert('XSS')\">", "<BODY ONLOAD=alert('XSS')>", "<BODY ONLOAD =alert('XSS')>", "<BR SIZE=\"&{alert('XSS')}\">", "¼script¾alert(¢XSS¢)¼/script¾", "<IMG SRC=\"livescript:alert('XSS')\">", "<SCRIPT SRC=//ha.ckers.org/.j>", "<IMG SRC=javascript:alert('XSS')>", "<IMG SRC=JaVaScRiPt:alert('XSS')>", "<<SCRIPT>alert(\"XSS\");//<</SCRIPT>", "<IMG SRC=\"javascript:alert('XSS')\"", "<IMG SRC='vbscript:msgbox(\"XSS\")'>", "<A HREF=\"http://1113982867/\">XSS</A>", "<IMG SRC=\"javascript:alert('XSS');\">", "<IMG SRC=\"jav\tascript:alert('XSS');\">", "<XSS STYLE=\"behavior: url(xss.htc);\">", "</TITLE><SCRIPT>alert(\"XSS\");</SCRIPT>", "<IMG DYNSRC=\"javascript:alert('XSS')\">", "<A HREF=\"http://66.102.7.147/\">XSS</A>", "<IMG LOWSRC=\"javascript:alert('XSS')\">", "<BGSOUND SRC=\"javascript:alert('XSS');\">", "<BASE HREF=\"javascript:alert('XSS');//\">", "<IMG \"\"\"><SCRIPT>alert(\"XSS\")</SCRIPT>\">", "<SCRIPT>a=/XSS/ alert(a.source)</SCRIPT>", "<IMG SRC=\"jav
ascript:alert('XSS');\">", "<IMG SRC=\"jav
ascript:alert('XSS');\">", "<XSS STYLE=\"xss:expression(alert('XSS'))\">", "<IMG SRC=\"jav	ascript:alert('XSS');\">", "<SCRIPT SRC=http://ha.ckers.org/xss.js?<B>", "<IMG SRC=\"  javascript:alert('XSS');\">", "<IMG SRC=javascript:alert("XSS")>", "<BODY BACKGROUND=\"javascript:alert('XSS')\">", "<TABLE BACKGROUND=\"javascript:alert('XSS')\">", "<DIV STYLE=\"width: expression(alert('XSS'));\">", "<TABLE><TD BACKGROUND=\"javascript:alert('XSS')\">", "<iframe src=http://ha.ckers.org/scriptlet.html <", "<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>", "<IFRAME SRC=\"javascript:alert('XSS');\"></IFRAME>", "<A HREF=\"http://0x42.0x0000066.0x7.0x93/\">XSS</A>", "<IMG STYLE=\"xss:expr/*XSS*/ession(alert('XSS'))\">", "<A HREF=\"http://0102.0146.0007.00000223/\">XSS</A>", "<IMG SRC=`javascript:alert(\"RSnake says, 'XSS'\")`>", "<SCRIPT/SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<SCRIPT SRC=\"http://ha.ckers.org/xss.jpg\"></SCRIPT>", "<STYLE TYPE=\"text/javascript\">alert('XSS');</STYLE>", "<BODY onload!\#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>", "<INPUT TYPE=\"IMAGE\" SRC=\"javascript:alert('XSS');\">", "<STYLE>@im\\port'\\ja\\vasc\\ript:alert(\"XSS\")';</STYLE>", "<STYLE>@import'http://ha.ckers.org/xss.css';</STYLE>", "<SCRIPT/XSS SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<? echo('<SCR)'; echo('IPT>alert(\"XSS\")</SCRIPT>'); ?>", "<SCRIPT =\">\" SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<LINK REL=\"stylesheet\" HREF=\"javascript:alert('XSS');\">", "<SCRIPT a=`>` SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<SCRIPT a=\">\" SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<LAYER SRC=\"http://ha.ckers.org/scriptlet.html\"></LAYER>", "<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>", "<SCRIPT \"a='>'\" SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<LINK REL=\"stylesheet\" HREF=\"http://ha.ckers.org/xss.css\">", "<SCRIPT a=\">'>\" SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<SCRIPT a=\">\" '' SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<FRAMESET><FRAME SRC=\"javascript:alert('XSS');\"></FRAMESET>", "<DIV STYLE=\"background-image: url(javascript:alert('XSS'))\">", "perl -e 'print \"<SCR\\0IPT>alert(\\\"XSS\\\")</SCR\\0IPT>\";' > out", "<IMG SRC = \" j a v a s c r i p t : a l e r t ( ' X S S ' ) \" >", "Redirect 302 /a.jpg http://www.rsmart.com/admin.asp&deleteuser", "perl -e 'print \"<IMG SRC=java\\0script:alert(\\\"XSS\\\")>\";' > out", "<!--[if gte IE 4]> <SCRIPT>alert('XSS');</SCRIPT> <![endif]-->", "<DIV STYLE=\"background-image: url(javascript:alert('XSS'))\">", "<A HREF=\"http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D\">XSS</A>", "<META HTTP-EQUIV=\"refresh\" CONTENT=\"0;url=javascript:alert('XSS');\">", "a=\"get\"; b=\"URL(\\\"\"; c=\"javascript:\"; d=\"alert('XSS');\\\")\"; eval(a+b+c+d);", "<STYLE>BODY{-moz-binding:url(\"http://ha.ckers.org/xssmoz.xml#xss\")}</STYLE>", "<EMBED SRC=\"http://ha.ckers.org/xss.swf\" AllowScriptAccess=\"always\"></EMBED>", "<STYLE type=\"text/css\">BODY{background:url(\"javascript:alert('XSS')\")}</STYLE>", "<STYLE>li {list-style-image: url(\"javascript:alert('XSS')\");}</STYLE><UL><LI>XSS", "<META HTTP-EQUIV=\"Link\" Content=\"<http://ha.ckers.org/xss.css>; REL=stylesheet\">", "<META HTTP-EQUIV=\"refresh\" CONTENT=\"0; URL=http://;URL=javascript:alert('XSS');\">", "<OBJECT TYPE=\"text/x-scriptlet\" DATA=\"http://ha.ckers.org/scriptlet.html\"></OBJECT>", "<SCRIPT>document.write(\"<SCRI\");</SCRIPT>PT SRC=\"http://ha.ckers.org/xss.js\"></SCRIPT>", "<STYLE>.XSS{background-image:url(\"javascript:alert('XSS')\");}</STYLE><A CLASS=XSS></A>", "<XML SRC=\"xsstest.xml\" ID=I></XML> <SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>", "<META HTTP-EQUIV=\"Set-Cookie\" Content=\"USERID=<SCRIPT>alert('XSS')</SCRIPT>\">", "exp/*<A STYLE='no\\xss:noxss(\"*//*\"); xss:ex/*XSS*//*/*/pression(alert(\"XSS\"))'>", "<META HTTP-EQUIV=\"refresh\" CONTENT=\"0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K\">", "<!--#exec cmd=\"/bin/echo '<SCR'\"--><!--#exec cmd=\"/bin/echo 'IPT SRC=http://ha.ckers.org/xss.js></SCRIPT>'\"-->", "<OBJECT classid=clsid:ae24fdae-03c6-11d1-8b76-0080c744f389><param name=url value=javascript:alert('XSS')></OBJECT>", "<HTML xmlns:xss> <?import namespace=\"xss\" implementation=\"http://ha.ckers.org/xss.htc\"> <xss:xss>XSS</xss:xss> </HTML>", "<IMG SRC=javascript:alert('XSS')>", "<HEAD><META HTTP-EQUIV=\"CONTENT-TYPE\" CONTENT=\"text/html; charset=UTF-7\"> </HEAD>+ADw-SCRIPT+AD4-alert('XSS');+ADw-/SCRIPT+AD4-", "<IMG SRC=javascript:alert('XSS')>", "<XML ID=I><X><C><![CDATA[<IMG SRC=\"javas]]><![CDATA[cript:alert('XSS');\">]]> </C></X></xml><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>", "<XML ID=\"xss\"><I><B><IMG SRC=\"javas<!-- -->cript:alert('XSS')\"></B></I></XML> <SPAN DATASRC=\"#xss\" DATAFLD=\"B\" DATAFORMATAS=\"HTML\"></SPAN>", "<DIV STYLE=\"background-image:\\0075\\0072\\006C\\0028'\\006a\\0061\\0076\\0061\\0073\\0063\\0072\\0069\\0070\\0074\\003a\\0061\\006c\\0065\\0072\\0074\\0028.1027\\0058.1053\\0053\\0027\\0029'\\0029\">", "<IMG SRC=javascript:alert('XSS')>", "';alert(String.fromCharCode(88,83,83))//\\';alert(String.fromCharCode(88,83,83))//\";alert(String.fromCharCode(88,83,83))//\\\";alert(String.fromCharCode(88,83,83))//--></SCRIPT>\">'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>", "<HTML><BODY> <?xml:namespace prefix=\"t\" ns=\"urn:schemas-microsoft-com:time\"> <?import namespace=\"t\" implementation=\"#default#time2\"> <t:set attributeName=\"innerHTML\" to=\"XSS<SCRIPT DEFER>alert("XSS")</SCRIPT>\"> </BODY></HTML>", "<EMBED SRC=\"data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==\" type=\"image/svg+xml\" AllowScriptAccess=\"always\"></EMBED>"]
|
144
|
+
prepend=[ %|"|, %||, %|">|, %|>| ]
|
145
|
+
"#{prepend[rand(prepend.length)]} #{xss[rand(number)]}"
|
146
|
+
end
|
147
|
+
|
148
|
+
# Returns a random hex string that matches an HTML color value.
|
149
|
+
#
|
150
|
+
def random_hex_color
|
151
|
+
"#"+("%06x" % (rand * 0xffffff)).upcase
|
152
|
+
end
|
153
|
+
|
154
|
+
# Converts a string to a symbol made up of snake case. Spaces and dashes are changed to underscore. Special characters are removed.
|
155
|
+
# @param text [String] The text to be converted to snake case.
|
156
|
+
# @example
|
157
|
+
# damballa("A String of Fun Stuff (for you)") => :a_string_of_fun_stuff_for_you
|
158
|
+
#
|
159
|
+
def damballa(text)
|
160
|
+
text.gsub(/([+=|\\\.,~@#'"\?`!\{\}\[\]\$%\^&\*\(\)])/, "").
|
161
|
+
gsub(/([-\/\s])/,"_").
|
162
|
+
downcase.
|
163
|
+
to_sym
|
164
|
+
end
|
165
|
+
module_function :damballa
|
166
|
+
|
167
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module TestFactory
|
2
|
+
|
3
|
+
def self.binary_transform(var)
|
4
|
+
case(var)
|
5
|
+
when nil
|
6
|
+
nil
|
7
|
+
when /yes/i, /on/i, :set, true
|
8
|
+
:set
|
9
|
+
when /no/i, /off/i, :clear, false
|
10
|
+
:clear
|
11
|
+
else
|
12
|
+
raise "The value of your DataObject's checkbox/radio ('#{var}') instance variable is not supported.\nPlease make sure the value conforms to one of the following patterns:\n\n - :set or :clear (Symbol)\n - 'yes', 'no', 'on', or 'off' (String; case insensitive)\n - true or false (Boolean)"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'kuali-test-factory'
|
3
|
+
s.version = '0.5.3.1'
|
4
|
+
s.summary = %q{rSmart's framework for creating automated testing scripts}
|
5
|
+
s.description = %q{This gem provides a set of modules and methods to help quickly and DRYly create a test automation framework using Ruby and Watir (or watir-webdriver).}
|
6
|
+
s.files = Dir.glob("**/**/**")
|
7
|
+
s.test_files = Dir.glob("test/*test_rb")
|
8
|
+
s.authors = ['Abraham Heward']
|
9
|
+
s.email = %w{aheward@rsmart.com}
|
10
|
+
s.homepage = 'https://github.com/kuali'
|
11
|
+
s.add_dependency 'watir-webdriver', '>= 0.6.4'
|
12
|
+
s.required_ruby_version = '>= 1.9.2'
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kuali-test-factory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Abraham Heward
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2014-09-19 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: watir-webdriver
|
16
|
+
prerelease: false
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.6.4
|
22
|
+
type: :runtime
|
23
|
+
version_requirements: *id001
|
24
|
+
description: This gem provides a set of modules and methods to help quickly and DRYly create a test automation framework using Ruby and Watir (or watir-webdriver).
|
25
|
+
email:
|
26
|
+
- aheward@rsmart.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- COPYING
|
35
|
+
- Gemfile
|
36
|
+
- Gemfile.lock
|
37
|
+
- LICENSE
|
38
|
+
- README.md
|
39
|
+
- lib/test-factory.rb
|
40
|
+
- lib/test-factory/collections_factory.rb
|
41
|
+
- lib/test-factory/core_ext.rb
|
42
|
+
- lib/test-factory/data_factory.rb
|
43
|
+
- lib/test-factory/date_factory.rb
|
44
|
+
- lib/test-factory/foundry.rb
|
45
|
+
- lib/test-factory/gem_ext.rb
|
46
|
+
- lib/test-factory/page_factory.rb
|
47
|
+
- lib/test-factory/string_factory.rb
|
48
|
+
- lib/test-factory/test_factory.rb
|
49
|
+
- test-factory.gemspec
|
50
|
+
homepage: https://github.com/kuali
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
metadata: {}
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.9.2
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 2.4.1
|
74
|
+
signing_key:
|
75
|
+
specification_version: 4
|
76
|
+
summary: rSmart's framework for creating automated testing scripts
|
77
|
+
test_files: []
|
78
|
+
|