taft 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +9 -3
- data/examples/ruby/rs/framework/red_sky/api_helpers/general.rb +140 -0
- data/examples/ruby/rs/framework/red_sky/api_helpers/rest.rb +249 -0
- data/examples/ruby/rs/framework/red_sky/ui_helpers/ui_general.rb +36 -0
- data/examples/ruby/rs/framework/red_sky/watir/custom/all.rb +4 -0
- data/examples/ruby/rs/framework/red_sky/watir/custom/rs_custom.rb +32 -0
- data/examples/ruby/rs/framework/red_sky/watir/flows/flow_objects.rb +466 -0
- data/examples/ruby/rs/framework/red_sky/watir/flows/rs_flow_names.rb +15 -0
- data/examples/ruby/rs/framework/red_sky/watir/flows/rs_flows.rb +117 -0
- data/examples/ruby/rs/framework/red_sky/watir/pages/page_objects.rb +166 -0
- data/examples/ruby/rs/framework/red_sky/watir/pages/rs_pages.rb +68 -0
- data/examples/ruby/rs/framework/red_sky.rb +12 -0
- data/examples/ruby/rs/lib/config/red_sky_config.rb +27 -0
- data/examples/ruby/rs/lib/config/runtime_constants.rb +20 -0
- data/examples/ruby/rs/lib/red_sky_test_case.rb +218 -0
- data/examples/ruby/rs/tests/v1/tc_r001_01_an_example_test.rb +112 -0
- data/examples/ruby/rs/tests/v1/tc_r001_01_google_search.rb +64 -0
- data/lib/taft_files/framework/zznamezz/api_helpers/general.rb +11 -11
- data/lib/taft_files/framework/zznamezz/ui_helpers/ui_general.rb +26 -0
- data/lib/taft_files/framework/zznamezz/watir/custom/all.rb +4 -0
- data/lib/taft_files/framework/zznamezz/watir/custom/xxabbrevxx_custom.rb +32 -0
- data/lib/taft_files/framework/zznamezz/watir/flows/flow_objects.rb +466 -0
- data/lib/taft_files/framework/zznamezz/watir/flows/xxabbrevxx_flow_names.rb +15 -0
- data/lib/taft_files/framework/zznamezz/watir/flows/xxabbrevxx_flows.rb +117 -0
- data/lib/taft_files/framework/zznamezz/watir/pages/page_objects.rb +166 -0
- data/lib/taft_files/framework/zznamezz/watir/pages/xxabbrevxx_pages.rb +101 -0
- data/lib/taft_files/framework/zznamezz.rb +4 -0
- data/lib/taft_files/lib/config/runtime_constants.rb +5 -1
- data/lib/taft_files/lib/config/zznamezz_config.rb +7 -2
- data/lib/taft_files/lib/zznamezz_test_case.rb +43 -42
- data/lib/taft_files/tests/v1/tc_r001_01_an_example_test.rb +1 -1
- data/taft.gemspec +4 -4
- metadata +28 -5
@@ -0,0 +1,466 @@
|
|
1
|
+
# A class defining the series of Flow classes & helpers
|
2
|
+
|
3
|
+
# TODO define some base class/classes. Must be scope here for consolidation through inheritance?
|
4
|
+
|
5
|
+
#require 'minitest/unit' # needed? # TODO use test-unit, or convert everything else to minitest
|
6
|
+
|
7
|
+
#class FlowObjects
|
8
|
+
# attr_accessor :flows
|
9
|
+
#
|
10
|
+
# def initialize
|
11
|
+
# @flows = [] # an array of Flow objects
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def add_flow(flow)
|
15
|
+
# @flows << flow
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # TODO needed?
|
19
|
+
# def ==(o)
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # TODO needed?
|
23
|
+
# def to_s
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
#end
|
27
|
+
|
28
|
+
# A class defining a flow. This contains the fields to be interacted with, in their proper sequence, with valid or
|
29
|
+
# invalid values
|
30
|
+
class Flow
|
31
|
+
|
32
|
+
attr_accessor :name
|
33
|
+
attr_accessor :flow_map # some collection of Flow, FlowField & other Flow-type objects # TODO
|
34
|
+
|
35
|
+
def initialize(name)
|
36
|
+
@name = name
|
37
|
+
@flow_map = []
|
38
|
+
end
|
39
|
+
|
40
|
+
def add(flow_item)
|
41
|
+
@flow_map << flow_item
|
42
|
+
end
|
43
|
+
|
44
|
+
# TODO needed?
|
45
|
+
def ==(o)
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
s = ""
|
50
|
+
s += "Flow name : #{@name}. Flow map size : #{@flow_map.size}. Flow items :"
|
51
|
+
@flow_map.each {|f| s += "\n\t#{f.to_s}" }
|
52
|
+
s
|
53
|
+
end
|
54
|
+
|
55
|
+
# Executes the flow
|
56
|
+
# Takes symbols which act as flags :
|
57
|
+
# success_sym - set to :success for a valid set of inputs, set to :fail for one or more of the inputs to be invalid and
|
58
|
+
# the flow to fail
|
59
|
+
# mandatory_fields_sym - set to :mandatory to only involve the mandatory fields, set to :all_fields to use all defined
|
60
|
+
# fields in the flow
|
61
|
+
# custom_values_hash - hash of values some/all of the fields must take (e.g. creating a new record with a specific foreign key)
|
62
|
+
# keys are field names (as defined in CeresFlows) in either symbol or string form, values are the values the fields should take
|
63
|
+
# TODO : don't want to have to pass in browser each time
|
64
|
+
def execute(browser, custom_values_hash = {}, success_sym = :success, mandatory_fields_sym = :mandatory)
|
65
|
+
report = nil # if report is still nil at the end of the method, generate a dummy one
|
66
|
+
return_value = nil # default value that will be fed into the report # TODO needs to be an array? Or hold multiple
|
67
|
+
# values?
|
68
|
+
# pass = true
|
69
|
+
# all = true
|
70
|
+
case success_sym
|
71
|
+
when :success
|
72
|
+
pass = true
|
73
|
+
when :fail
|
74
|
+
pass = false
|
75
|
+
else
|
76
|
+
raise "Did not understand value '#{success_sym.inspect}' for success_sym"
|
77
|
+
end
|
78
|
+
|
79
|
+
case mandatory_fields_sym
|
80
|
+
when :mandatory
|
81
|
+
all = false
|
82
|
+
when :all_fields
|
83
|
+
all = true
|
84
|
+
else
|
85
|
+
raise "Did not understand value '#{mandatory_fields_sym.inspect}' for mandatory_fields_sym"
|
86
|
+
end
|
87
|
+
|
88
|
+
@flow_map.each do |flow_item|
|
89
|
+
case flow_item
|
90
|
+
when Flow # flows can contain sub-flows
|
91
|
+
flow_item.execute(browser, custom_values_hash, success_sym, mandatory_fields_sym) # call recursively
|
92
|
+
when FlowPrecondition
|
93
|
+
# TODO : find flow from name & execute it
|
94
|
+
flow_item.execute_precondition_flow(custom_values_hash)
|
95
|
+
when FlowLink
|
96
|
+
# debugging
|
97
|
+
# puts "Executing #{flow_item.name}"
|
98
|
+
# puts browser.url
|
99
|
+
|
100
|
+
browser.link(:id => flow_item.name).click
|
101
|
+
|
102
|
+
sleep 1 # TODO determine expected page, call page.wait_until_displayed
|
103
|
+
when FlowField
|
104
|
+
puts "Now executing field #{flow_item.to_s}"
|
105
|
+
next if all == false && flow_item.mandatory == false # skip optional fields if instructed
|
106
|
+
|
107
|
+
field = nil
|
108
|
+
|
109
|
+
# TODO : look up field identification parameters (e.g. :id => something) from field definition in rs_pages
|
110
|
+
# The linkage should be that the NAME of the rs_page field (e.g. page.add_field("role", :list, :id, "user_role") )
|
111
|
+
# matches the NAME of the flow_item. We therefore use flow_item.name to track down the field identification parameters
|
112
|
+
# stored in the field definition in rs_pages (in this example, :id, "user_role" )
|
113
|
+
# Until this is done, flow_item.name needs to match the rs_pages field ident param.
|
114
|
+
|
115
|
+
case flow_item.type
|
116
|
+
# TODO only have this case statement determine field type, then pass it into one eval line instead of one
|
117
|
+
# line per type
|
118
|
+
# Type field completion may differ by more than just their field type...
|
119
|
+
|
120
|
+
when :string
|
121
|
+
field = browser.text_field(:id => flow_item.name)
|
122
|
+
when :p
|
123
|
+
field = browser.p(:id => flow_item.name)
|
124
|
+
when :div
|
125
|
+
field = browser.div(:id => flow_item.name)
|
126
|
+
when :checkbox
|
127
|
+
field = browser.input(:id => flow_item.name)
|
128
|
+
when :list
|
129
|
+
# field = browser.select_list(:id => flow_item.name)
|
130
|
+
field = browser.select(:id => flow_item.name)
|
131
|
+
when :button
|
132
|
+
# buttons only have one function - to be pressed, not to be read or written to
|
133
|
+
browser.button(:id => flow_item.name).click
|
134
|
+
else
|
135
|
+
raise "Cannot execute #{flow_item.class} of type #{flow_item.type}"
|
136
|
+
end
|
137
|
+
case flow_item.operation
|
138
|
+
when :read
|
139
|
+
case flow_item.type
|
140
|
+
when :string, :checkbox, :list, :p, :div
|
141
|
+
# puts "value : #{field.value}"
|
142
|
+
# puts "text : #{field.text}"
|
143
|
+
return_value = field.value
|
144
|
+
return_value = field.text if return_value == "" # p needs .text
|
145
|
+
# puts "return_value : #{return_value}"
|
146
|
+
end
|
147
|
+
when :write
|
148
|
+
# get valid value from hash, if it has been specified
|
149
|
+
value = custom_values_hash[flow_item.name.to_sym].to_s # flow_item.name is defined in rs_flows to be a string; it is nicer if the custom hash keys are symbols, but we then need to convert them
|
150
|
+
value = flow_item.random_valid_value if value == nil
|
151
|
+
# value = flow_item.random_invalid_value if invalid # TODO enable
|
152
|
+
case flow_item.type
|
153
|
+
when :string, :checkbox
|
154
|
+
field.set(value)
|
155
|
+
when :list
|
156
|
+
field.select(value)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
when FlowVerify
|
160
|
+
name = "verify"
|
161
|
+
verify_flow = Flow.new(name)
|
162
|
+
verify_flow.add(flow_item.flow_field)
|
163
|
+
# call recursively, have it generate a Report, perform validation against the Report
|
164
|
+
report = verify_flow.execute(browser)
|
165
|
+
#puts "report : #{report}"
|
166
|
+
value = report.value
|
167
|
+
flow_item.verify(value)
|
168
|
+
return_value = "FlowVerify passed : #{flow_item}"
|
169
|
+
when FlowReport # not yet in use - no FlowReports have been defined in rs_flows
|
170
|
+
report = flow_item.generate_report
|
171
|
+
else
|
172
|
+
raise "Cannot execute flow item of class #{flow_item.class}"
|
173
|
+
end # end case
|
174
|
+
end # end .each
|
175
|
+
if report == nil # if report is still nil at the end of the method, generate a dummy one
|
176
|
+
# return_value =
|
177
|
+
report = FlowReport.new(return_value)
|
178
|
+
end
|
179
|
+
report
|
180
|
+
end # end execute
|
181
|
+
|
182
|
+
end # end class
|
183
|
+
|
184
|
+
# A class defining a flow that must be executed as a precondition to the flow this object belongs to
|
185
|
+
class FlowPrecondition
|
186
|
+
|
187
|
+
attr_accessor :precondition_flow # precondition_flow is the name of the precondition flow that must be executed
|
188
|
+
|
189
|
+
def initialize(precondition_flow)
|
190
|
+
@precondition_flow = precondition_flow
|
191
|
+
end
|
192
|
+
|
193
|
+
def to_s
|
194
|
+
s = ""
|
195
|
+
s += "Precondition Flow : #{@precondition_flow}"
|
196
|
+
s
|
197
|
+
end
|
198
|
+
|
199
|
+
# TODO : need success & madatory field flags here?
|
200
|
+
def execute_precondition_flow(custom_values_hash = {})
|
201
|
+
# find flow from name
|
202
|
+
# TODO : flows all stored in @flow (CeresFlow.new()). Gaining access to this feels wrong...
|
203
|
+
|
204
|
+
# execute flow
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
# A class defining a navigation step that is needed as part of a flow. These assume that their navigation is done via
|
211
|
+
# links, not buttons/divs/etc.
|
212
|
+
class FlowLink
|
213
|
+
|
214
|
+
attr_accessor :name, :parent_page, :destination, :verification # parent_page is the page within which the desired link
|
215
|
+
# can be found
|
216
|
+
# destination is the name of the page that the browser will arrive at after performing this navigation.
|
217
|
+
# verification is a FlowVerify object that is defined such that it can only pass if it matches the defined field on the
|
218
|
+
# destination page
|
219
|
+
# TODO enable mechanism such that one can simply state flow.goto(destination) and all flows will be scanned for the
|
220
|
+
# flow that will take us there, then that flow will be executed.
|
221
|
+
|
222
|
+
def initialize(destination, name, parent_page)
|
223
|
+
@destination = destination
|
224
|
+
@name = name
|
225
|
+
@parent_page = parent_page
|
226
|
+
end
|
227
|
+
|
228
|
+
def to_s
|
229
|
+
s = ""
|
230
|
+
s += "Flow destination : #{@destination}. Link ID : #{@name}. Parent page : #{@parent_page}"
|
231
|
+
s
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
# A class defining a field that is interacted with in some way as part of a flow.
|
237
|
+
# Valid types: :string (a text field); :button (a button); :link (a link); :list (a select list); :checkbox (a checkbox)
|
238
|
+
# TODO still want link to be valid here? What about FlowLink?
|
239
|
+
class FlowField
|
240
|
+
|
241
|
+
attr_accessor :name, :type, :operation, :mandatory, :size, :custom_valid_value_definition, :custom_invalid_value_definition
|
242
|
+
|
243
|
+
def initialize(name, type = :string, operation = :write, mandatory = true, size = nil, custom_valid_value_definition = nil, custom_invalid_value_definition = nil)
|
244
|
+
raise "FlowField name must be a string" unless name.class == String
|
245
|
+
@name = name
|
246
|
+
@type = type
|
247
|
+
@operation = operation
|
248
|
+
raise "Cannot define FlowField #{@name} with operation of #{@operation.inspect}" unless @operation == :read || @operation == :write
|
249
|
+
@mandatory = mandatory
|
250
|
+
if size == nil
|
251
|
+
@size = get_default_size
|
252
|
+
else
|
253
|
+
@size = size
|
254
|
+
end
|
255
|
+
|
256
|
+
custom_valid_value_definition = nil
|
257
|
+
custom_invalid_value_definition = nil
|
258
|
+
|
259
|
+
check_valid_type
|
260
|
+
|
261
|
+
# TODO custom_valid_value_definition, etc
|
262
|
+
case custom_valid_value_definition
|
263
|
+
when NilClass
|
264
|
+
# take default valid field def based on @type
|
265
|
+
when Symbol
|
266
|
+
#run sub-case based on symbol
|
267
|
+
when Regexp # ?
|
268
|
+
# define method
|
269
|
+
when Array
|
270
|
+
@custom_valid_value_definition = custom_valid_value_definition
|
271
|
+
when block # ?
|
272
|
+
# define method
|
273
|
+
else
|
274
|
+
raise "Could not process custom_valid_value_definition specified for FlowField of name '#{@name}'"
|
275
|
+
end
|
276
|
+
|
277
|
+
case custom_invalid_value_definition
|
278
|
+
when NilClass
|
279
|
+
# take default valid field def based on @type
|
280
|
+
when Symbol
|
281
|
+
#run sub-case based on symbol
|
282
|
+
when Regexp # ?
|
283
|
+
# define method
|
284
|
+
when Block # ?
|
285
|
+
# define method
|
286
|
+
else
|
287
|
+
raise "Could not process custom_invalid_value_definition specified for FlowField of name '#{@name}'"
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
# Retrieves default sizes for fields
|
292
|
+
# Assumes @type is set
|
293
|
+
def get_default_size
|
294
|
+
size = 0
|
295
|
+
case @type
|
296
|
+
when :button, :link, :list, :checkbox
|
297
|
+
# do nothing
|
298
|
+
when :string
|
299
|
+
size = 32
|
300
|
+
when :p, :div # these will be read-only so this doesn't really matter
|
301
|
+
size = 4000
|
302
|
+
else
|
303
|
+
raise "#{@type} is not a valid type for FlowField"
|
304
|
+
end
|
305
|
+
size
|
306
|
+
end
|
307
|
+
|
308
|
+
# Valid types:
|
309
|
+
# :string (a text field);
|
310
|
+
# :button (a button);
|
311
|
+
# :link (a link);
|
312
|
+
# :list (a select list);
|
313
|
+
# :checkbox (a checkbox)
|
314
|
+
def check_valid_type
|
315
|
+
case @type
|
316
|
+
when :button, :link, :list, :checkbox
|
317
|
+
check_valid_size(0)
|
318
|
+
when :string, :p, :div
|
319
|
+
check_valid_size(@size) # TODO a pointless call - @size will compared against itself!
|
320
|
+
else
|
321
|
+
raise "#{@type} is not a valid type for FlowField"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Raises unless the supplied size is greater or equal to @size
|
326
|
+
def check_valid_size(valid_size_for_type)
|
327
|
+
valid = false
|
328
|
+
case @size
|
329
|
+
when NilClass
|
330
|
+
valid = true if @size == nil
|
331
|
+
when TrueClass # possible?
|
332
|
+
valid = @size if something # TODO
|
333
|
+
when FalseClass # possible?
|
334
|
+
valid = @size if something # TODO
|
335
|
+
when Fixnum, String
|
336
|
+
valid = true if @size <= valid_size_for_type
|
337
|
+
end
|
338
|
+
|
339
|
+
raise "Defined size #{@size.inspect} for FlowField '#{@name}' is not valid for field of type '#{type}'" unless valid
|
340
|
+
end
|
341
|
+
|
342
|
+
# TODO needed?
|
343
|
+
def ==(o)
|
344
|
+
end
|
345
|
+
|
346
|
+
# TODO needed?
|
347
|
+
def to_s
|
348
|
+
s = ""
|
349
|
+
s += "Flow field : #{@name}. Type : #{@type}. Mandatory : #{@mandatory}. Size : #{@size}"
|
350
|
+
s
|
351
|
+
end
|
352
|
+
|
353
|
+
# Generate a random value based on its type
|
354
|
+
def random_valid_value
|
355
|
+
value = nil
|
356
|
+
case @type
|
357
|
+
when :string
|
358
|
+
value = rand_string(@size) # TODO : vary size of random string?
|
359
|
+
when :checkbox
|
360
|
+
# value = (rand(2) == 1) # TODO : need to have the object itself have defined what is a valid and invalid
|
361
|
+
# value
|
362
|
+
value = true # most checkboxes will want to be ticked, but it is plausable that the valid value for some of them
|
363
|
+
# is to be unticked
|
364
|
+
when :list
|
365
|
+
# TODO difficult - need to pick a random item from the list. How do we know its contents?
|
366
|
+
# Maybe pick a random number, not greater than the size of the list, then set by index/position?
|
367
|
+
if @custom_valid_value_definition != nil # if not nil, custom_valid_value_definition should be an array of the valid options
|
368
|
+
value = @custom_valid_value_definition.random
|
369
|
+
end
|
370
|
+
when :button
|
371
|
+
# do nothing
|
372
|
+
else
|
373
|
+
raise "Do not know how to generate a random valid value for FlowField of type #{@type}"
|
374
|
+
end
|
375
|
+
value
|
376
|
+
end
|
377
|
+
|
378
|
+
end
|
379
|
+
|
380
|
+
# A class defining a verification step
|
381
|
+
class FlowVerify
|
382
|
+
|
383
|
+
include Test::Unit::Assertions
|
384
|
+
|
385
|
+
attr_accessor :expected, :value_or_regex, :flow_field
|
386
|
+
# expected is a boolean for whether or not the verification is expected to succeed or fail
|
387
|
+
# value_or_regex is a string, number, boolean or regex
|
388
|
+
# flow_field is a FlowField object pointing to a field whose value value_or_regex must be used against
|
389
|
+
|
390
|
+
def initialize(expected, value_or_regex, flow_field)
|
391
|
+
@expected = expected
|
392
|
+
@value_or_regex = value_or_regex
|
393
|
+
|
394
|
+
@flow_field = flow_field
|
395
|
+
raise ":flow_field must be of class FlowField" unless @flow_field.class == FlowField
|
396
|
+
end
|
397
|
+
|
398
|
+
def to_s
|
399
|
+
s = ""
|
400
|
+
s += "Flow verifier : expected : #{@expected}. Value/regex : #{@value_or_regex.inspect}. Field : #{@flow_field}"
|
401
|
+
s
|
402
|
+
end
|
403
|
+
|
404
|
+
def verify(actual)
|
405
|
+
puts "now in verify for FlowVerify for field #{@flow_field} against value #{@value_or_regex}"
|
406
|
+
|
407
|
+
case @value_or_regex # case is better, leaves room for other options depending on class
|
408
|
+
when Regexp
|
409
|
+
match = !!(actual =~ @value_or_regex) # double-invert to convert to true-or-false
|
410
|
+
else
|
411
|
+
match = (actual == @value_or_regex)
|
412
|
+
end
|
413
|
+
if @expected
|
414
|
+
message = "FlowVerify failed. Expected the value to match #{@value_or_regex.inspect} but was actually #{actual.inspect}"
|
415
|
+
else
|
416
|
+
message = "FlowVerify failed. Expected the value #{@value_or_regex.inspect} to be different to the actual value of #{actual.inspect}"
|
417
|
+
end
|
418
|
+
puts "about to assert; #{actual.inspect} == #{@value_or_regex.inspect} => #{@expected == match}"
|
419
|
+
assert_equal(@expected, match, message)
|
420
|
+
puts "assertion passed"
|
421
|
+
end
|
422
|
+
|
423
|
+
end
|
424
|
+
|
425
|
+
# A class defining feedback to be returned after invoking the flow.
|
426
|
+
# TODO : rework this so that it knows how to gather the required information (?)
|
427
|
+
class FlowReport
|
428
|
+
|
429
|
+
# attr_accessor :success, :message, :value_hash_array
|
430
|
+
# # success is a boolean
|
431
|
+
# # message is a string
|
432
|
+
# # value_hash_array is an array of hashes, one per object/event/thing. Its keys are the object's fields, and the
|
433
|
+
# values
|
434
|
+
## are their values
|
435
|
+
#
|
436
|
+
# def initialize(success, message, value_hash_array)
|
437
|
+
# @success = success
|
438
|
+
# @message = message
|
439
|
+
# @value_hash_array = value_hash_array
|
440
|
+
# end
|
441
|
+
#
|
442
|
+
# def to_s
|
443
|
+
# s = ""
|
444
|
+
# s += "Flow report : success? #{@success}. Message : #{@message}. Values : #{@value_hash_array}"
|
445
|
+
# s
|
446
|
+
# end
|
447
|
+
|
448
|
+
attr_accessor :value
|
449
|
+
|
450
|
+
def initialize(value = nil)
|
451
|
+
# do nothing?
|
452
|
+
@value = value
|
453
|
+
end
|
454
|
+
|
455
|
+
def to_s
|
456
|
+
s = ""
|
457
|
+
s += "Flow report : value : #{@value}"
|
458
|
+
s
|
459
|
+
end
|
460
|
+
|
461
|
+
def generate_report
|
462
|
+
#TODO
|
463
|
+
""
|
464
|
+
end
|
465
|
+
|
466
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# List of constants that store names of flows
|
2
|
+
# Names are stored as symbols
|
3
|
+
|
4
|
+
class RSFN
|
5
|
+
|
6
|
+
# Homepage
|
7
|
+
GOTO_HOMEPAGE = :goto_homepage
|
8
|
+
|
9
|
+
# Users
|
10
|
+
VIEW_ALL_USERS = :view_all_users
|
11
|
+
VIEW_USER = :view_user
|
12
|
+
CREATE_USER = :create_user
|
13
|
+
DELETE_USER = :delete_user
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# A class defining the UI flows within RedSky, such that simple usecase-esq methods arise from them and can
|
2
|
+
# perform a series of UI actions (making a record, viewing & deleting, etc.)
|
3
|
+
|
4
|
+
# The intended use is that the test (or supporting framework) call @flow.flow_name, e.g. @flow.create_project, which will
|
5
|
+
# perform all of the actions of that flow. Parameters can be supplied to the call, which will change its behaviour
|
6
|
+
|
7
|
+
require_relative 'flow_objects'
|
8
|
+
require_relative 'rs_flow_names'
|
9
|
+
|
10
|
+
class RSFlows
|
11
|
+
|
12
|
+
attr_accessor :flows # array of Flow objects
|
13
|
+
attr_accessor :flow_names # array of names of known Flow objects
|
14
|
+
|
15
|
+
|
16
|
+
# Assembles all of the flows and stores them, ready for use
|
17
|
+
def initialize
|
18
|
+
@flows = [] # an array of Flow objects
|
19
|
+
@flow_names = []
|
20
|
+
|
21
|
+
# Simple nav flow to get to the homepage
|
22
|
+
flow = Flow.new(RSFN::GOTO_HOMEPAGE)
|
23
|
+
flow.add(FlowLink.new("goto_homepage", "rs_home_header_link", nil)) # no parent page, is valid from any page
|
24
|
+
add_flow(flow)
|
25
|
+
|
26
|
+
# View all users
|
27
|
+
flow = new_base_flow(RSFN::VIEW_ALL_USERS)
|
28
|
+
flow.add(FlowLink.new("all_users", "users_header_link", nil))
|
29
|
+
add_flow(flow)
|
30
|
+
|
31
|
+
# Create user
|
32
|
+
flow = new_base_flow(RSFN::CREATE_USER)
|
33
|
+
add_existing_flow_to_flow(flow, RSFN::VIEW_ALL_USERS)
|
34
|
+
|
35
|
+
flow.add(FlowLink.new("all_users", "users_header_link", nil))
|
36
|
+
flow.add(FlowLink.new("create_user", "new_user_link", "all_users"))
|
37
|
+
field_flow = Flow.new("create_user_fields")
|
38
|
+
|
39
|
+
field_flow.add(FlowField.new("user_name"))
|
40
|
+
field_flow.add(FlowField.new("user_role", :list, :write, true, nil, RedSkyConfig::ALL_USER_ROLES))
|
41
|
+
|
42
|
+
flow.add(field_flow)
|
43
|
+
flow.add(FlowField.new("save", :button))
|
44
|
+
|
45
|
+
message = FlowField.new("notice", :p, :read)
|
46
|
+
flow.add(FlowVerify.new(true, "User was successfully created.", message))
|
47
|
+
|
48
|
+
add_flow(flow)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
##############################################################################
|
53
|
+
|
54
|
+
|
55
|
+
def method_missing(name, *args, &block)
|
56
|
+
puts "RSFlows method_missing called; name = #{name.inspect}; #{name.class}"
|
57
|
+
|
58
|
+
if flow_known(name)
|
59
|
+
puts "Flow #{name} is known"
|
60
|
+
# TODO define a whole bunch of methods and then perform them
|
61
|
+
# If args and/or block have been provided, process them. E.g. one arg could be a trigger to perform the flow with
|
62
|
+
# invalid values # TODO : is that the best way of doing that?
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_flow(flow)
|
69
|
+
@flows << flow
|
70
|
+
@flow_names << flow.name
|
71
|
+
end
|
72
|
+
|
73
|
+
# TODO needed?
|
74
|
+
def ==(o)
|
75
|
+
end
|
76
|
+
|
77
|
+
# TODO needed?
|
78
|
+
def to_s
|
79
|
+
s = ""
|
80
|
+
s += "#{@flows.size} flows defined. Names :"
|
81
|
+
@flow_names.each {|f| s += "\n#{f}" }
|
82
|
+
s
|
83
|
+
end
|
84
|
+
|
85
|
+
# Will convert name to a string
|
86
|
+
def flow_known?(name)
|
87
|
+
@flow_names.include?(name)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Retrieves the specific flow; raises if it cannot be found
|
91
|
+
# Will convert name to a string
|
92
|
+
def find(name)
|
93
|
+
raise "Could not locate flow '#{name}'" unless flow_known?(name)
|
94
|
+
@flows[@flow_names.index(name)]
|
95
|
+
end
|
96
|
+
|
97
|
+
# Finds & executes a flow
|
98
|
+
def find_and_execute(browser, name, custom_values_hash = {}, success_sym = :success, mandatory_fields_sym = :mandatory)
|
99
|
+
f = find(name)
|
100
|
+
f.execute(browser, custom_values_hash, success_sym, mandatory_fields_sym)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Adds an already-existing flow to the supplied flow
|
104
|
+
def add_existing_flow_to_flow(new_flow, existing_flow_name)
|
105
|
+
# TODO : need deduplication mechanism so that a flow doesn't gain two/more duplicate flow items in a row (e.g. two calls to GOTO_HOMEPAGE in a row)
|
106
|
+
new_flow.add(find(existing_flow_name))
|
107
|
+
end
|
108
|
+
|
109
|
+
# Shortcut to define a new flow with standard prerequisite flows already added
|
110
|
+
# Cannot be called until the flows that are to be added have been defined
|
111
|
+
def new_base_flow(name)
|
112
|
+
flow = Flow.new(name)
|
113
|
+
add_existing_flow_to_flow(flow, RSFN::GOTO_HOMEPAGE)
|
114
|
+
flow
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|