test-factory 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,146 @@
1
+ rSmart's Test Factory Gem
2
+ =========================
3
+
4
+ Overview
5
+ --------
6
+
7
+ This gem contains the basic framework for [dryly](http://en.wikipedia.org/wiki/Don%27t_repeat_yourself) creating test scripts for the web site that needs testing.
8
+
9
+ Use it to abstract away from the underlying [Watir](http://www.watir.com) code and create your own [DSL](http://en.wikipedia.org/wiki/Domain_specific_language).
10
+
11
+ How to Start
12
+ ------------
13
+
14
+ First install the gem, of course.
15
+
16
+ gem install test-factory
17
+
18
+ Now you'll want to start building your own page classes, using the methods in Test Factory as your tool chest.
19
+
20
+ Please note that the following example is *very* simplified and contrived, to keep every step as compartmentalized as possible. Once you've read through this, it is strongly recommended that you visit an actual repository that is using the test factory.
21
+
22
+ [Here](https://github.com/rSmart/sambal-cle) is one such.
23
+
24
+ Begin by creating a BasePage class. This class should inherit from PageFactory and contain sets of elements that are generally common across the pages of your site.
25
+
26
+ ```ruby
27
+ require 'test-factory'
28
+
29
+ class BasePage < PageFactory
30
+
31
+ class << self
32
+
33
+ def header_elements
34
+ element(:main_menu) { |b| b.link(title: "Main Menu") }
35
+ element(:logout) { |b| b.button(value: "Logout") }
36
+ element(:administration) { |b| b.link(title: "Administration") }
37
+
38
+ action(:main_menu) { |p| p.main_menu.click }
39
+ action(:provide_feedback) { |b| b.link(title: "Provide Feedback").click }
40
+ action(:administration) { |p| p.administration.click }
41
+ end
42
+ end
43
+ end
44
+
45
+ ```
46
+
47
+ Next, you create classes for the individual pages in your web site. These classes should inherit from your BasePage class, and should use any of the relevant methods defined in the BasePage class.
48
+
49
+ ```ruby
50
+ class Home < BasePage
51
+
52
+ # This allows the header elements to be defined once
53
+ # in the BasePage class and then reused throughout your web pages...
54
+ header_elements
55
+
56
+ expected_element :title # When the Home class is instantiated (using the Foundry),
57
+ # the script will ensure that the :title element is present
58
+ # on the page before the script continues
59
+
60
+ # Now you define elements that are specific to your Home page...
61
+ element(:title) { |b| b.h3(id: "title") }
62
+ # and on and on...
63
+
64
+ end
65
+ ```
66
+
67
+ Once you've got a bunch of classes set up for your site's various pages, you're going to want to create "data objects" to represent what goes into those pages. For this, you'll use the module DataObject. Your data classes should follow this basic structure:
68
+
69
+ ```ruby
70
+ class YourDataObject
71
+
72
+ include DataFactory
73
+
74
+ # Define all the things you need to test about your data object.
75
+ # These are some example attributes...
76
+ attr_accessor :title, :id, :link, :status, :description
77
+
78
+ # Your data object has to know about Watir's browser object, so it's passed to it here, along
79
+ # with a hash containing all the attributes you want the data object to have
80
+ def initialize(browser, opts={})
81
+ @browser = browser
82
+
83
+ # Put any attributes here that you don't want to always have to define explicitly...
84
+ defaults = {
85
+ :title=>"My Data Title",
86
+ :description=>"My Data's Description"
87
+ }
88
+ options = defaults.merge(opts) # This line combines the defaults
89
+ # with any options you passed explicitly
90
+ set_options(options) # This line turns all the contents of the options
91
+ # Hash into YourDataObject's class instance variables
92
+ requires :id # This line allows you to specify any attributes that must
93
+ # be explicitly defined for the data object
94
+ end
95
+
96
+ # Now define a bunch of methods that are relevant to your data object.
97
+ # In general these methods will follow the CRUD pattern
98
+
99
+ def create
100
+ # Your code here...
101
+ end
102
+
103
+ def view
104
+ # Your code here...
105
+ end
106
+
107
+ def edit opts={}
108
+ # Your code here...
109
+ set_options(opts) # This updates all your class instance variables
110
+ # with any new values specified by the opts Hash.
111
+ end
112
+
113
+ def remove
114
+ # Your code here...
115
+ end
116
+
117
+ end
118
+ ```
119
+
120
+ Now you have your basic infrastructure in place, and you can start writing your test cases using these classes.
121
+
122
+ ```ruby
123
+ include Foundry # Gives you access to the methods that instantiate your Page and Data classes
124
+
125
+ # First, make the data object you're going to use for testing...
126
+ @my_thing = make YourDataObject :id=>"identifier", :description=>"It's lovely."
127
+
128
+ # Now, create the data in your site...
129
+ @my_thing.create
130
+
131
+ on MyPage do |page|
132
+ page.title.set "Bla bla"
133
+ # Very contrived example. You should be using your favorite verification framework here:
134
+ page.description==@my_thing.description ? puts "Passed" : puts "Failed"
135
+ end
136
+
137
+ ```
138
+
139
+ Notice
140
+ ------
141
+
142
+ Copyright 2012 rSmart, Inc., Licensed under the Educational Community License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
143
+
144
+ [http://www.osedu.org/licenses/ECL-2.0](http://www.osedu.org/licenses/ECL-2.0)
145
+
146
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
@@ -0,0 +1,2 @@
1
+ require 'watir-webdriver'
2
+ Dir["#{File.dirname(__FILE__)}/test-factory/*.rb"].each {|f| require f }
@@ -0,0 +1,90 @@
1
+ class Time
2
+
3
+ # Using the :year_range option (or no option), this method creates a
4
+ # Time object of a random value, within
5
+ # the year range specified (default is 5 years in the past).
6
+ #
7
+ # Using the :series option, this method returns an array
8
+ # containing a randomized Time object as its first element (limited by
9
+ # the specified :year_range value). Subsequent elements will be Time objects
10
+ # with values putting them later than the prior element, within the specified
11
+ # range value (see examples).
12
+ #
13
+ # Usage Examples:
14
+ # @example
15
+ # a random date...
16
+ # ?> Time.random
17
+ # => Tue Aug 05 00:00:00 EDT 2007
18
+ #
19
+ # birthdays, anyone?...
20
+ # 5.times { p Time.random(:year_range=>80) }
21
+ # Wed Feb 06 00:00:00 EDT 1974
22
+ # Tue Dec 22 00:00:00 EST 1992
23
+ # Fri Apr 14 00:00:00 EWT 1944
24
+ # Thu Jul 01 00:00:00 EDT 1993
25
+ # Wed Oct 02 00:00:00 EDT 2002
26
+ #
27
+ # A series of dates are useful for account-related info...
28
+ # ?> Time.random(:series=>[20.days, 3.years])
29
+ # => [Sat Jan 22 00:00:00 EST 2005,
30
+ # Sat Jan 29 12:58:45 EST 2005,
31
+ # Fri Sep 08 09:34:58 EDT 2006]
32
+ #
33
+ # or maybe to simulate events during an hour?...
34
+ # ?> Time.random(:series=>[1.hour,1.hour,1.hour])
35
+ # => [Wed Apr 21 00:00:00 EDT 2004,
36
+ # Wed Apr 21 00:45:59 EDT 2004,
37
+ # Wed Apr 21 01:02:47 EDT 2004,
38
+ # Wed Apr 21 01:31:00 EDT 2004]
39
+ def self.random(params={})
40
+ years_back = params[:year_range] || 5
41
+ year = (rand * (years_back)).ceil + (Time.now.year - years_back)
42
+ month = (rand * 12).ceil
43
+ day = (rand * 31).ceil
44
+ series = [date = Time.local(year, month, day)]
45
+ if params[:series]
46
+ params[:series].each do |some_time_after|
47
+ series << series.last + (rand * some_time_after).ceil
48
+ end
49
+ return series
50
+ end
51
+ date
52
+ end
53
+
54
+ end # Time
55
+
56
+ module Enumerable
57
+
58
+ # Use for getting a natural sort order instead of the ASCII
59
+ # sort order.
60
+ def alphabetize
61
+ sort { |a, b| grouped_compare(a, b) }
62
+ end
63
+
64
+ # Use for sorting an Enumerable object in place.
65
+ def alphabetize!
66
+ sort! { |a, b| grouped_compare(a, b) }
67
+ end
68
+
69
+ private
70
+ def grouped_compare(a, b)
71
+ loop {
72
+ a_chunk, a = extract_alpha_or_number_group(a)
73
+ b_chunk, b = extract_alpha_or_number_group(b)
74
+ ret = a_chunk <=> b_chunk
75
+ return -1 if a_chunk == ''
76
+ return ret if ret != 0
77
+ }
78
+ end
79
+
80
+ def extract_alpha_or_number_group(item)
81
+ test_item = item.downcase
82
+ matchdata = /([a-z]+|[\d]+)/.match(test_item)
83
+ if matchdata.nil?
84
+ ["", ""]
85
+ else
86
+ [matchdata[0], test_item = test_item[matchdata.offset(0)[1] .. -1]]
87
+ end
88
+ end
89
+
90
+ end # Enumerable
@@ -0,0 +1,38 @@
1
+ # Provides a set of tools used to create your Data Object classes.
2
+ module DataFactory
3
+
4
+ # Add this to the bottom of your Data Object's initialize method.
5
+ # Converts the contents of the hash into the class's instance variables.
6
+ # @param hash [Hash] Contains all options required for creating the needed Data Object
7
+ def set_options(hash)
8
+ hash.each do |key, value|
9
+ instance_variable_set("@#{key}", value)
10
+ end
11
+ end
12
+ alias update_options set_options
13
+
14
+ # Items passed to this method are checked to ensure that the associated class instance variable
15
+ # is not nil. If it is, the script is aborted and an error is thrown, describing what information
16
+ # the Data Object requires before the script can run.
17
+ # @param elements [Array] the list of items that are required.
18
+ #
19
+ # @example
20
+ #
21
+ # requires :site :assignment
22
+ #
23
+ def requires(*elements)
24
+ elements.each do |inst_var|
25
+ raise "You must explicitly define the #{inst_var} variable for the #{self}." if inst_var==nil
26
+ end
27
+ end
28
+
29
+ # Transform for use with data object instance variables
30
+ # that refer to checkboxes or radio buttons.
31
+ # @param checkbox [Watir::CheckBox] The checkbox on the page that you want to inspect
32
+ # @returns :set or :clear
33
+ def checkbox_setting(checkbox)
34
+ checkbox.set? ? :set : :clear
35
+ end
36
+ alias radio_setting checkbox_setting
37
+
38
+ end
@@ -0,0 +1,137 @@
1
+ # Some date and time helper functions....
2
+ module DateFactory
3
+
4
+ MONTHS = %w{JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC}
5
+
6
+ def an_hour_ago
7
+ date_factory(Time.now - 3600)
8
+ end
9
+ alias last_hour an_hour_ago
10
+
11
+ def right_now
12
+ date_factory(Time.now)
13
+ end
14
+
15
+ def in_an_hour
16
+ date_factory(Time.now + 3600)
17
+ end
18
+ alias next_hour in_an_hour
19
+
20
+ def last_year
21
+ date_factory(Time.now - (3600*24*365))
22
+ end
23
+ alias a_year_ago last_year
24
+
25
+ # Returns a randomly selected date/time from
26
+ # within the last year.
27
+ def in_the_last_year
28
+ date_factory(Time.random(:year_range=>1))
29
+ end
30
+
31
+ def last_month
32
+ index = MONTHS.index(current_month)
33
+ return MONTHS[index-1]
34
+ end
35
+
36
+ def hours_ago(hours)
37
+ date_factory(Time.now - hours*3600)
38
+ end
39
+
40
+ def hours_from_now(hours)
41
+ date_factory(Time.now + hours*3600)
42
+ end
43
+
44
+ # Takes an integer representing
45
+ # the count of minutes as the parameter, and
46
+ # returns the date_factory hash for the
47
+ # resulting Time value.
48
+ def minutes_ago(mins)
49
+ date_factory(Time.now - mins*60)
50
+ end
51
+
52
+ def minutes_from_now(mins)
53
+ date_factory(Time.now + mins*60)
54
+ end
55
+
56
+ # Returns the current month as an
57
+ # upper-case 3-letter string.
58
+ # example: "JUL"
59
+ def current_month
60
+ Time.now.strftime("%^b")
61
+ end
62
+
63
+ def next_month
64
+ index = MONTHS.index(current_month)
65
+ if index < 11
66
+ return MONTHS[index+1]
67
+ else
68
+ return MONTHS[0]
69
+ end
70
+ end
71
+
72
+ def in_a_year
73
+ date_factory(Time.now + (3600*24*365))
74
+ end
75
+
76
+ def yesterday
77
+ date_factory(Time.now - (3600*24))
78
+ end
79
+
80
+ def tomorrow
81
+ date_factory(Time.now + (3600*24))
82
+ end
83
+
84
+ def in_a_week
85
+ date_factory(Time.now + (3600*24*7))
86
+ end
87
+ alias next_week in_a_week
88
+
89
+ def a_week_ago
90
+ date_factory(Time.now - (3600*24*7))
91
+ end
92
+
93
+ def next_monday
94
+ date_factory(Time.at(Time.now+(8-Time.now.wday)*24*3600))
95
+ end
96
+
97
+ # Formats a date string Sakai-style.
98
+ # Useful for verifying creation dates and such.
99
+ #
100
+ # @param time_object [Time] the moment that you want converted to the string
101
+ # @returns [String] a date formatted to look like this: Jun 8, 2012 12:02 pm
102
+ def make_date(time_object)
103
+ month = time_object.strftime("%b ")
104
+ day = time_object.strftime("%-d")
105
+ year = time_object.strftime(", %Y ")
106
+ mins = time_object.strftime(":%M %P")
107
+ hour = time_object.strftime("%l").to_i
108
+ return month + day + year + hour.to_s + mins
109
+ end
110
+
111
+ # Takes a time object and returns a hash containing
112
+ # various parts of the relevant date.
113
+ # @param time_object [Time] the moment you want to convert
114
+ # @returns [Hash] a hash object containing various parts of the date/time you passed to the method
115
+ def date_factory(time_object)
116
+ {
117
+ :sakai=>make_date(time_object),
118
+ :sakai_rounded=>make_date(time_object).gsub!(/:\d+/, ":#{Time.at(time_object.to_i/(5*60)*(5*60)).strftime("%M")}"), # Date with time rounded to nearest 5-minute mark.
119
+ :short_date=>time_object.strftime("%b %-d, %Y"), # => "Oct 18, 2013"
120
+ :samigo=>time_object.strftime("%m/%d/%Y %I:%M:%S %p"), # => "10/30/2012 07:02:05 AM"
121
+ :MON => time_object.strftime("%^b"), # => "DEC"
122
+ :Mon => time_object.strftime("%b"), # => "Jan"
123
+ :Month => time_object.strftime("%B"), # => "February"
124
+ :month_int => time_object.month, # => 3
125
+ :day_of_month => time_object.day, # => 17 Note this is not zero-padded
126
+ :weekday => time_object.strftime("%A"), # => "Monday"
127
+ :wkdy => time_object.strftime("%a"), # => "Tue"
128
+ :year => time_object.year, # => 2013
129
+ :hour => time_object.strftime("%I").to_i, # => "07" Zero-padded, 12-hour clock
130
+ :minute => (time_object).strftime("%M"), # => "02" Zero-padded
131
+ :minute_rounded => (Time.at(time_object.to_i/(5*60)*(5*60))).strftime("%M"), # => "05" Zero-padded, rounded to 5-minute increments
132
+ :meridian => time_object.strftime("%P"), # => "pm"
133
+ :MERIDIAN => time_object.strftime("%p") # => "AM"
134
+ }
135
+ end
136
+
137
+ end
@@ -0,0 +1,45 @@
1
+ # This module provides methods that instantiate the page and data classes.
2
+ module Foundry
3
+
4
+ # Using the page_url defined in the provided page_class,
5
+ # this method will enter that url into the browser's address bar, then run the block of
6
+ # code that you specify.
7
+ # @param page_class [Class] the name of the page class that you want to instantiate
8
+ # @param &block [C] this is the block of code that you want to run while on the given page
9
+ def visit page_class, &block
10
+ on page_class, true, &block
11
+ end
12
+
13
+ # Instantiates the supplied page class, then runs the supplied block of code. Use this
14
+ # method when you are already on the site page you want to interact with.
15
+ # @param page_class [Class] the name of the page class that you want to instantiate
16
+ # @param visit [TrueClass, FalseClass] Essentially you will never have to specify this explicitly
17
+ def on page_class, visit=false, &block
18
+ @current_page = page_class.new @browser, visit
19
+ block.call @current_page if block
20
+ @current_page
21
+ end
22
+ alias on_page on
23
+
24
+ # Use this for making a data object in your test steps
25
+ #
26
+ # @param data_object_class [Class] The name of the class you want to use to build a data object for testing
27
+ # @param opts [Hash] The list of attributes you want to give to your data object
28
+ def make data_object_class, opts={}
29
+ data_object_class.new @browser, opts
30
+ end
31
+
32
+ # A helper method that takes a block of code and waits until it resolves to true.
33
+ # Useful when you need to wait for something to be on a page that's a little more
34
+ # involved than a simple element (for those, you should use the #expected_element
35
+ # method found in the PageFactory class)
36
+ # @param timeout [Fixnum] Defaults to 30 seconds
37
+ # @param message [String] The text thrown if the timeout is reached
38
+ #
39
+ # @example
40
+ # page.wait_until { |b| b.processing_message=="Done" }
41
+ def wait_until(timeout=30, message=nil, &block)
42
+ Object::Watir::Wait.until(timeout, message, &block)
43
+ end
44
+
45
+ end
@@ -0,0 +1,54 @@
1
+ class PageFactory
2
+
3
+ def initialize browser, visit = false
4
+ @browser = browser
5
+ goto if visit
6
+ expected_element if respond_to? :expected_element
7
+ has_expected_title? if respond_to? :has_expected_title?
8
+ end
9
+
10
+ def method_missing sym, *args, &block
11
+ @browser.send sym, *args, &block
12
+ end
13
+
14
+ class << self
15
+
16
+ def page_url url
17
+ define_method 'goto' do
18
+ @browser.goto url
19
+ end
20
+ end
21
+
22
+ def expected_element element_name, timeout=30
23
+ define_method 'expected_element' do
24
+ self.send(element_name).wait_until_present timeout
25
+ end
26
+ end
27
+
28
+ def expected_title expected_title
29
+ define_method 'has_expected_title?' do
30
+ has_expected_title = expected_title.kind_of?(Regexp) ? expected_title =~ @browser.title : expected_title == @browser.title
31
+ raise "Expected title '#{expected_title}' instead of '#{@browser.title}'" unless has_expected_title
32
+ end
33
+ end
34
+
35
+ def element element_name
36
+ raise "#{element_name} is being defined twice in #{self}!" if self.instance_methods.include?(element_name.to_sym)
37
+ define_method element_name.to_s do
38
+ yield self
39
+ end
40
+ end
41
+ alias :value :element
42
+ alias :action :element
43
+ alias :thing :element
44
+
45
+ def page_method method_name, &block
46
+ define_method method_name.to_s do |*thing|
47
+ Proc.new(&block).call *thing, self
48
+ end
49
+ end
50
+ alias :pgmd :page_method
51
+
52
+ end
53
+
54
+ end # PageMaker
@@ -0,0 +1,127 @@
1
+ # coding: UTF-8
2
+ module StringFactory
3
+
4
+ # A random string creator that draws from all printable ASCII characters
5
+ # from 33 to 128. Default length is 10 characters.
6
+ # @param length [Integer] The count of characters in the string
7
+ # @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will still be as specified
8
+ def random_string(length=10, s="")
9
+ length.enum_for(:times).inject(s) do |result, index|
10
+ s << rand(93) + 33
11
+ end
12
+ end
13
+
14
+ # A random string creator that draws from all printable ASCII and High ASCII characters
15
+ # from 33 to 256. Default length is 10 characters.
16
+ # @param length [Integer] The count of characters in the string
17
+ # @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will still be as specified
18
+ def random_high_ascii(length=10, s="")
19
+ length.enum_for(:times).inject(s) do |result, index|
20
+ s << rand(223) + 33
21
+ end
22
+ end
23
+
24
+ # A "friendlier" random string generator. No characters need to be escaped for valid URLs.
25
+ # Uses no Reserved or "Unsafe" characters.
26
+ # Also excludes the comma, the @ sign and the plus sign. Default length is 10 characters.
27
+ def random_nicelink(length=10)
28
+ 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 _ - .}
29
+ (0...length).map { chars[rand(chars.size)]}.join
30
+ end
31
+
32
+ # Returns a string that is properly formatted like an email address.
33
+ # The string returned defaults to 268 characters long.
34
+ # @param x [Integer] This is not the length of the whole string, but only of the "name" portion of the email, minus 2.
35
+ def random_email(x=62)
36
+ x > 62 ? x=62 : x=x
37
+ 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 ! # $ % & ' * + - / = ? ^ _ ` { | } ~}
38
+ random_alphanums(1) + (0...x).map { chars[rand(chars.size)]}.join + random_alphanums(1) + "@" + random_alphanums(60) + ".com"
39
+ end
40
+
41
+ # A random string generator that uses all characters
42
+ # available on an American Qwerty keyboard.
43
+ # @param length [Integer] The count of characters in the string
44
+ # @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will still be as specified
45
+ def random_alphanums_plus(length=10, s="")
46
+ 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 ` ~ ! @ # $% ^ & * ( ) _ + - = { } [ ] \ : " ; ' < > ? , . / }
47
+ length.times { s << chars[rand(chars.size)] }
48
+ s.to_s
49
+ end
50
+
51
+ # A random string generator that uses only letters and numbers in the string. Default length is 10 characters.
52
+ # @param length [Integer] The count of characters in the string
53
+ # @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will still be as specified
54
+ def random_alphanums(length=10, s="")
55
+ chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ0123456789'
56
+ length.times { s << chars[rand(chars.size)] }
57
+ s.to_s
58
+ end
59
+
60
+ # A random string generator that uses only lower case letters.
61
+ # @param length [Integer] The count of characters in the string
62
+ # @param s [String] Typically this will be left blank, but if included, any string created will be prepended with s. Note that the string length will still be as specified
63
+ def random_letters(length=10, s="")
64
+ chars = 'abcdefghjkmnpqrstuvwxyz'
65
+ length.times { s << chars[rand(chars.size)] }
66
+ s.to_s
67
+ end
68
+
69
+ # Returns a block of text (of the specified type, see below) containing
70
+ # the specified number of "words" (each containing between 1 and 16 chars)
71
+ # randomly spread across the specified number of lines (note that
72
+ # the method does not allow the line count to be larger than
73
+ # the word count and will "fix" it if it is).
74
+ #
75
+ # @param word_count [Integer] The count of "words" in the string, separated by spaces or line feeds. If no parameters are provided, the method will return two alphanumeric "words" on two lines.
76
+ # @param line_count [Integer] The count of line feeds that will be randomly placed throughout the string
77
+ # @param char_type [:symbol] Determines the character content
78
+ # of the string.
79
+ #
80
+ # @example
81
+ #
82
+ # :alpha => "Alphanumeric" - Uses the #random_alphanums method
83
+ # :string => uses the #random_string method, so chars 33 through 128 will be included
84
+ # :ascii => All ASCII chars from 33 to 256 are fair game -> uses #random_high_ascii
85
+ def random_multiline(word_count=2, line_count=2, char_type=:alpha)
86
+ char_methods = {:alpha=>"random_alphanums(rand(16)+1)", :string=>"random_string(rand(16)+1)", :ascii=>"random_high_ascii(rand(16)+1)"}
87
+ if line_count > word_count
88
+ line_count = word_count - 1
89
+ end
90
+ words = []
91
+ non_words = []
92
+ word_count.times { words << eval(char_methods[char_type]) } # creating the words, adding to the array
93
+ (line_count - 1).times { non_words << "\n" } # adding the number of line feeds
94
+ unless word_count==line_count
95
+ (word_count - line_count - 1).times { non_words << " " } # adding the right number of spaces
96
+ end
97
+ non_words.shuffle! # Have to shuffle the line feeds around!
98
+ array = words.zip(non_words)
99
+ array.flatten!
100
+ array.join("")
101
+ end
102
+
103
+ # Picks at random from the list of XSS test strings, using
104
+ # the provided number as size of the list to choose from.
105
+ # It will randomly pre-pend the string with HTML closing tags.
106
+ #
107
+ # The strings are organized by length, with the shorter ones
108
+ # first. There are 102 strings.
109
+ def random_xss_string(number=102)
110
+ if number > 102
111
+ number = 102
112
+ end
113
+ 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>"]
114
+ x = rand(4)
115
+ case(x)
116
+ when 0
117
+ return xss[rand(number)]
118
+ when 1
119
+ return %|"| + xss[rand(number)]
120
+ when 2
121
+ return %|">| + xss[rand(number)]
122
+ when 3
123
+ return %|>| + xss[rand(number)]
124
+ end
125
+
126
+ end
127
+ end
@@ -0,0 +1,13 @@
1
+ spec = Gem::Specification.new do |s|
2
+ s.name = 'test-factory'
3
+ s.version = '0.0.1'
4
+ s.summary = %q{rSmart's framework for creating automated testing scripts}
5
+ s.description = %q{This gem provides a set of modules and methods to help quickly and DRYly create a test automation framework using Ruby and Watir (or watir-webdriver).}
6
+ s.files = Dir.glob("**/**/**")
7
+ s.test_files = Dir.glob("test/*test_rb")
8
+ s.authors = ["Abraham Heward"]
9
+ s.email = %w{"aheward@rsmart.com"}
10
+ s.homepage = 'https://github.com/rSmart'
11
+ s.add_dependency 'watir-webdriver', '>= 0.6.1'
12
+ s.required_ruby_version = '>= 1.9.2'
13
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: test-factory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Abraham Heward
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-26 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: watir-webdriver
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.6.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.6.1
30
+ description: This gem provides a set of modules and methods to help quickly and DRYly
31
+ create a test automation framework using Ruby and Watir (or watir-webdriver).
32
+ email:
33
+ - ! '"aheward@rsmart.com"'
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/test-factory/core_ext.rb
39
+ - lib/test-factory/data_factory.rb
40
+ - lib/test-factory/date_factory.rb
41
+ - lib/test-factory/foundry.rb
42
+ - lib/test-factory/page_factory.rb
43
+ - lib/test-factory/string_factory.rb
44
+ - lib/test-factory.rb
45
+ - README.md
46
+ - test-factory.gemspec
47
+ homepage: https://github.com/rSmart
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: 1.9.2
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.24
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: rSmart's framework for creating automated testing scripts
71
+ test_files: []