taft 0.1.0 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+