sakai-oae-test-api 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +7 -0
- data/lib/sakai-oae-test-api.rb +37 -0
- data/lib/sakai-oae-test-api/cle_frame_classes.rb +2160 -0
- data/lib/sakai-oae-test-api/gem_extensions.rb +168 -0
- data/lib/sakai-oae-test-api/global_methods.rb +109 -0
- data/lib/sakai-oae-test-api/page_classes.rb +1949 -0
- data/lib/sakai-oae-test-api/pop_up_dialogs.rb +1273 -0
- data/lib/sakai-oae-test-api/toolbars_and_menus.rb +745 -0
- data/lib/sakai-oae-test-api/widgets.rb +495 -0
- data/sakai-oae-test-api.gemspec +16 -0
- metadata +121 -0
@@ -0,0 +1,495 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
# Methods related to the expandable Collector item that can appear at the top of any page.
|
4
|
+
module CollectorWidget
|
5
|
+
|
6
|
+
include PageObject
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
# Methods associated with documents that use the TinyMCE Editor.
|
11
|
+
module DocumentWidget
|
12
|
+
|
13
|
+
include PageObject
|
14
|
+
|
15
|
+
# Page Objects
|
16
|
+
button(:dont_save, :id=>"sakaidocs_edit_cancel_button")
|
17
|
+
button(:save_button, :id=>"sakaidocs_edit_save_button")
|
18
|
+
button(:insert, :id=>"sakaidocs_insert_dropdown_button")
|
19
|
+
select_list(:format, :id=>/formatselect/)
|
20
|
+
select_list(:font, :id=>/fontselect/)
|
21
|
+
select_list(:font_size, :id=>/fontsizeselect/)
|
22
|
+
link(:bold, :id=>/_bold/)
|
23
|
+
link(:italic, :id=>/_italic/)
|
24
|
+
link(:underline, :id=>/_underline/)
|
25
|
+
|
26
|
+
# These methods click the Insert button (you must be editing the document first),
|
27
|
+
# then select the specified menu item, to bring up the Widget settings dialog.
|
28
|
+
# The first argument is the method name (which automatically gets pre-pended
|
29
|
+
# with "insert_", the second is the id of the target
|
30
|
+
# button in the Insert menu, and the last argument is the name of the module
|
31
|
+
# to be included in the current Class object. The module name can be nil,
|
32
|
+
# since not every item in the insert button list brings up a Pop Up dialog.
|
33
|
+
insert_button(:files_and_documents, "embedcontent", "FilesAndDocsPopUp")
|
34
|
+
insert_button(:discussion, "discussion", "Discussion")
|
35
|
+
insert_button(:remote_content, "remotecontent", "RemoteContentPopUp" )
|
36
|
+
insert_button(:inline_content, "inlinecontent", "InlineContentPopUp" )
|
37
|
+
insert_button(:google_maps, "googlemaps", "GoogleMapsPopUp" )
|
38
|
+
insert_button(:comments, "comments", "CommentsPopUp" )
|
39
|
+
insert_button(:rss_feed_reader, "rss", "RSSFeedPopUp" )
|
40
|
+
insert_button(:google_gadget, "ggadget", "GoogleGadgetPopUp" )
|
41
|
+
insert_button(:horizontal_line, "hr")
|
42
|
+
insert_button(:tests_and_quizzes, "sakai2samigo")
|
43
|
+
insert_button(:calendar, "sakai2calendar")
|
44
|
+
insert_button(:jisc_content, "jisccontent")
|
45
|
+
insert_button(:assignments, "sakai2assignments")
|
46
|
+
insert_button(:basic_lti, "basiclti")
|
47
|
+
insert_button(:gradebook, "sakai2gradebook")
|
48
|
+
|
49
|
+
# Custom Methods...
|
50
|
+
|
51
|
+
# Clicks the Save button. Waits for Ajax calls to fall off.
|
52
|
+
def save
|
53
|
+
self.save_button
|
54
|
+
sleep 1
|
55
|
+
self.wait_for_ajax
|
56
|
+
end
|
57
|
+
|
58
|
+
# Erases the entire contents of the TinyMCE Editor, then
|
59
|
+
# enters the specified string into the Editor.
|
60
|
+
def set_content=(text)
|
61
|
+
self.frame(:id=>"elm1_ifr").body(:id=>"tinymce").fire_event("onclick")
|
62
|
+
self.frame(:id=>"elm1_ifr").send_keys( [:command, 'a'] )
|
63
|
+
self.frame(:id=>"elm1_ifr").send_keys(text)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Appends the specified string to the contents of the TinyMCE Editor.
|
67
|
+
def add_content=(text)
|
68
|
+
self.frame(:id=>"elm1_ifr").body(:id=>"tinymce").fire_event("onclick")
|
69
|
+
self.frame(:id=>"elm1_ifr").send_keys(text)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Selects all the contents of the TinyMCE Editor
|
73
|
+
def select_all
|
74
|
+
self.frame(:id=>"elm1_ifr").send_keys( [:command, 'a'] )
|
75
|
+
end
|
76
|
+
|
77
|
+
# Clicks the Text Box of the TinyMCE Editor so that the edit cursor
|
78
|
+
# will become active in the Editor.
|
79
|
+
def insert_text
|
80
|
+
self.frame(:id=>"elm1_ifr").body(:id=>"tinymce").fire_event("onclick")
|
81
|
+
end
|
82
|
+
|
83
|
+
# Other MCE Objects TBD later, maybe, though we're not in the business of testing TinyMCE...
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
# Methods related to the Library List page.
|
88
|
+
module LibraryWidget
|
89
|
+
|
90
|
+
include PageObject
|
91
|
+
|
92
|
+
text_field(:search_library, :id=>"mylibrary_livefilter")
|
93
|
+
checkbox(:select_all_library_items, :id=>"mylibrary_select_checkbox")
|
94
|
+
button(:add_selected_to_buton, :id=>"mylibrary_addpeople_button")
|
95
|
+
button(:remove_selected_button, :id=>"mylibrary_remove")
|
96
|
+
button(:share_selected_button, :id=>"mylibrary_content_share")
|
97
|
+
select_list(:sort_by_list, :id=>"mylibrary_sortby")
|
98
|
+
|
99
|
+
# Enters the specified string in the search field.
|
100
|
+
# Note that it appends a line feed on the string, so the
|
101
|
+
# search occurs immediately.
|
102
|
+
def search_library_for=(text)
|
103
|
+
self.search_library=("#{text}\n")
|
104
|
+
self.wait_for_ajax
|
105
|
+
end
|
106
|
+
|
107
|
+
def sort_by=(sort_option)
|
108
|
+
self.sort_by_list=sort_option
|
109
|
+
self.linger_for_ajax(2)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns the checkbox element itself for the specified
|
113
|
+
# item in the list. Use this method for checking whether or
|
114
|
+
# not the checkbox in question is selected or not--e.g.,
|
115
|
+
# library.checkbox("textfile.txt").should be_set
|
116
|
+
def checkbox(item)
|
117
|
+
name_li(item).checkbox
|
118
|
+
end
|
119
|
+
|
120
|
+
# Checks the specified Library item.
|
121
|
+
def check_content(item)
|
122
|
+
name_li(item).checkbox.set
|
123
|
+
end
|
124
|
+
|
125
|
+
# Unchecks the specified library item.
|
126
|
+
def uncheck_content(item)
|
127
|
+
name_li(item).checkbox.clear
|
128
|
+
end
|
129
|
+
|
130
|
+
def add_selected_to
|
131
|
+
self.add_selected_to_button
|
132
|
+
self.wait_for_ajax
|
133
|
+
self.class.class_eval { include AddToGroupsPopUp }
|
134
|
+
end
|
135
|
+
|
136
|
+
def add_to(name)
|
137
|
+
name_li(name)
|
138
|
+
# TODO - Finish writing this method
|
139
|
+
end
|
140
|
+
|
141
|
+
def share_selected
|
142
|
+
self.share_selected_button
|
143
|
+
self.text_field(:name=>"newsharecontent_sharelist").wait_until_present
|
144
|
+
self.class.class_eval { include ShareWithPopUp }
|
145
|
+
end
|
146
|
+
|
147
|
+
def remove_selected
|
148
|
+
self.remove_selected_button
|
149
|
+
self.div(:id=>"deletecontent_dialog").wait_until_present
|
150
|
+
self.class.class_eval { include DeleteContentPopUp }
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
# Contains methods common to all Results lists
|
156
|
+
module ListWidget
|
157
|
+
|
158
|
+
include PageObject
|
159
|
+
|
160
|
+
# Page Objects
|
161
|
+
# select_list(:sort_by, :id=>/sortby/) Collision with method in Library widget
|
162
|
+
select_list(:filter_by, :id=>"facted_select")
|
163
|
+
|
164
|
+
# Custom Methods...
|
165
|
+
|
166
|
+
# Returns an array containing the text of the links (for Groups, Courses, etc.) listed
|
167
|
+
def results_list
|
168
|
+
list = []
|
169
|
+
begin
|
170
|
+
self.spans(:class=>"s3d-search-result-name").each do |element|
|
171
|
+
list << element.text
|
172
|
+
end
|
173
|
+
rescue
|
174
|
+
list = []
|
175
|
+
end
|
176
|
+
list
|
177
|
+
end
|
178
|
+
alias courses results_list
|
179
|
+
alias course_list results_list
|
180
|
+
alias groups_list results_list
|
181
|
+
alias groups results_list
|
182
|
+
alias projects results_list
|
183
|
+
alias documents results_list
|
184
|
+
alias documents_list results_list
|
185
|
+
alias content_list results_list
|
186
|
+
alias results results_list
|
187
|
+
alias people_list results_list
|
188
|
+
alias contacts results_list
|
189
|
+
alias memberships results_list
|
190
|
+
|
191
|
+
# Gets the text describing when the specified item was last changed.
|
192
|
+
def last_updated(name)
|
193
|
+
# Get the target class...
|
194
|
+
klass = case
|
195
|
+
when name_li(name).div(:class=>"searchgroups_result_usedin").present?
|
196
|
+
"searchgroups_result_usedin"
|
197
|
+
when name_li(name).div(:class=>"searchcontent_result_by").present?
|
198
|
+
"searchcontent_result_by"
|
199
|
+
when name_li(name).div(:class=>"mymemberships_item_usedin").present?
|
200
|
+
"mymemberships_item_usedin"
|
201
|
+
when name_li(name).div(:class=>"mylibrary_item_by").present?
|
202
|
+
"mylibrary_item_by"
|
203
|
+
else
|
204
|
+
puts "Didn't find any expected DIVs. Please investigate and add missing class value"
|
205
|
+
puts
|
206
|
+
puts name_li(name).html
|
207
|
+
end
|
208
|
+
# Grab the text now that we know the class of the div...
|
209
|
+
div_text = name_li(name).div(:class=>klass).text
|
210
|
+
case(klass)
|
211
|
+
when "mylibrary_item_by"
|
212
|
+
return div_text[/(?<=\|.).+/]
|
213
|
+
when "searchgroups_result_usedin"
|
214
|
+
return div_text[/^.+(?=.\|)/]
|
215
|
+
when "mymemberships_item_usedin"
|
216
|
+
return div_text[/^.+(?=.\|)/]
|
217
|
+
when "searchcontent_result_by"
|
218
|
+
return div_text[/(?<=\|.).+/]
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
alias last_changed last_updated
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
# Methods related to lists of Collections
|
227
|
+
module ListCollections
|
228
|
+
|
229
|
+
include PageObject
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
# Methods related to lists of Content-type objects
|
234
|
+
module ListContent
|
235
|
+
|
236
|
+
include PageObject
|
237
|
+
|
238
|
+
# Returns the src text for the specified item's
|
239
|
+
# Thumbnail image.
|
240
|
+
def thumbnail(name)
|
241
|
+
name_li(name).link(:title=>"View this item").image.src
|
242
|
+
end
|
243
|
+
|
244
|
+
# Clicks to share the specified item. Waits for the page
|
245
|
+
# to refresh to bring up the Share Pop Up dialog.
|
246
|
+
def share(name)
|
247
|
+
name_li(name).button(:title=>"Share content").click
|
248
|
+
self.wait_until { self.text.include? "Or, share it on a webservice:" }
|
249
|
+
self.class.class_eval { include ShareWithPopUp }
|
250
|
+
end
|
251
|
+
|
252
|
+
# Adds the specified (listed) content to the library.
|
253
|
+
def add_to_library(name)
|
254
|
+
name_li(name).button(:title=>/^Save /).click
|
255
|
+
self.wait_until { self.div(:id=>"savecontent_widget").visible? }
|
256
|
+
self.class.class_eval { include SaveContentPopUp }
|
257
|
+
end
|
258
|
+
|
259
|
+
def delete(name)
|
260
|
+
name_li(name).button(:title=>"Remove").click
|
261
|
+
self.div(:id=>"deletecontent_dialog").wait_until_present
|
262
|
+
self.class.class_eval { include DeleteContentPopUp }
|
263
|
+
end
|
264
|
+
alias remove_item delete
|
265
|
+
|
266
|
+
# Clicks to view the owner information of the specified item.
|
267
|
+
def view_owner_of(name)
|
268
|
+
name_li(name).link(:class=>/s3d-regular-light-links (mylibrary_item_|searchcontent_result_)username/).click
|
269
|
+
self.div(:id=>"entity_name").wait_until_present
|
270
|
+
ViewPerson.new @browser
|
271
|
+
end
|
272
|
+
|
273
|
+
# Returns the item's owner name (as a text string).
|
274
|
+
def content_owner(name)
|
275
|
+
name_li(name).div(:class=>/(mylibrary_item_|searchcontent_result_)by/).link.text
|
276
|
+
end
|
277
|
+
|
278
|
+
# Returns an Array object containing the list of tags/categories
|
279
|
+
# listed for the specified content item.
|
280
|
+
def content_tags(name)
|
281
|
+
array = []
|
282
|
+
name_li(name).div(:class=>/(mylibrary_item_|searchcontent_result_)tags/).lis.each do |li|
|
283
|
+
array << li.span(:class=>"s3d-search-result-tag").text
|
284
|
+
end
|
285
|
+
return array
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns the mimetype text next to the Content name--the text that describes
|
289
|
+
# what the system thinks the content is.
|
290
|
+
def content_type(name)
|
291
|
+
name_li(name).span(:class=>/(mylibrary_item_|searchcontent_result_)mimetype/).text
|
292
|
+
end
|
293
|
+
|
294
|
+
def content_description(name)
|
295
|
+
name_li(name).div(:class=>/(mylibrary_item_|searchcontent_result_)description/).text
|
296
|
+
end
|
297
|
+
|
298
|
+
def search_by_tag(tag)
|
299
|
+
name_link(tag).click
|
300
|
+
sleep 3
|
301
|
+
self.wait_for_ajax
|
302
|
+
ExploreAll.new @browser
|
303
|
+
end
|
304
|
+
|
305
|
+
def used_in_count(name)
|
306
|
+
used_in_text(name)[/(?<=in.)\d+/].to_i
|
307
|
+
end
|
308
|
+
|
309
|
+
def comments_count(name)
|
310
|
+
used_in_text(name)[/\d+(?=.comment)/].to_i
|
311
|
+
end
|
312
|
+
|
313
|
+
#Private methods
|
314
|
+
private
|
315
|
+
|
316
|
+
def used_in_text(name)
|
317
|
+
name_li(name).div(:class=>/(mylibrary_item_|searchcontent_result_)usedin/).text
|
318
|
+
end
|
319
|
+
|
320
|
+
end # ListContent
|
321
|
+
|
322
|
+
# Methods related to lists of People/Participants
|
323
|
+
module ListPeople
|
324
|
+
|
325
|
+
include PageObject
|
326
|
+
|
327
|
+
# Clicks the plus sign next to the specified Contact name.
|
328
|
+
# Obviously the name must exist in the list.
|
329
|
+
def add_contact(name)
|
330
|
+
self.button(:title=>"Request connection with #{name}").click
|
331
|
+
self.wait_until { @browser.button(:text=>"Invite").visible? }
|
332
|
+
self.class.class_eval { include AddToContactsPopUp }
|
333
|
+
end
|
334
|
+
alias request_contact add_contact
|
335
|
+
alias request_connection add_contact
|
336
|
+
|
337
|
+
# Clicks the X to remove the selected person from the
|
338
|
+
# Contacts list (in My Contacts).
|
339
|
+
def remove(name)
|
340
|
+
self.button(:title=>"Remove contact #{name}").click
|
341
|
+
self.wait_for_ajax
|
342
|
+
self.class.class_eval { include RemoveContactsPopUp }
|
343
|
+
end
|
344
|
+
alias remove_contact remove
|
345
|
+
|
346
|
+
def send_message_to(name)
|
347
|
+
name_li(name).button(:class=>"s3d-link-button s3d-action-icon s3d-actions-message searchpeople_result_message_icon sakai_sendmessage_overlay").click
|
348
|
+
self.wait_for_ajax
|
349
|
+
self.class.class_eval { include SendMessagePopUp }
|
350
|
+
end
|
351
|
+
|
352
|
+
# This method checks whether or not the listed
|
353
|
+
# person has the "Add contact" button available.
|
354
|
+
# To ensure the test case will be valid, it first
|
355
|
+
# makes sure the specified person is in the list.
|
356
|
+
# Returns true if the button is available.
|
357
|
+
def addable?(name)
|
358
|
+
if name_li(name).exists?
|
359
|
+
self.button(:title=>"Request connection with #{name}").present?
|
360
|
+
else
|
361
|
+
puts "\n#{name} isn't in the results list. Check your script.\nThis may be a false negative.\n"
|
362
|
+
return false
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
end
|
367
|
+
|
368
|
+
# Methods related to lists of Groups/Courses
|
369
|
+
module ListGroups
|
370
|
+
|
371
|
+
include PageObject
|
372
|
+
|
373
|
+
def join_button_for(name)
|
374
|
+
name_li(name).div(:class=>/searchgroups_result_left_filler/)
|
375
|
+
end
|
376
|
+
|
377
|
+
# Clicks on the plus sign image for the specified group in the list.
|
378
|
+
def add_group(name)
|
379
|
+
name_li(name).div(:class=>/searchgroups_result_left_filler/).fire_event("onclick")
|
380
|
+
end
|
381
|
+
alias add_course add_group
|
382
|
+
alias add_research add_group
|
383
|
+
alias join_course add_group
|
384
|
+
alias join_group add_group
|
385
|
+
|
386
|
+
#
|
387
|
+
def remove_membership(name)
|
388
|
+
remove_membership_button(name).click
|
389
|
+
self.linger_for_ajax
|
390
|
+
self.class.class_eval { include LeaveWorldPopUp }
|
391
|
+
end
|
392
|
+
alias leave_group remove_membership
|
393
|
+
|
394
|
+
# This returns the Remove button element itself, for the
|
395
|
+
# specified Group/Course/Research listed. This is useful
|
396
|
+
# for interacting directly with the element instead of
|
397
|
+
# simply clicking on it.
|
398
|
+
def remove_membership_button(name)
|
399
|
+
name_li(name).button(:title=>/Remove membership from/)
|
400
|
+
end
|
401
|
+
|
402
|
+
# Checks the checkbox for the specified group _
|
403
|
+
def check_group(name)
|
404
|
+
name_li(name).checkbox(:title=>/Select/).set
|
405
|
+
end
|
406
|
+
alias select_group check_group
|
407
|
+
|
408
|
+
# Returns the specified item's "type", as shown next to the item name--i.e.,
|
409
|
+
# "GROUP", "COURSE", etc.
|
410
|
+
def group_type(name)
|
411
|
+
self.span(:class=>"s3d-search-result-name",:text=>name).parent.parent.span(:class=>"mymemberships_item_grouptype").text
|
412
|
+
end
|
413
|
+
alias course_type group_type
|
414
|
+
alias research_type group_type
|
415
|
+
|
416
|
+
# Returns the number of content items (as an Integer, not a String) in the specified
|
417
|
+
# course/group.
|
418
|
+
def content_item_count(name)
|
419
|
+
text = self.span(:class=>"s3d-search-result-name",:text=>name).parent.parent.parent.link(:title=>/\d+.content items/).text
|
420
|
+
text[/\d+/].to_i
|
421
|
+
end
|
422
|
+
|
423
|
+
# Returns the count (as an Integer, not a String) of participants in the specified group/course.
|
424
|
+
def participants_count(name)
|
425
|
+
text = self.span(:class=>"s3d-search-result-name",:text=>name).parent.parent.parent.link(:title=>/\d+.participant/).text
|
426
|
+
text[/\d+/].to_i
|
427
|
+
end
|
428
|
+
|
429
|
+
def view_group_participants(name)
|
430
|
+
name_li(name).link(:title=>/\d+.participant/i).click
|
431
|
+
self.linger_for_ajax(2)
|
432
|
+
Participants.new @browser
|
433
|
+
end
|
434
|
+
|
435
|
+
# Clicks the Message button for the specified listed item.
|
436
|
+
def message_course(name)
|
437
|
+
message_button(name).click
|
438
|
+
self.linger_for_ajax(2)
|
439
|
+
self.class.class_eval { include SendMessagePopUp }
|
440
|
+
end
|
441
|
+
alias send_message_to_course message_course
|
442
|
+
alias send_message_to_group message_course
|
443
|
+
alias message_group message_course
|
444
|
+
alias message_person message_course
|
445
|
+
alias message_research message_course
|
446
|
+
|
447
|
+
# Returns the message button element itself.
|
448
|
+
def message_button(name)
|
449
|
+
name_li(name).button(:class=>/sakai_sendmessage_overlay/)
|
450
|
+
end
|
451
|
+
|
452
|
+
end
|
453
|
+
|
454
|
+
# Methods related to lists of Research Projects
|
455
|
+
module ListProjects
|
456
|
+
|
457
|
+
include PageObject
|
458
|
+
|
459
|
+
# Page Objects
|
460
|
+
|
461
|
+
# Custom Methods...
|
462
|
+
|
463
|
+
# Clicks the specified Link (will open any link that matches the
|
464
|
+
# supplied text, but it's made for clicking on a Research item listed on
|
465
|
+
# the page because it will instantiate the ResearchIntro class).
|
466
|
+
def open_research(name)
|
467
|
+
name_link(name).click
|
468
|
+
sleep 1
|
469
|
+
self.wait_for_ajax
|
470
|
+
self.execute_script("$('#joinrequestbuttons_widget').css({display: 'block'})")
|
471
|
+
ResearchIntro.new @browser
|
472
|
+
end
|
473
|
+
|
474
|
+
alias view_research open_research
|
475
|
+
alias open_project open_research
|
476
|
+
|
477
|
+
end
|
478
|
+
|
479
|
+
# Methods related to the Participants "Area" or "Page" in
|
480
|
+
# Groups/Courses. This is not the same thing as the ManageParticipants
|
481
|
+
# module, which relates to the "Add People" Pop Up.
|
482
|
+
module ParticipantsWidget
|
483
|
+
|
484
|
+
include PageObject
|
485
|
+
|
486
|
+
end
|
487
|
+
|
488
|
+
# Page Elements and Custom Methods that are shared among the three Error pages
|
489
|
+
module CommonErrorElements
|
490
|
+
|
491
|
+
include PageObject
|
492
|
+
|
493
|
+
# TBD
|
494
|
+
|
495
|
+
end
|