taft 0.1.0 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -3
  3. data/examples/ruby/rs/framework/red_sky.rb +11 -0
  4. data/examples/ruby/rs/framework/red_sky/api_helpers/general.rb +140 -0
  5. data/examples/ruby/rs/framework/red_sky/api_helpers/rest.rb +249 -0
  6. data/examples/ruby/rs/framework/red_sky/ui_helpers/ui_general.rb +36 -0
  7. data/examples/ruby/rs/framework/red_sky/watir/custom/all.rb +4 -0
  8. data/examples/ruby/rs/framework/red_sky/watir/custom/rs_custom.rb +32 -0
  9. data/examples/ruby/rs/framework/red_sky/watir/pages/page_objects.rb +166 -0
  10. data/examples/ruby/rs/framework/red_sky/watir/pages/rs_pages.rb +68 -0
  11. data/examples/ruby/rs/lib/config/red_sky_config.rb +27 -0
  12. data/examples/ruby/rs/lib/config/runtime_constants.rb +20 -0
  13. data/examples/ruby/rs/lib/red_sky_test_case.rb +218 -0
  14. data/examples/ruby/rs/tests/v1/tc_r001_01_an_example_test.rb +112 -0
  15. data/examples/ruby/rs/tests/v1/tc_r001_01_google_search.rb +64 -0
  16. data/lib/taft.rb +2 -0
  17. data/lib/taft_files/framework/zznamezz.rb +3 -0
  18. data/lib/taft_files/framework/zznamezz/api_helpers/general.rb +13 -13
  19. data/lib/taft_files/framework/zznamezz/ui_helpers/ui_general.rb +26 -0
  20. data/lib/taft_files/framework/zznamezz/watir/custom/all.rb +4 -0
  21. data/lib/taft_files/framework/zznamezz/watir/custom/xxabbrevxx_custom.rb +32 -0
  22. data/lib/taft_files/framework/zznamezz/watir/pages/page_objects.rb +166 -0
  23. data/lib/taft_files/framework/zznamezz/watir/pages/xxabbrevxx_pages.rb +101 -0
  24. data/lib/taft_files/lib/config/runtime_constants.rb +5 -1
  25. data/lib/taft_files/lib/config/zznamezz_config.rb +7 -2
  26. data/lib/taft_files/lib/zznamezz_test_case.rb +43 -42
  27. data/lib/taft_files/tests/v1/tc_r001_01_an_example_test.rb +1 -1
  28. data/taft.gemspec +5 -5
  29. metadata +23 -6
@@ -0,0 +1,112 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../../lib")
2
+
3
+ require "red_sky_test_case"
4
+
5
+ class TC_R001_01_AN_EXAMPLE_TEST < Test::Unit::TestCase
6
+ include RedSkyTestCase
7
+
8
+ def setup
9
+ # specify setup parameters
10
+ @certificate = :regular # this is the default user for this test
11
+ @initialBrowser = :none # if you want this test to navigate to your webapp automatically as part of setup, change this value to the value referring to your webapp
12
+
13
+ super # must call super so that the common setup method in RedSkyTestCase is called
14
+ end
15
+
16
+ def test_r001_01_an_example_test
17
+
18
+ ############################################################################################
19
+ # PURPOSE :
20
+ # Verify that <description of your test's intent>
21
+ #
22
+ # PRECONDITIONS :
23
+ # <list your preconditions>
24
+ ############################################################################################
25
+
26
+ filename = "data_for_example_test.csv" # file must be in the data/ directory
27
+ data = @help.read_csv_test_data(filename)
28
+ header = data.shift
29
+
30
+ # Step 1 :
31
+ # Send a request to the RED SKY API Options method
32
+
33
+ random_row = data.random
34
+ search_term = random_row[0]
35
+ expected_result_count = random_row[1]
36
+
37
+ # This is too raw - it would be better to bundle these lines into a separate "search_options" method,
38
+ # with additional validation (e.g. to throw a clean error if the request failed)
39
+ @client = @help.get_rest_client(:options, @certificate, search_term)
40
+ json = client.get
41
+ response = JSON.pretty_unparse(json)
42
+
43
+ # Expected Result :
44
+ # The request has succeeded & returned the expected results
45
+
46
+ # This is quite brittle
47
+ # A better approach is to create a new class which would parse the response & convert
48
+ # it into a bespoke Object, so that the various values could be accessed in a better OO-fashion.
49
+ # E.g. response.number_of_results. The object could also have extra methods,
50
+ # e.g. response.check_results_are_valid, and so on.
51
+ assert_equal(expected_result_count, response["number_of_results"], "The search request did not return the expected number of results")
52
+
53
+
54
+ # Step 2 :
55
+ # Log in to RED SKY
56
+
57
+ rs_login
58
+
59
+ # Expected Result :
60
+ # The RED SKY homepage is displayed
61
+
62
+ assert(rsHomepage.displayed?, "The RED SKY homepage is not displayed")
63
+
64
+
65
+ # Step 3 :
66
+ # Enter in a search term and click the Search button.
67
+
68
+ data.each do |row|
69
+ search_term = row[0]
70
+ expected_result_text = row[2]
71
+ puts "Will now search for '#{term}'; expect to see '#{expected_result_text}'"
72
+
73
+ rsHomepage.term = search_term
74
+ rsHomepage.click_search
75
+
76
+
77
+ # Expected Result :
78
+ # Results are displayed
79
+
80
+ assert(rsSearchResults.displayed?, "The RED SKY search results page is not displayed")
81
+ assert_equal(expected_result_text, rsSearchResults.result, "The RED SKY search results page did not display the expected result")
82
+
83
+
84
+ # Step 4 :
85
+ # Return to the previous page
86
+
87
+ browser.back
88
+
89
+
90
+
91
+ # Expected Result :
92
+ # The RED SKY homepage is displayed
93
+
94
+ assert(rsHomepage.displayed?, "The RED SKY homepage is not displayed")
95
+
96
+
97
+ # Step 5 :
98
+ # Repeat steps 3 and 4 for a few more search terms
99
+
100
+ # Actions performed in above steps
101
+
102
+
103
+ # Expected Result :
104
+ # Results are displayed for each term
105
+
106
+ # Assertions performed in above steps
107
+
108
+ end # end .each
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,64 @@
1
+ $LOAD_PATH.unshift("#{File.expand_path(File.dirname(__FILE__))}/../../lib")
2
+
3
+ require "red_sky_test_case"
4
+
5
+ class TC_R001_01_GOOGLE_SEARCH < Test::Unit::TestCase
6
+ include RedSkyTestCase
7
+
8
+ def setup
9
+ # specify setup parameters
10
+ @certificate = :regular # this is the default user for this test
11
+ @initialBrowser = :none # if you want this test to navigate to your webapp automatically as part of setup, change this value to the value referring to your webapp
12
+
13
+ super # must call super so that the common setup method in RedSkyTestCase is called
14
+ end
15
+
16
+ def test_r001_01_google_search
17
+
18
+ ############################################################################################
19
+ # PURPOSE :
20
+ # Verify that Google searches can be made
21
+ #
22
+ # PRECONDITIONS :
23
+ # None
24
+ ############################################################################################
25
+
26
+ @help.ui_helper_test
27
+
28
+ # Step 1 :
29
+ # Open the Google Search page
30
+
31
+ google_login
32
+
33
+ # Expected Result :
34
+ # The RED SKY homepage is displayed
35
+
36
+ assert(googleSearch.displayed?, "The Google search page is not displayed")
37
+
38
+
39
+ # Step 3 :
40
+ # Enter in a search term and click the Search button.
41
+
42
+ term = "Ruby"
43
+
44
+ puts "Will now search for '#{term}'"
45
+
46
+ #googleSearch.search_term = term
47
+ @help.enter_google_term(term) # use @help to set the field, demonstrating that this can be done outside the test
48
+ googleSearch.click_search_button
49
+
50
+
51
+ # Expected Result :
52
+ # Results are displayed
53
+
54
+ assert(googleSearchResults.displayed?, "The Google search results page is not displayed")
55
+
56
+ puts googleSearchResults.result_stats
57
+
58
+ assert_not_nil(googleSearchResults.result_stats, "The Google search results page did not display any result-stats")
59
+ assert_not_empty(googleSearchResults.result_stats, "The Google search results page did not display any result-stats")
60
+
61
+
62
+ end
63
+
64
+ end
data/lib/taft.rb CHANGED
@@ -199,6 +199,8 @@ class Taft
199
199
  entries = Dir.entries(dest_base_folder)
200
200
  entries.delete(".")
201
201
  entries.delete("..")
202
+ entries.delete(".git")
203
+ entries.delete(".gitignore")
202
204
  entries.each do |f|
203
205
  f = File.expand_path(f)
204
206
  pd "Now looking at #{f}; is dir? #{Dir.exists?(f)}"
@@ -6,3 +6,6 @@ require "zznamezz/api_helpers/general"
6
6
  require "zznamezz/api_helpers/rest"
7
7
 
8
8
  require "zznamezz/ui_helpers/ui_general"
9
+
10
+ require "zznamezz/watir/pages/xxabbrevxx_pages"
11
+ require "zznamezz/watir/custom/all"
@@ -5,22 +5,22 @@ require "avro"
5
5
  require "csv"
6
6
  require "net/ssh"
7
7
  require "net/sftp"
8
+ require "more_ruby"
8
9
 
9
10
 
10
11
  class XXabbrevupperxxHelper
11
12
  include Test::Unit::Assertions
12
- include FrameworkHelpers
13
13
 
14
- # initialize and method_missing are necessary for for allowing this class to access outside methods
15
- attr_accessor :xxabbrevxx_context
16
- def initialize(xxabbrevxx_context)
17
- @xxabbrevxx_context = xxabbrevxx_context
18
- end
19
-
20
- def method_missing(meth, *args)
21
- case meth.to_s
22
- when /^xxabbrevxx/
23
- @xxabbrevxx_context.send(meth, *args)
14
+ # E.g. calling homepage.displayed? from a test script :
15
+ # Test cannot see homepage so its call is routed through method_missing
16
+ # If method_missing returns an instance of the class, .displayed? can be called on it (seamlessly)
17
+ # At present this will happen for every call to a page from a test script
18
+ def method_missing(name, *args, &block)
19
+ #puts "XXabbrevupperxxHelper method_missing called; name = #{name.inspect}; #{name.class}"
20
+
21
+ case name.to_s
22
+ when /^xxabbrevxx/i
23
+ RSPages.find(name.to_s) # return the page so that the helper can use it
24
24
  else
25
25
  super
26
26
  end
@@ -28,7 +28,7 @@ class XXabbrevupperxxHelper
28
28
 
29
29
  # Reads in a file of CSV test data, e.g for use in data-driven tests
30
30
  def read_csv_test_data(filename)
31
- path = File.join(File.dirname(File.expand_path(__FILE__)) + "/../../../../tests/data", filename)
31
+ path = File.join(File.dirname(File.expand_path(__FILE__)) + "/../../../tests/data", filename)
32
32
  read_csv_data_from_file(path)
33
33
  end
34
34
 
@@ -43,7 +43,7 @@ class XXabbrevupperxxHelper
43
43
 
44
44
  # Reads in a JSON schema
45
45
  def read_json_schema(schema_filename)
46
- path = File.join(File.dirname(File.expand_path(__FILE__)) + "/../../../../tests/data", schema_filename)
46
+ path = File.join(File.dirname(File.expand_path(__FILE__)) + "/../../../tests/data", schema_filename)
47
47
  data = []
48
48
  File.open(path, "r") do |f|
49
49
  data = f.readlines
@@ -0,0 +1,26 @@
1
+
2
+ class XXabbrevupperxxHelper
3
+
4
+ def new_browser_at_url(url)
5
+ puts "New browser at #{url}"
6
+ case ZZnamezzConfig::BROWSER
7
+ when :chrome
8
+ # Set detach to true so the browser remains open once the test finishes
9
+ options = Selenium::WebDriver::Chrome::Options.new
10
+ options.add_option(:detach, true)
11
+ b = Watir::Browser.new :chrome, :options => options
12
+
13
+ when :firefox
14
+ b = Watir::Browser.new :firefox
15
+
16
+ end
17
+
18
+ b.goto url
19
+
20
+ # Store the new browser in the global list
21
+ $browsers << b
22
+
23
+ b # return the browser
24
+ end
25
+
26
+ end
@@ -0,0 +1,4 @@
1
+ # simple require class for the Custom folder
2
+
3
+ # use require_relative, not require
4
+ require_relative 'xxabbrevxx_custom'
@@ -0,0 +1,32 @@
1
+
2
+ # All methods in this module will be added to those classes. If methods with the
3
+ # same names exist, these methods will overwrite the pre-existing ones.
4
+
5
+ module ZZnamezzCustom
6
+
7
+ # Example code :
8
+ #
9
+ # class XXabbrevupperxxPage
10
+ #
11
+ # # All page titles exist in the same-named element
12
+ # def title_field
13
+ # browser.h1(:id => "page_title")
14
+ # end
15
+ #
16
+ # def title
17
+ # title_field.value
18
+ # end
19
+ #
20
+ # end
21
+ #
22
+ # class XXabbrevupperxxHomepage
23
+ #
24
+ # def displayed?
25
+ # puts "In #{__method__}"
26
+ # title == "Welcome to ZZnamezz"
27
+ # end
28
+ #
29
+ # end
30
+ #
31
+
32
+ end
@@ -0,0 +1,166 @@
1
+ # Base class that every defined page will inherit from
2
+ class Page
3
+
4
+ attr_accessor :name, :displayed_field, :displayed_value
5
+ attr_accessor :browser
6
+ attr_accessor :field_parameters_array # stores parameters of each field added to the page
7
+
8
+ # Name : the name of this page, e.g. rsHomepage
9
+ # Field : the field used to determine if the page is displayed. More precisely,
10
+ # the name of the method that accesses the field. E.g. if the page has a field called 'page_title'
11
+ # defined, then its accessor method 'page_title_field' will have been generated .
12
+ # If the displayed? check is against an expected value, specify the field name corresponding to
13
+ # the read-method (e.g. page_title), and specify the value (String or Regexp).
14
+ # If the displayed? check is for a field to exist, specify the field's accessor method name
15
+ # (e.g. page_title_field), and keep value nil.
16
+ def initialize(name, field, value = nil)
17
+ @name = name
18
+ @displayed_field = field
19
+ @displayed_value = value
20
+ @field_parameters_array = []
21
+ end
22
+
23
+ def displayed?(wait = true)
24
+ displayed = false
25
+ puts "in displayed? for page #{@name}"
26
+ if wait
27
+ puts "will wait for page to be loaded"
28
+ wait_until_displayed
29
+ end
30
+
31
+ puts "about to send to #{@displayed_field.to_sym.inspect}"
32
+ begin
33
+ field_or_value = self.send(@displayed_field.to_sym)
34
+ rescue Watir::Exception::UnknownObjectException
35
+ # cannot find the field on the page
36
+ # do nothing, displayed will stay false
37
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
38
+ # TODO : fix! wait then call displayed? again?
39
+ puts "hit StaleElementReferenceError for page #{@name}"
40
+ end
41
+
42
+ puts "field_or_value retrieved is of class #{field_or_value.class}"
43
+ p field_or_value
44
+ if @displayed_value == nil
45
+ displayed = true if field_or_value.exists?
46
+ else
47
+ if @displayed_value.class == Regexp
48
+ displayed = true if field_or_value =~ @displayed_value
49
+ else
50
+ displayed = true if field_or_value == @displayed_value
51
+ end
52
+ end
53
+ displayed
54
+ end
55
+
56
+ # Method to wait for the page to be displayed, up to <timeout> seconds
57
+ # Returns displayed status (true/false)
58
+ def wait_until_displayed(timeout = 5)
59
+ max = timeout * 10
60
+ count = 0
61
+ displayed = false
62
+ while count < max
63
+ displayed = displayed?(false)
64
+ break if displayed
65
+ sleep 0.2
66
+ count += 2
67
+ end
68
+ displayed
69
+ end
70
+
71
+ # Defines methods to access the field of specified type, by specified key & value
72
+ def add_field(name, type, key, value)
73
+ field_parameters_array << [name, type, key, value]
74
+ add_field_using_constructor_class(name, type, key, value)
75
+ end
76
+
77
+ # Add to self all fields that were defined on page_object
78
+ # E.g. the supplied page_object represents part of a panel/page that is common to several pages
79
+ def add_page(page_object)
80
+ page_object.field_parameters_array.each do |field_parameters|
81
+ add_field(field_parameters[0], field_parameters[1], field_parameters[2], field_parameters[3])
82
+ end
83
+ end
84
+
85
+ # Defines methods to access the field of specified type, by specified key & value
86
+ def add_field_using_constructor_class(name, type, key, value)
87
+ PageFieldConstructor.add_fields(self, name, type, key, value)
88
+ end
89
+
90
+ end # end Page
91
+
92
+ class PageFieldConstructor
93
+
94
+ # Defines methods to access the field of specified type, by specified key & value
95
+ def PageFieldConstructor.add_fields(page_object, name, type, key, value)
96
+
97
+ # Fields cannot have the following names : name
98
+ raise "Field on page #{page_object.name} with name of #{name} is not allowed" if ZZnamezzConfig::DISALLOWED_FIELD_NAMES.include?(name)
99
+
100
+ case type
101
+ when :button
102
+ real_type = :input
103
+ else
104
+ real_type = type
105
+ end
106
+
107
+ # add accessor to field
108
+ s = <<-METHOD
109
+ def page_object.#{name}_field
110
+ # puts "in #{name} method"
111
+ @browser.#{real_type}(#{key.inspect} => "#{value}")
112
+ end
113
+ METHOD
114
+ # page_object.class.module_eval(s) # do not do this - want to add methods (field) to the object, not the class!
115
+ eval(s)
116
+
117
+ case type
118
+ when :text_field
119
+ add_read_method(page_object, name)
120
+ add_write_method(page_object, name)
121
+ when :button
122
+ add_click_method(page_object, name)
123
+ when :link
124
+ add_read_method(page_object, name)
125
+ add_click_method(page_object, name)
126
+ else
127
+ add_read_method(page_object, name)
128
+ end
129
+
130
+ end
131
+
132
+ def PageFieldConstructor.add_read_method(page_object, name)
133
+ s = <<-READ
134
+ def page_object.#{name}
135
+ # puts "in #{name} read method"
136
+ #{name}_field.text # value
137
+ end
138
+ READ
139
+ # page_object.class.module_eval(s) # do not do this - want to add methods (field) to the object, not the class!
140
+ eval(s)
141
+ end
142
+
143
+ def PageFieldConstructor.add_write_method(page_object, name)
144
+ s = <<-WRITE
145
+ def page_object.#{name}=(v)
146
+ # puts "in #{name} write method"
147
+ #{name}_field.set(v)
148
+ end
149
+ WRITE
150
+ # page_object.class.module_eval(s) # do not do this - want to add methods (field) to the object, not the class!
151
+ eval(s)
152
+ end
153
+
154
+ def PageFieldConstructor.add_click_method(page_object, name)
155
+ s = <<-CLICK
156
+ def page_object.click_#{name}
157
+ # puts "in #{name} click method"
158
+ #{name}_field.click
159
+ end
160
+ CLICK
161
+ # page_object.class.module_eval(s) # do not do this - want to add methods (field) to the object, not the class!
162
+ eval(s)
163
+ end
164
+
165
+ end
166
+