sakai-cle-test-api 0.0.75 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/lib/sakai-cle-test-api.rb +4 -5
  2. data/lib/sakai-cle-test-api/base_page.rb +20 -0
  3. data/lib/sakai-cle-test-api/core-ext.rb +90 -0
  4. data/lib/sakai-cle-test-api/data_objects/announcement.rb +81 -0
  5. data/lib/sakai-cle-test-api/data_objects/assessment.rb +32 -0
  6. data/lib/sakai-cle-test-api/data_objects/assignment.rb +90 -0
  7. data/lib/sakai-cle-test-api/data_objects/event.rb +89 -0
  8. data/lib/sakai-cle-test-api/data_objects/lesson.rb +185 -0
  9. data/lib/sakai-cle-test-api/data_objects/resource.rb +209 -0
  10. data/lib/sakai-cle-test-api/data_objects/site.rb +208 -0
  11. data/lib/sakai-cle-test-api/data_objects/syllabus.rb +39 -0
  12. data/lib/sakai-cle-test-api/data_objects/web_content_tool.rb +51 -0
  13. data/lib/sakai-cle-test-api/data_objects/wiki.rb +53 -0
  14. data/lib/sakai-cle-test-api/gem_ext.rb +23 -0
  15. data/lib/sakai-cle-test-api/page_helper.rb +22 -0
  16. data/lib/sakai-cle-test-api/page_maker.rb +48 -0
  17. data/lib/sakai-cle-test-api/page_objects/account.rb +111 -0
  18. data/lib/sakai-cle-test-api/page_objects/aliases.rb +43 -0
  19. data/lib/sakai-cle-test-api/page_objects/announcements.rb +190 -0
  20. data/lib/sakai-cle-test-api/page_objects/assessments.rb +874 -0
  21. data/lib/sakai-cle-test-api/page_objects/assignments.rb +771 -0
  22. data/lib/sakai-cle-test-api/page_objects/basic_lti.rb +6 -0
  23. data/lib/sakai-cle-test-api/page_objects/blogger.rb +205 -0
  24. data/lib/sakai-cle-test-api/page_objects/blogs.rb +60 -0
  25. data/lib/sakai-cle-test-api/page_objects/calendar.rb +431 -0
  26. data/lib/sakai-cle-test-api/page_objects/calendar_summary.rb +1 -0
  27. data/lib/sakai-cle-test-api/page_objects/chat_room.rb +12 -0
  28. data/lib/sakai-cle-test-api/page_objects/drop_box.rb +9 -0
  29. data/lib/sakai-cle-test-api/page_objects/email_archive.rb +22 -0
  30. data/lib/sakai-cle-test-api/page_objects/evaluations.rb +158 -0
  31. data/lib/sakai-cle-test-api/page_objects/feedback.rb +36 -0
  32. data/lib/sakai-cle-test-api/page_objects/forms.rb +120 -0
  33. data/lib/sakai-cle-test-api/page_objects/forums.rb +289 -0
  34. data/lib/sakai-cle-test-api/page_objects/glossary.rb +117 -0
  35. data/lib/sakai-cle-test-api/page_objects/gradebook.rb +29 -0
  36. data/lib/sakai-cle-test-api/page_objects/gradebook2.rb +17 -0
  37. data/lib/sakai-cle-test-api/page_objects/home.rb +36 -0
  38. data/lib/sakai-cle-test-api/page_objects/jforums.rb +444 -0
  39. data/lib/sakai-cle-test-api/page_objects/job_scheduler.rb +121 -0
  40. data/lib/sakai-cle-test-api/page_objects/lessons.rb +360 -0
  41. data/lib/sakai-cle-test-api/page_objects/login.rb +28 -0
  42. data/lib/sakai-cle-test-api/page_objects/matrix.rb +241 -0
  43. data/lib/sakai-cle-test-api/page_objects/media_gallery.rb +13 -0
  44. data/lib/sakai-cle-test-api/page_objects/messages.rb +622 -0
  45. data/lib/sakai-cle-test-api/page_objects/my_workspace.rb +44 -0
  46. data/lib/sakai-cle-test-api/page_objects/news.rb +8 -0
  47. data/lib/sakai-cle-test-api/page_objects/podcasts.rb +27 -0
  48. data/lib/sakai-cle-test-api/page_objects/polls.rb +69 -0
  49. data/lib/sakai-cle-test-api/page_objects/portfolio_templates.rb +161 -0
  50. data/lib/sakai-cle-test-api/page_objects/portfolios.rb +162 -0
  51. data/lib/sakai-cle-test-api/page_objects/post_em.rb +1 -0
  52. data/lib/sakai-cle-test-api/page_objects/profile.rb +51 -0
  53. data/lib/sakai-cle-test-api/page_objects/profile2.rb +344 -0
  54. data/lib/sakai-cle-test-api/page_objects/public_search.rb +61 -0
  55. data/lib/sakai-cle-test-api/page_objects/realms.rb +19 -0
  56. data/lib/sakai-cle-test-api/page_objects/resources.rb +326 -0
  57. data/lib/sakai-cle-test-api/{resources_roster.rb → page_objects/resources_roster.rb} +0 -0
  58. data/lib/sakai-cle-test-api/page_objects/rosters.rb +70 -0
  59. data/lib/sakai-cle-test-api/page_objects/rwiki.rb +34 -0
  60. data/lib/sakai-cle-test-api/page_objects/search.rb +34 -0
  61. data/lib/sakai-cle-test-api/page_objects/sections.rb +295 -0
  62. data/lib/sakai-cle-test-api/page_objects/single_user.rb +1 -0
  63. data/lib/sakai-cle-test-api/page_objects/site_setup.rb +686 -0
  64. data/lib/sakai-cle-test-api/page_objects/site_statistics.rb +1 -0
  65. data/lib/sakai-cle-test-api/page_objects/sites.rb +255 -0
  66. data/lib/sakai-cle-test-api/page_objects/styles.rb +74 -0
  67. data/lib/sakai-cle-test-api/page_objects/syllabus.rb +166 -0
  68. data/lib/sakai-cle-test-api/page_objects/user_membership.rb +57 -0
  69. data/lib/sakai-cle-test-api/page_objects/users.rb +88 -0
  70. data/lib/sakai-cle-test-api/rich_text.rb +27 -0
  71. data/lib/sakai-cle-test-api/utilities.rb +260 -0
  72. data/lib/sakai-cle-test-api/workflows.rb +224 -0
  73. data/sakai-cle-test-api.gemspec +3 -5
  74. metadata +74 -64
  75. data/lib/sakai-cle-test-api/admin_page_elements.rb +0 -1030
  76. data/lib/sakai-cle-test-api/announcements.rb +0 -59
  77. data/lib/sakai-cle-test-api/assessments.rb +0 -194
  78. data/lib/sakai-cle-test-api/assignments.rb +0 -113
  79. data/lib/sakai-cle-test-api/basic_lti.rb +0 -5
  80. data/lib/sakai-cle-test-api/blogs.rb +0 -5
  81. data/lib/sakai-cle-test-api/calendar.rb +0 -65
  82. data/lib/sakai-cle-test-api/calendar_summary.rb +0 -0
  83. data/lib/sakai-cle-test-api/common_page_elements.rb +0 -1228
  84. data/lib/sakai-cle-test-api/drop_box.rb +0 -0
  85. data/lib/sakai-cle-test-api/email_archive.rb +0 -10
  86. data/lib/sakai-cle-test-api/forums.rb +0 -39
  87. data/lib/sakai-cle-test-api/gradebook.rb +0 -10
  88. data/lib/sakai-cle-test-api/gradebook2.rb +0 -6
  89. data/lib/sakai-cle-test-api/messages.rb +0 -119
  90. data/lib/sakai-cle-test-api/news.rb +0 -9
  91. data/lib/sakai-cle-test-api/polls.rb +0 -24
  92. data/lib/sakai-cle-test-api/post_em.rb +0 -0
  93. data/lib/sakai-cle-test-api/profile.rb +0 -17
  94. data/lib/sakai-cle-test-api/profile2.rb +0 -43
  95. data/lib/sakai-cle-test-api/rwiki.rb +0 -0
  96. data/lib/sakai-cle-test-api/sections.rb +0 -47
  97. data/lib/sakai-cle-test-api/single_user.rb +0 -0
  98. data/lib/sakai-cle-test-api/site_page_elements.rb +0 -2350
  99. data/lib/sakai-cle-test-api/site_statistics.rb +0 -0
  100. data/lib/sakai-cle-test-api/syllabus.rb +0 -77
  101. data/lib/sakai-cle-test-api/tools_menu.rb +0 -415
@@ -0,0 +1,57 @@
1
+ #================
2
+ # User Membership Pages from Administration Workspace
3
+ #================
4
+
5
+ # User Membership page for admin users - "icon-sakai-usermembership"
6
+ class UserMembership < BasePage
7
+
8
+ frame_element
9
+
10
+ # Returns an array containing the user names displayed in the search results.
11
+ def names
12
+ names = []
13
+ frm.table(:class=>/listHier/).rows.each do |row|
14
+ names << row[2].text
15
+ end
16
+ names.delete_at(0)
17
+ return names
18
+ end
19
+
20
+ # Returns the user id of the specified user (assuming that person
21
+ # appears in the search results list, otherwise this method will
22
+ # throw an error.)
23
+ def user_id(name)
24
+ frm.table(:class=>/listHier/).row(:text=>/#{Regexp.escape(name)}/)[0].text
25
+ end
26
+
27
+ # Returns the user type of the specified user (assuming that person
28
+ # appears in the search results list, otherwise this method will
29
+ # throw an error.)
30
+ def type(name)
31
+ frm.table(:class=>/listHier/).row(:text=>/#{Regexp.escape(name)}/)[4].text
32
+ end
33
+
34
+ # Returns the text contents of the "instruction" paragraph that
35
+ # appears when there are no search results.
36
+ def alert_text
37
+ frm.p(:class=>"instruction").text
38
+ end
39
+
40
+ element(:user_type) { |b| b.frm.select_list(:id=>"userlistForm:selectType") }
41
+ element(:user_authority) { |b| b.frm.select_list(:id=>"userlistForm:selectAuthority") }
42
+ element(:search_field) { |b| b.frm.text_field(:id=>"userlistForm:inputSearchBox") }
43
+ action(:search) { |b| b.frm.button(:id=>"userlistForm:searchButton").click }
44
+ action(:clear_search) { |b| b.frm.button(:id=>"userlistForm:clearSearchButton").click }
45
+ element(:page_size) { |b| b.frm.select_list(:id=>"userlistForm:pager_pageSize") }
46
+ action(:export_csv) { |b| b.frm.button(:id=>"userlistForm:exportCsv").click }
47
+ action(:export_excel) { |b| b.frm.button(:id=>"userlistForm:exportXls").click }
48
+ action(:sort_user_id) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp14").click }
49
+ action(:sort_internal_user_id) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp18").click }
50
+ action(:sort_name) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp21").click }
51
+ action(:sort_email) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp24").click }
52
+ action(:sort_type) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp28").click }
53
+ action(:sort_authority) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp31").click }
54
+ action(:sort_created_on) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp34").click }
55
+ action(:sort_modified_on) { |b| b.frm.link(id=>"userlistForm:_idJsp13:_idJsp37").click }
56
+
57
+ end
@@ -0,0 +1,88 @@
1
+ #================
2
+ # Users Pages - From the Workspace
3
+ #================
4
+
5
+ # The Page for editing User Account details
6
+ class EditUser < BasePage
7
+
8
+ frame_element
9
+
10
+ def update_details
11
+ frm.button(:name=>"eventSubmit_doSave").click
12
+ sleep 1
13
+ end
14
+
15
+ action(:remove_user) { |b| b.frm.link(text=>"Remove User").click }
16
+ element(:first_name) { |b| b.frm.text_field(:id=>"first-name") }
17
+ element(:last_name) { |b| b.frm.text_field(:id=>"last-name") }
18
+ element(:email) { |b| b.frm.text_field(:id=>"email") }
19
+ element(:create_new_password) { |b| b.frm.text_field(:id=>"pw") }
20
+ element(:verify_new_password) { |b| b.frm.text_field(:id=>"pw0") }
21
+ action(:cancel_changes) { |b| b.frm.button(:name=>"eventSubmit_doCancel").click }
22
+
23
+ end
24
+
25
+ # The Users page - "icon-sakai-users"
26
+ class Users < BasePage
27
+
28
+ frame_element
29
+
30
+ def new_user
31
+ frm.link(:text=>"New User").click
32
+ CreateNewUser.new @browser
33
+ end
34
+
35
+ # Returns the contents of the Name cell
36
+ # based on the specified user ID value.
37
+ def name(user_id)
38
+ frm.table(:class=>"listHier lines").row(:text=>/#{Regexp.escape(user_id)}/i)[1].text
39
+ end
40
+
41
+ # Returns the contents of the Email cell
42
+ # based on the specified user ID value.
43
+ def email(user_id)
44
+ frm.table(:class=>"listHier lines").row(:text=>/#{Regexp.escape(user_id)}/i)[2].text
45
+ end
46
+
47
+ # Returns the contents of the Type cell
48
+ # based on the specified user ID value.
49
+ def type(user_id)
50
+ frm.table(:class=>"listHier lines").row(:text=>/#{Regexp.escape(user_id)}/i)[3].text
51
+ end
52
+
53
+ def search_button
54
+ frm.link(:text=>"Search").click
55
+ frm.table(:class=>"listHier lines").wait_until_present
56
+ Users.new @browser
57
+ end
58
+
59
+ action(:clear_search) { |b| b.frm.link(text=>"Clear Search").click }
60
+ element(:search_field) { |b| b.frm.text_field(:id=>"search") }
61
+ element(:select_page_size) { |b| b.frm.select_list(:name=>"selectPageSize") }
62
+ action(:next) { |b| b.frm.button(:name=>"eventSubmit_doList_next").click }
63
+ action(:last) { |b| b.frm.button(:name=>"eventSubmit_doList_last").click }
64
+ action(:previous) { |b| b.frm.button(:name=>"eventSubmit_doList_prev").click }
65
+ action(:first) { |b| b.frm.button(:name=>"eventSubmit_doList_first").click }
66
+
67
+ end
68
+
69
+
70
+ # The Create New User page
71
+ class CreateNewUser < BasePage
72
+
73
+ frame_element
74
+
75
+ def save_details
76
+ frm.button(:name=>"eventSubmit_doSave").click
77
+ Users.new(@browser)
78
+ end
79
+
80
+ element(:user_id) { |b| b.frm.text_field(:id=>"eid") }
81
+ element(:first_name) { |b| b.frm.text_field(:id=>"first-name") }
82
+ element(:last_name) { |b| b.frm.text_field(:id=>"last-name") }
83
+ element(:email) { |b| b.frm.text_field(:id=>"email") }
84
+ element(:create_new_password) { |b| b.frm.text_field(:id=>"pw") }
85
+ element(:verify_new_password) { |b| b.frm.text_field(:id=>"pw0") }
86
+ element(:type) { |b| b.frm.select_list(:name=>"type") }
87
+ action(:cancel_changes) { |b| b.frm.button(:name=>"eventSubmit_doCancel").click }
88
+ end
@@ -0,0 +1,27 @@
1
+ module FCKEditor
2
+
3
+ # This has to be defined this way because there several pages
4
+ # that have multiple rich text editors.
5
+ def source(editor)
6
+ editor.div(:title=>/Source/).wait_until_present
7
+ editor.div(:title=>/Source/).click
8
+ end
9
+
10
+ def select_all(editor)
11
+ editor.div(:title=>"Select All").wait_until_present
12
+ editor.div(:title=>"Select All").click
13
+ end
14
+
15
+ def enter_source_text(editor, text)
16
+ source(editor)
17
+ editor.text_field(:class=>"SourceField").wait_until_present
18
+ editor.text_field(:class=>"SourceField").set text
19
+ end
20
+
21
+ def get_source_text(editor)
22
+ source(editor)
23
+ editor.text_field(:class=>"SourceField").wait_until_present
24
+ editor.text_field(:class=>"SourceField").value
25
+ end
26
+
27
+ end
@@ -1,5 +1,260 @@
1
+ # coding: UTF-8
2
+
1
3
  module Utilities
2
4
 
5
+ # Creates a page object based on the class passed to it.
6
+ #
7
+ # @example using a page that has already been visited in a Scenario
8
+ # on_page MyPageObject do |page|
9
+ # page.name.should == 'rSmart'
10
+ # end
11
+ def on_page(page_class, &block)
12
+ @current_page = page_class.new(@browser)
13
+ block.call @current_page if block
14
+ @current_page
15
+ end
16
+
17
+ # Strips the file name away from the path information.
18
+ #
19
+ # This way it's not necessary to define variables for BOTH the
20
+ # file name and the file path + file name. Just define the
21
+ # path + name and then use this method to extract only the filename
22
+ # portion.
23
+ def get_filename(path_plus_name_string)
24
+ path_plus_name_string =~ /(?<=\/).+/
25
+ return $~.to_s
26
+ end
27
+
28
+ # A random string creator that draws from all printable ASCII characters
29
+ # from 33 to 128. Default length is 10 characters.
30
+ def random_string(length=10, s="")
31
+ length.enum_for(:times).inject(s) do |result, index|
32
+ s << rand(93) + 33
33
+ end
34
+ end
35
+
36
+ # A random string creator that draws from all printable ASCII and High ASCII characters
37
+ # from 33 to 256. Default length is 10 characters.
38
+ def random_high_ascii(length=10, s="")
39
+ length.enum_for(:times).inject(s) do |result, index|
40
+ s << rand(223) + 33
41
+ end
42
+ end
43
+
44
+ # A "friendlier" random string generator. No characters need to be escaped for valid URLs.
45
+ # Uses no Reserved or "Unsafe" characters.
46
+ # Also excludes the comma, the @ sign and the plus sign. Default length is 10 characters.
47
+ def random_nicelink(length=10)
48
+ 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 _ - .}
49
+ (0...length).map { chars[rand(chars.size)]}.join
50
+ end
51
+
52
+ # Returns a string that is properly formatted like an email address.
53
+ # The string returned defaults to 268 characters long.
54
+ # Including a number between 1 and 62 will shrink this string by 62 minus the specified
55
+ # value.
56
+ def random_email(x=62)
57
+ x > 62 ? x=62 : x=x
58
+ 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 ! # $ % & ' * + - / = ? ^ _ ` { | } ~}
59
+ random_alphanums(1) + (0...x).map { chars[rand(chars.size)]}.join + random_alphanums(1) + "@" + random_alphanums(60) + ".com"
60
+ end
61
+
62
+ # A random string generator that uses all characters
63
+ # available on an American Qwerty keyboard.
64
+ def random_alphanums_plus(length=10, s="")
65
+ 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 ` ~ ! @ # $% ^ & * ( ) _ + - = { } [ ] \ : " ; ' < > ? , . / }
66
+ length.times { s << chars[rand(chars.size)] }
67
+ s.to_s
68
+ end
69
+
70
+ # A random string generator that uses only letters and numbers in the string. Default length is 10 characters.
71
+ def random_alphanums(length=10, s="")
72
+ chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
73
+ length.times { s << chars[rand(chars.size)] }
74
+ s.to_s
75
+ end
76
+
77
+ # A random string generator that uses only lower case letters.
78
+ def random_letters(length=10, s="")
79
+ chars = 'abcdefghjkmnpqrstuvwxyz'
80
+ length.times { s << chars[rand(chars.size)] }
81
+ s.to_s
82
+ end
83
+
84
+ # Returns a block of text (of the specified type, see below) containing
85
+ # the specified number of "words" (each containing between 1 and 16 chars)
86
+ # randomly spread across the specified number of lines (note that
87
+ # the method does not allow the line count to be larger than
88
+ # the word count and will "fix" it if it is).
89
+ #
90
+ # If no arguments are provided, the method will return two alphanumeric
91
+ # "words" on two lines.
92
+ #
93
+ # The last argument the method takes will determine the character content
94
+ # of the string, viz.:
95
+ #
96
+ # :alpha => Alphanumeric -> uses the random_alphanums method
97
+ # :string => uses the random_string method, so chars 33 through 128 will be included
98
+ # :ascii => All ASCII chars from 33 to 256 are fair game -> uses random_high_ascii
99
+ def random_multiline(word_count=2, line_count=2, char_type=:alpha)
100
+ char_methods = {:alpha=>"random_alphanums(rand(16)+1)", :string=>"random_string(rand(16)+1)", :ascii=>"random_high_ascii(rand(16)+1)"}
101
+ if line_count > word_count
102
+ line_count = word_count - 1
103
+ end
104
+ words = []
105
+ non_words = []
106
+ word_count.times { words << eval(char_methods[char_type]) } # creating the words, adding to the array
107
+ (line_count - 1).times { non_words << "\n" } # adding the number of line feeds
108
+ unless word_count==line_count
109
+ (word_count - line_count - 1).times { non_words << " " } # adding the right number of spaces
110
+ end
111
+ non_words.shuffle! # Have to shuffle the line feeds around!
112
+ array = words.zip(non_words)
113
+ array.flatten!
114
+ return array.join("")
115
+ end
116
+
117
+ # Picks at random from the list of XSS test strings, using
118
+ # the provided number as size of the list to choose from.
119
+ # It will randomly pre-pend the string with HTML closing tags.
120
+ #
121
+ # The strings are organized by length, with the shorter ones
122
+ # first. There are 102 strings.
123
+ def random_xss_string(number=102)
124
+ if number > 102
125
+ number = 102
126
+ end
127
+ 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&#x0D;ascript:alert('XSS');\">", "<IMG SRC=\"jav&#x0A;ascript:alert('XSS');\">", "<XSS STYLE=\"xss:expression(alert('XSS'))\">", "<IMG SRC=\"jav&#x09;ascript:alert('XSS');\">", "<SCRIPT SRC=http://ha.ckers.org/xss.js?<B>", "<IMG SRC=\" &#14; javascript:alert('XSS');\">", "<IMG SRC=javascript:alert(&quot;XSS&quot;)>", "<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(&#1;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=&lt;SCRIPT&gt;alert('XSS')&lt;/SCRIPT&gt;\">", "exp/*<A STYLE='no\\xss:noxss(\"*//*\"); xss:&#101;x&#x2F;*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=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>", "<HEAD><META HTTP-EQUIV=\"CONTENT-TYPE\" CONTENT=\"text/html; charset=UTF-7\"> </HEAD>+ADw-SCRIPT+AD4-alert('XSS');+ADw-/SCRIPT+AD4-", "<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>", "<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>&lt;IMG SRC=\"javas<!-- -->cript:alert('XSS')\"&gt;</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=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>", "';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&lt;SCRIPT DEFER&gt;alert(&quot;XSS&quot;)&lt;/SCRIPT&gt;\"> </BODY></HTML>", "<EMBED SRC=\"data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==\" type=\"image/svg+xml\" AllowScriptAccess=\"always\"></EMBED>"]
128
+ x = rand(4)
129
+ case(x)
130
+ when 0
131
+ return xss[rand(number)]
132
+ when 1
133
+ return %|"| + xss[rand(number)]
134
+ when 2
135
+ return %|">| + xss[rand(number)]
136
+ when 3
137
+ return %|>| + xss[rand(number)]
138
+ end
139
+
140
+ end
141
+
142
+ # Some date and time helper functions....
143
+
144
+ # Returns the value of the last hour as an Integer object, which
145
+ # eliminates the zero-padding for single-digit hours. 12-hour clock.
146
+ def last_hour
147
+ (Time.now - 3600).strftime("%I").to_i
148
+ end
149
+
150
+ # Returns the value of the current hour as an Integer object, which
151
+ # eliminates the zero-padding for single-digit hours. 12-hour clock.
152
+ def current_hour
153
+ Time.now.strftime("%I").to_i
154
+ end
155
+
156
+ # Returns the value of the next hour as an Integer object, which
157
+ # eliminates the zero-padding for single-digit hours. 12-hour clock.
158
+ def next_hour
159
+ (Time.now + 3600).strftime("%I").to_i
160
+ end
161
+
162
+ # Returns a 4-digit Integer object, equal to last year.
163
+ def last_year
164
+ (Time.now - (3600*24*365)).strftime("%Y").to_i
165
+ end
166
+
167
+ # Returns a 4-digit Integer object equal to the current year.
168
+ def current_year
169
+ (Time.now).strftime("%Y").to_i
170
+ end
171
+
172
+ # Returns an all-caps 3-char string equal to the prior month
173
+ def last_month
174
+ months = ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]
175
+ index = months.index(current_month)
176
+ return months[index-1]
177
+ end
178
+
179
+ # Returns an all-caps 3-char string equal to the current month
180
+ def current_month
181
+ Time.now.strftime("%^b")
182
+ end
183
+
184
+ # Returns an all-caps 3-char string equal to next month
185
+ def next_month
186
+ months = ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]
187
+ index = months.index(current_month)
188
+ if index < 12
189
+ return months[index+1]
190
+ else
191
+ return months[0]
192
+ end
193
+ end
194
+
195
+ # Returns a 4-digit Integer object equal to next year.
196
+ def next_year
197
+ (Time.now + (3600*24*365)).strftime("%Y").to_i
198
+ end
199
+
200
+ # Returns an Integer object equal to
201
+ # yesterday's day of the month. The string is converted to
202
+ # an integer so as to remove the zero-padding from single-digit day values.
203
+ def yesterday
204
+ (Time.now - (3600*24)).strftime("%d").to_i
205
+ end
206
+
207
+ # Returns an Integer object equal to
208
+ # tomorrow's day of the month. The string is converted to
209
+ # an integer so as to remove the zero-padding from single-digit day values.
210
+ def tomorrow
211
+ (Time.now + (3600*24)).strftime("%d").to_i
212
+ end
213
+
214
+ # Takes a time object as the input (e.g., Time.now) and returns
215
+ # a string formatted in particular ways.
216
+ # When the specified "type" value is "cle" (or not specified),
217
+ # The returned string will look like this:
218
+ # "Jan 9, 2012 1:12 am"
219
+ # When "oae-message":
220
+ # "2/8/2012 1:06 PM"
221
+ # Note the lack of zero-padding for the day of the month and the
222
+ # hour of the day. The hour value will be for a 12-hour clock.
223
+ def make_date(time_object, type="cle")
224
+ case(type)
225
+ when "cle"
226
+ month = time_object.strftime("%b ")
227
+ day = time_object.strftime("%d").to_i
228
+ year = time_object.strftime(", %Y ")
229
+ mins = time_object.strftime(":%M %P")
230
+ hour = time_object.strftime("%l").to_i
231
+ return month + day.to_s + year + hour.to_s + mins
232
+ when "oae-message"
233
+ date = time_object.strftime("%-m/%-d/%Y ")
234
+ hour = time_object.strftime("%l").to_i
235
+ mins = time_object.strftime(":%M %p")
236
+ return date + hour.to_s + mins
237
+ end
238
+
239
+ end
240
+
241
+ # returns a hash object containing strings that will, for example,
242
+ # allow creation of an event starting 15 minutes in the future.
243
+ # Hour and Day values are Integer objects, not strings, so that
244
+ # they will not be zero-padded. The :meridian string is lower-case.
245
+ def in_15_minutes
246
+ t = Time.now.utc+15*60
247
+ return {
248
+ :month_str => t.strftime("%^b"),
249
+ :month_int => t.strftime("%-m"),
250
+ :day =>t.strftime("%d").to_i,
251
+ :year =>t.strftime("%Y").to_i,
252
+ :hour =>t.strftime("%I").to_i,
253
+ :minute =>(t-t.sec-t.min%5*60).strftime("%M"),
254
+ :meridian =>t.strftime("%P")
255
+ }
256
+ end
257
+
3
258
  # Formats a date string Sakai-style.
4
259
  # Useful for verifying creation dates and such.
5
260
  #
@@ -13,4 +268,9 @@ module Utilities
13
268
  return month + day.to_s + year + hour.to_s + mins
14
269
  end
15
270
 
271
+ # Shorthand method for making a data object for testing.
272
+ def make data_object_class, opts={}
273
+ data_object_class.new @browser, opts
274
+ end
275
+
16
276
  end
@@ -0,0 +1,224 @@
1
+ # Workflows is a module containing helper navigation methods
2
+ module Workflows
3
+
4
+ def self.menu_link name, opts={}
5
+ define_method name.to_s do
6
+ @browser.link(opts).click
7
+ end
8
+ end
9
+
10
+ # Opens "My Sites" and then clicks on the matching
11
+ # Site name. Shortens the name used for search so
12
+ # that truncated names are not a problem.
13
+ # Should be followed by the Home class.
14
+ #
15
+ # Will error out if there are not matching links.
16
+ def open_my_site_by_name(name)
17
+ truncated_name = name[0..19]
18
+ @browser.link(:text, "My Sites").click
19
+ @browser.link(:text, /#{Regexp.escape(truncated_name)}/).click
20
+ end
21
+
22
+ # Clicks the "Account" link in the Adminstration Workspace
23
+ # Should be followed by the UserAccount class.
24
+ #
25
+ # Throws an error if the link is not present.
26
+ menu_link :account, :text=>"Account"
27
+
28
+ # Clicks the "Aliases" link in the Administration Workspace
29
+ # menu, then should be followed by the Aliases class.
30
+ menu_link :aliases, :text=>"Aliases"
31
+
32
+ # Clicks the link for the Administration Workspace, then
33
+ # should be followed by the MyWorkspace class.
34
+ menu_link :administration_workspace, :text=>"Administration Workspace"
35
+
36
+ # Clicks the Announcements link goes to
37
+ # the Announcements class.
38
+ menu_link :announcements, :class=>'icon-sakai-announcements'
39
+
40
+ # Clicks the Assignments link, goes to
41
+ # the AssignmentsList class.
42
+ menu_link :assignments, :class=>"icon-sakai-assignment-grades"
43
+
44
+ # BasicLTI class
45
+ menu_link :basic_lti, :class=>"icon-sakai-basiclti"
46
+
47
+ # Blogs class
48
+ menu_link :blogs, :class=>"icon-sakai-blogwow"
49
+
50
+ # Clicks the Blogger link in the Site menu and
51
+ # instantiates the Blogger Class.
52
+ menu_link :blogger, :class=>"icon-blogger"
53
+
54
+ # Clicks the Calendar link, then instantiates
55
+ # the Calendar class.
56
+ menu_link :calendar, :text=>"Calendar"
57
+
58
+ menu_link :certification, :text=>"Certification"
59
+
60
+ # ChatRoom class
61
+ menu_link :chat_room, :class=>"icon-sakai-chat"
62
+
63
+ menu_link :configuration_viewer, :text=>"Configuration Viewer"
64
+ menu_link :customizer, :text=>"Customizer"
65
+
66
+ # JForum page class.
67
+ menu_link :discussion_forums, :class=>"icon-sakai-jforum-tool"
68
+
69
+ # DropBox class
70
+ menu_link :drop_box, :class=>"icon-sakai-dropbox"
71
+
72
+ menu_link :email, :text=>"Email"
73
+
74
+ # Email Archive class
75
+ menu_link :email_archive, :class=>"icon-sakai-mailbox"
76
+
77
+ menu_link :email_template_administration, :text=>"Email Template Administration"
78
+
79
+ # EvaluationSystem class
80
+ menu_link :evaluation_system, :class=>"icon-sakai-rsf-evaluation"
81
+
82
+ # Feedback class
83
+ menu_link :feedback, :class=>"icon-sakai-postem"
84
+
85
+ # Forms class
86
+ menu_link :forms, :text=>"Forms", :class=>"icon-sakai-metaobj"
87
+
88
+ # Forums class.
89
+ menu_link :forums, :text=>"Forums"
90
+
91
+ # Glossary Class.
92
+ menu_link :glossary, :text=>"Glossary"
93
+
94
+ # Gradebook Class.
95
+ menu_link :gradebook, :text=>"Gradebook"
96
+
97
+ # Gradebook2 class
98
+ menu_link :gradebook2, :text=>"Gradebook2"
99
+
100
+ menu_link :help, :text=>"Help"
101
+
102
+ # Home class--unless the target page happens to be
103
+ # My Workspace, in which case the MyWorkspace
104
+ # page should be used.
105
+ menu_link :home, :text=>"Home"
106
+
107
+ # Job Scheduler class.
108
+ menu_link :job_scheduler, :text=>"Job Scheduler"
109
+
110
+ # Lessons class
111
+ menu_link :lessons, :text=>"Lessons"
112
+
113
+ menu_link :lesson_builder, :text=>"Lesson Builder"
114
+ menu_link :link_tool, :text=>"Link Tool"
115
+ menu_link :live_virtual_classroom, :text=>"Live Virtual Classroom"
116
+
117
+ # Matrices Class
118
+ menu_link :matrices, :text=>"Matrices"
119
+
120
+ # MediaGallery class
121
+ menu_link :media_gallery, :class=>"icon-sakai-kaltura"
122
+
123
+ menu_link :membership, :text=>"Membership"
124
+ menu_link :memory, :text=>"Memory"
125
+
126
+ # Messages class.
127
+ menu_link :messages, :text=>"Messages"
128
+
129
+ menu_link :my_sites, :text=>"My Sites"
130
+
131
+ # MyWorkspace Class.
132
+ menu_link :my_workspace, :text=>"My Workspace"
133
+
134
+ # News
135
+ menu_link :news, :class=>"icon-sakai-news"
136
+
137
+ menu_link :online, :text=>"On-Line"
138
+ menu_link :oauth_providers, :text=>"Oauth Providers"
139
+ menu_link :oauth_tokens, :text=>"Oauth Tokens"
140
+ menu_link :openSyllabus, :text=>"OpenSyllabus"
141
+
142
+ # Podcasts
143
+ menu_link :podcasts, :class=>"icon-sakai-podcasts"
144
+
145
+ # Polls class
146
+ menu_link :polls, :class=>"icon-sakai-poll"
147
+
148
+ # Portfolios class
149
+ menu_link :portfolios, :class=>"icon-osp-presentation"
150
+
151
+ # PortfolioTemplates
152
+ menu_link :portfolio_templates, :text=>"Portfolio Templates"
153
+
154
+ menu_link :preferences, :text=>"Preferences"
155
+
156
+ menu_link :profile, :text=>"Profile"
157
+
158
+ # Profile2 class
159
+ menu_link :profile2, :class=>"icon-sakai-profile2"
160
+
161
+ menu_link :realms, :text=>"Realms"
162
+
163
+ # Resources class.
164
+ menu_link :resources, :text=>"Resources"
165
+
166
+ # Roster
167
+ menu_link :roster, :class=>"icon-sakai-site-roster"
168
+
169
+ menu_link :rsmart_support, :text=>"rSmart Support"
170
+
171
+ # Because "Search" is used in many pages,
172
+ # The Search button found in the Site Management
173
+ # Menu must be given the more explicit name
174
+ menu_link :site_management_search, :class=>"icon-sakai-search"
175
+
176
+ # Sections
177
+ menu_link :sections, :class=>"icon-sakai-sections"
178
+
179
+ menu_link :site_archive, :text=>"Site Archive"
180
+
181
+ # SiteEditor class.
182
+ menu_link :site_editor, :text=>"Site Editor"
183
+
184
+ # SiteSetup class.
185
+ menu_link :site_setup, :text=>"Site Setup"
186
+
187
+ menu_link :site_statistics, :text=>"Site Statistics"
188
+
189
+ # Sites class.
190
+ menu_link :sites, :class=>"icon-sakai-sites"
191
+
192
+ menu_link :skin_manager, :text=>"Skin Manager"
193
+ menu_link :super_user, :text=>"Super User"
194
+
195
+ # Styles
196
+ menu_link :styles, :text=>"Styles"
197
+
198
+ # Syllabus class.
199
+ menu_link :syllabus, :text=>"Syllabus"
200
+
201
+ # AssessmentsList class OR the TakeAssessmentList for students
202
+ menu_link :assessments, :class=>"icon-sakai-samigo"
203
+
204
+ # UserMembership
205
+ menu_link :user_membership, :class=>"icon-sakai-usermembership"
206
+
207
+ # Users
208
+ menu_link :users, :class=>"icon-sakai-users"
209
+
210
+ # WebContent
211
+ menu_link :web_content, :class=>"icon-sakai-iframe"
212
+
213
+ # Wikis
214
+ menu_link :wiki, :class=>"icon-sakai-rwiki"
215
+
216
+ # The Page Reset button, found on all Site pages
217
+ menu_link :reset, :href=>/tool-reset/
218
+
219
+ # Login class.
220
+ menu_link :logout, :text=>"Logout"
221
+ alias :log_out :logout
222
+ alias :sign_out :logout
223
+
224
+ end