testcentricity_web 4.1.6 → 4.1.7

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/Gemfile.lock +2 -2
  4. data/Rakefile +32 -9
  5. data/config/cucumber.yml +20 -7
  6. data/config/test_data/data.json +12 -0
  7. data/config/test_data/data.xls +0 -0
  8. data/config/test_data/data.yml +12 -0
  9. data/features/basic_test_page_css.feature +11 -0
  10. data/features/basic_test_page_xpath.feature +3 -0
  11. data/features/media_players.feature +87 -0
  12. data/features/step_definitions/generic_steps.rb.rb +7 -0
  13. data/features/step_definitions/media_steps.rb +30 -0
  14. data/features/support/env.rb +14 -7
  15. data/features/support/pages/base_test_page.rb +11 -0
  16. data/features/support/pages/basic_css_test_page.rb +8 -5
  17. data/features/support/pages/basic_test_page.rb +67 -8
  18. data/features/support/pages/basic_xpath_test_page.rb +8 -4
  19. data/features/support/pages/custom_controls_page.rb +16 -0
  20. data/features/support/pages/indexed_sections_page.rb +16 -0
  21. data/features/support/pages/media_test_page.rb +195 -0
  22. data/features/support/sections/header_nav.rb +28 -0
  23. data/features/support/world_data.rb +12 -0
  24. data/features/support/world_pages.rb +3 -0
  25. data/lib/testcentricity_web/data_objects/environment.rb +12 -0
  26. data/lib/testcentricity_web/version.rb +1 -1
  27. data/lib/testcentricity_web/web_core/page_object.rb +1 -8
  28. data/lib/testcentricity_web/web_elements/checkbox.rb +3 -4
  29. data/lib/testcentricity_web/web_elements/media.rb +50 -4
  30. data/lib/testcentricity_web/web_elements/radio.rb +5 -1
  31. data/test_site/basic_test_page.html +51 -1
  32. data/test_site/custom_controls_page.html +58 -0
  33. data/test_site/indexed_sections_page.html +58 -0
  34. data/test_site/media/MIB2-subtitles-pt-BR.vtt +49 -0
  35. data/test_site/media/MIB2.mp4 +0 -0
  36. data/test_site/media_page.html +60 -7
  37. metadata +25 -4
  38. data/features/support/pages/media_page.rb +0 -11
@@ -0,0 +1,195 @@
1
+ # Page Object class definition for Media Test page with CSS locators
2
+
3
+ class MediaTestPage < BaseTestPage
4
+ trait(:page_name) { 'Media Test' }
5
+ trait(:page_locator) { 'div.media-page-body' }
6
+ trait(:page_url) { '/media_page.html' }
7
+ trait(:navigator) { header_nav.open_media_page }
8
+
9
+ # Media Test page UI elements
10
+ videos video_player: 'video#video_player'
11
+ audios audio_player: 'audio#audio_player'
12
+
13
+ def verify_page_ui
14
+ preload = case
15
+ when Environ.browser == :safari || Environ.device_os == :ios
16
+ 'auto'
17
+ when Environ.browser == :firefox
18
+ ''
19
+ else
20
+ 'metadata'
21
+ end
22
+ video_player.wait_until_ready_state_is(4, 10)
23
+ ui = {
24
+ self => { exists: true, secure: false, title: 'Media Page' },
25
+ header_label => { visible: true, caption: 'Media Page' },
26
+ video_player => {
27
+ visible: true,
28
+ paused: true,
29
+ autoplay: false,
30
+ loop: false,
31
+ ended: false,
32
+ controls: true,
33
+ current_time: 0,
34
+ ready_state: 4,
35
+ default_playback_rate: 1,
36
+ playback_rate: 1,
37
+ seeking: false,
38
+ default_muted: false,
39
+ muted: false,
40
+ volume: 1,
41
+ preload: preload,
42
+ poster: '',
43
+ src: '',
44
+ duration: 17.6
45
+ },
46
+ audio_player => {
47
+ visible: true,
48
+ paused: true,
49
+ autoplay: false,
50
+ loop: false,
51
+ ended: false,
52
+ controls: true,
53
+ current_time: 0,
54
+ ready_state: 4,
55
+ default_playback_rate: 1,
56
+ playback_rate: 1,
57
+ seeking: false,
58
+ default_muted: false,
59
+ muted: false,
60
+ volume: 1,
61
+ preload: preload,
62
+ src: '',
63
+ duration: 3.45
64
+ }
65
+ }
66
+ verify_ui_states(ui)
67
+ end
68
+
69
+ def perform_action(media_type, action)
70
+ player = dispatch_player(media_type)
71
+ case action.downcase.to_sym
72
+ when :play
73
+ player.play
74
+ player.send_keys(:enter) if player.paused?
75
+ player.click if player.paused?
76
+ when :pause
77
+ player.pause
78
+ when :mute
79
+ player.mute
80
+ when :unmute
81
+ player.unmute
82
+ else
83
+ raise "#{action} is not a valid selector"
84
+ end
85
+ sleep(2)
86
+ end
87
+
88
+ def verify_media_state(media_type, state)
89
+ player = dispatch_player(media_type)
90
+ duration = player.duration
91
+ props = case state.downcase.to_sym
92
+ when :playing
93
+ {
94
+ visible: true,
95
+ paused: false,
96
+ ended: false,
97
+ current_time: { greater_than: 0 },
98
+ seeking: false
99
+ }
100
+ when :paused
101
+ {
102
+ visible: true,
103
+ paused: true,
104
+ ended: false,
105
+ current_time: { greater_than: 0 },
106
+ seeking: false
107
+ }
108
+ when :ended
109
+ {
110
+ visible: true,
111
+ paused: true,
112
+ ended: true,
113
+ current_time: duration,
114
+ seeking: false
115
+ }
116
+ when :muted
117
+ {
118
+ visible: true,
119
+ muted: true
120
+ }
121
+ when :unmuted
122
+ {
123
+ visible: true,
124
+ muted: false
125
+ }
126
+ else
127
+ raise "#{state} is not a valid selector"
128
+ end
129
+ verify_ui_states(player => props)
130
+ end
131
+
132
+ def set_playback_rate(media_type, rate)
133
+ player = dispatch_player(media_type)
134
+ player.playback_rate = rate.to_f
135
+ reset_play(player)
136
+ end
137
+
138
+ def verify_playback_rate(media_type, rate)
139
+ player = dispatch_player(media_type)
140
+ ui = {
141
+ player => {
142
+ playback_rate: rate.to_f,
143
+ visible: true,
144
+ paused: false,
145
+ current_time: { greater_than: 0 },
146
+ seeking: false
147
+ }
148
+ }
149
+ verify_ui_states(ui)
150
+ end
151
+
152
+ def set_volume(media_type, volume)
153
+ player = dispatch_player(media_type)
154
+ player.volume = volume.to_f
155
+ reset_play(player)
156
+ end
157
+
158
+ def verify_volume(media_type, volume)
159
+ player = dispatch_player(media_type)
160
+ ui = {
161
+ player => {
162
+ volume: volume.to_f,
163
+ visible: true,
164
+ muted: false,
165
+ paused: false,
166
+ current_time: { greater_than: 0 },
167
+ seeking: false
168
+ }
169
+ }
170
+ verify_ui_states(ui)
171
+ end
172
+
173
+ private
174
+
175
+ def dispatch_player(media_type)
176
+ player = case media_type.downcase.to_sym
177
+ when :video
178
+ video_player
179
+ when :audio
180
+ audio_player
181
+ else
182
+ raise "#{media_type} is not a valid selector"
183
+ end
184
+ player.wait_until_ready_state_is(4, 10)
185
+ player
186
+ end
187
+
188
+ def reset_play(player)
189
+ player.pause
190
+ player.current_time = 0
191
+ player.play
192
+ player.send_keys(:enter) if player.paused?
193
+ sleep(1)
194
+ end
195
+ end
@@ -0,0 +1,28 @@
1
+ # Section Object class definition for Top Navigation Bar
2
+
3
+ class NavHeader < TestCentricity::PageSection
4
+ trait(:section_locator) { 'div#nav_bar' }
5
+ trait(:section_name) { 'Top Navigation Bar' }
6
+
7
+ # Top Navigation Bar UI elements
8
+ links form_link: 'a#form_link',
9
+ media_link: 'a#media_link',
10
+ indexed_sections_link: 'a#indexed_sections_link',
11
+ custom_controls_link: 'a#custom_controls_link'
12
+
13
+ def open_form_page
14
+ form_link.click
15
+ end
16
+
17
+ def open_media_page
18
+ media_link.click
19
+ end
20
+
21
+ def open_indexed_sections_page
22
+ indexed_sections_link.click
23
+ end
24
+
25
+ def open_custom_controls_page
26
+ custom_controls_link.click
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ module WorldData
2
+ #
3
+ # data_objects method returns a hash table of your web app's data objects and associated data object classes to be instantiated
4
+ # by the TestCentricity™ DataManager. Data Object class definitions are contained in the features/support/data folder.
5
+ #
6
+ def data_objects
7
+ {}
8
+ end
9
+ end
10
+
11
+
12
+ World(WorldData)
@@ -7,6 +7,9 @@ module WorldPages
7
7
  {
8
8
  basic_css_test_page: BasicCSSTestPage,
9
9
  basic_xpath_test_page: BasicXpathTestPage,
10
+ media_test_page: MediaTestPage,
11
+ indexed_sections_page: IndexedSectionsPage,
12
+ custom_controls_page: CustomControlsPage
10
13
  }
11
14
  end
12
15
  end
@@ -71,6 +71,7 @@ module TestCentricity
71
71
  @screen_shots = []
72
72
 
73
73
  attr_accessor :test_environment
74
+ attr_accessor :app_host
74
75
  attr_accessor :browser
75
76
  attr_accessor :browser_size
76
77
  attr_accessor :headless
@@ -133,9 +134,20 @@ module TestCentricity
133
134
  @db_username = data['DB_USERNAME']
134
135
  @db_password = data['DB_PASSWORD']
135
136
 
137
+ url = @hostname.blank? ? "#{@base_url}#{@append}" : "#{@hostname}/#{@base_url}#{@append}"
138
+ @app_host = if @user_id.blank? || @password.blank?
139
+ "#{@protocol}://#{url}"
140
+ else
141
+ "#{@protocol}://#{@user_id}:#{@password}@#{url}"
142
+ end
143
+
136
144
  super
137
145
  end
138
146
 
147
+ def self.app_host
148
+ @app_host
149
+ end
150
+
139
151
  def self.session_code
140
152
  if @session_code.nil?
141
153
  characters = ('a'..'z').to_a
@@ -1,3 +1,3 @@
1
1
  module TestCentricityWeb
2
- VERSION = '4.1.6'
2
+ VERSION = '4.1.7'
3
3
  end
@@ -312,14 +312,7 @@ module TestCentricity
312
312
  end
313
313
 
314
314
  def open_portal
315
- environment = Environ.current
316
- url = environment.hostname.blank? ? "#{environment.base_url}#{environment.append}" : "#{environment.hostname}/#{environment.base_url}#{environment.append}"
317
- full_url = if environment.user_id.blank? || environment.password.blank?
318
- "#{environment.protocol}://#{url}"
319
- else
320
- "#{environment.protocol}://#{environment.user_id}:#{environment.password}@#{url}"
321
- end
322
- visit full_url
315
+ visit Environ.current.app_host
323
316
  Environ.portal_state = :open
324
317
  end
325
318
 
@@ -112,11 +112,10 @@ module TestCentricity
112
112
  object_not_found_exception(obj, 'Checkbox')
113
113
  invalid_object_type_exception(obj, 'checkbox')
114
114
  if @proxy.nil?
115
- if obj.native.attribute('ot') == 'JCheckBox'
116
- expected = state.to_bool
117
- obj.click unless expected == obj.checked?
118
- else
115
+ begin
119
116
  obj.set(state)
117
+ rescue
118
+ obj.click unless state == obj.checked?
120
119
  end
121
120
  else
122
121
  page.find(:css, @proxy).click unless state == obj.checked?
@@ -125,7 +125,7 @@ module TestCentricity
125
125
  def current_time
126
126
  obj, = find_element(visible = :all)
127
127
  object_not_found_exception(obj, @type)
128
- obj.native.attribute('currentTime').to_f
128
+ obj.native.attribute('currentTime').to_f.round(2)
129
129
  end
130
130
 
131
131
  # Return media defaultPlaybackRate property
@@ -137,7 +137,7 @@ module TestCentricity
137
137
  def default_playback_rate
138
138
  obj, = find_element(visible = :all)
139
139
  object_not_found_exception(obj, @type)
140
- obj.native.attribute('defaultPlaybackRate')
140
+ obj.native.attribute('defaultPlaybackRate').to_f
141
141
  end
142
142
 
143
143
  # Return media duration property
@@ -149,7 +149,7 @@ module TestCentricity
149
149
  def duration
150
150
  obj, = find_element(visible = :all)
151
151
  object_not_found_exception(obj, @type)
152
- obj.native.attribute('duration').to_f
152
+ obj.native.attribute('duration').to_f.round(2)
153
153
  end
154
154
 
155
155
  # Return media playbackRate property
@@ -161,7 +161,7 @@ module TestCentricity
161
161
  def playback_rate
162
162
  obj, = find_element(visible = :all)
163
163
  object_not_found_exception(obj, @type)
164
- obj.native.attribute('playbackRate')
164
+ obj.native.attribute('playbackRate').to_f
165
165
  end
166
166
 
167
167
  # Return media readyState property
@@ -247,6 +247,52 @@ module TestCentricity
247
247
  page.execute_script('arguments[0].pause()', obj)
248
248
  end
249
249
 
250
+ # Mute the media's audio
251
+ #
252
+ # @example
253
+ # media_player.mute
254
+ #
255
+ def mute
256
+ obj, = find_element(visible = :all)
257
+ object_not_found_exception(obj, @type)
258
+ page.execute_script('arguments[0].muted = true;', obj)
259
+ end
260
+
261
+ # Unmute the media's audio
262
+ #
263
+ # @example
264
+ # media_player.unmute
265
+ #
266
+ def unmute
267
+ obj, = find_element(visible = :all)
268
+ object_not_found_exception(obj, @type)
269
+ page.execute_script('arguments[0].muted = false;', obj)
270
+ end
271
+
272
+ # Set the media playbackRate property
273
+ #
274
+ # @param value [Float]
275
+ # @example
276
+ # media_player.playback_rate = 1.5
277
+ #
278
+ def playback_rate=(value)
279
+ obj, = find_element(visible = :all)
280
+ object_not_found_exception(obj, @type)
281
+ page.execute_script('arguments[0].playbackRate = arguments[1]', obj, value)
282
+ end
283
+
284
+ # Set the media volume property
285
+ #
286
+ # @param value [Float] between 0 and 1
287
+ # @example
288
+ # media_player.volume = 0.5
289
+ #
290
+ def volume=(value)
291
+ obj, = find_element(visible = :all)
292
+ object_not_found_exception(obj, @type)
293
+ page.execute_script('arguments[0].volume = arguments[1]', obj, value)
294
+ end
295
+
250
296
  # Return media crossorigin property
251
297
  #
252
298
  # @return crossorigin value
@@ -101,7 +101,11 @@ module TestCentricity
101
101
  object_not_found_exception(obj, 'Radio')
102
102
  invalid_object_type_exception(obj, 'radio')
103
103
  if @proxy.nil?
104
- obj.set(state)
104
+ begin
105
+ obj.set(state)
106
+ rescue
107
+ obj.click unless state == obj.checked?
108
+ end
105
109
  else
106
110
  page.find(:css, @proxy).click unless state == obj.checked?
107
111
  end
@@ -15,11 +15,44 @@
15
15
  text-align: left;
16
16
  padding: 8px;
17
17
  }
18
+ body {
19
+ margin: 0;
20
+ font-family: Arial, Helvetica, sans-serif;
21
+ }
22
+ .topnav {
23
+ overflow: hidden;
24
+ background-color: #333;
25
+ }
26
+ .topnav a {
27
+ float: left;
28
+ color: #f2f2f2;
29
+ text-align: center;
30
+ padding: 12px 14px;
31
+ text-decoration: none;
32
+ font-size: 15px;
33
+ }
34
+ .topnav a:hover {
35
+ background-color: #ddd;
36
+ color: black;
37
+ }
38
+ .topnav a.active {
39
+ background-color: #04AA6D;
40
+ color: white;
41
+ }
18
42
  </style>
19
43
  </head>
20
44
  <body>
21
45
  <div class="page-body">
22
- <h1>Basic HTML Form Example</h1>
46
+ <h2>Basic HTML Form Example</h2>
47
+
48
+ <div id="nav_bar" class="topnav">
49
+ <a id="form_link" class="active" href="#">Basic HTML Form</a>
50
+ <a id="media_link" href="media_page.html">Media</a>
51
+ <a id="indexed_sections_link" href="indexed_sections_page.html">Indexed Sections</a>
52
+ <a id="custom_controls_link" href="custom_controls_page.html">Custom Controls</a>
53
+ </div>
54
+
55
+
23
56
  <div class="centered">
24
57
  <form name="HTMLFormElements" id="HTMLFormElements">
25
58
  <table border="1" cellpadding="5">
@@ -132,6 +165,23 @@
132
165
  </td>
133
166
  </tr>
134
167
 
168
+ <tr>
169
+ <td>
170
+ <label id="links">Links:</label>
171
+ <ul>
172
+ <li>
173
+ <a id="link1" href="media_page.html">Open Media Page in same window/tab</a>
174
+ </li>
175
+ <li>
176
+ <a id="link2" href="media_page.html" target="_blank">Open Media Page in a new window/tab</a>
177
+ </li>
178
+ <li>
179
+ <a id="link3" role="link" aria-disabled="true">Disabled Link</a>
180
+ </li>
181
+ </ul>
182
+ </td>
183
+ </tr>
184
+
135
185
  <tr>
136
186
  <td>
137
187
  <label for="table">Table:</label>
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Custom Controls Page</title>
6
+ <style>
7
+ table {
8
+ font-family: arial, sans-serif;
9
+ font-size: 15px;
10
+ border-collapse: collapse;
11
+ width: 85%;
12
+ }
13
+ td, th {
14
+ border: 1px solid #dddddd;
15
+ text-align: left;
16
+ padding: 8px;
17
+ }
18
+ body {
19
+ margin: 0;
20
+ font-family: Arial, Helvetica, sans-serif;
21
+ }
22
+ .topnav {
23
+ overflow: hidden;
24
+ background-color: #333;
25
+ }
26
+ .topnav a {
27
+ float: left;
28
+ color: #f2f2f2;
29
+ text-align: center;
30
+ padding: 12px 14px;
31
+ text-decoration: none;
32
+ font-size: 15px;
33
+ }
34
+ .topnav a:hover {
35
+ background-color: #ddd;
36
+ color: black;
37
+ }
38
+ .topnav a.active {
39
+ background-color: #04AA6D;
40
+ color: white;
41
+ }
42
+ </style>
43
+ </head>
44
+ <body>
45
+ <div class="custom-controls-page-body">
46
+ <h2>Custom Controls Page</h2>
47
+
48
+ <div id="nav_bar" class="topnav">
49
+ <a id="form_link" href="basic_test_page.html">Basic HTML Form</a>
50
+ <a id="media_link" href="media_page.html">Media</a>
51
+ <a id="indexed_sections_link" href="indexed_sections_page.html">Indexed Sections</a>
52
+ <a id="custom_controls_link" class="active" href="#">Custom Controls</a>
53
+ </div>
54
+
55
+
56
+ </div>
57
+ </body>
58
+ </html>
@@ -0,0 +1,58 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Indexed Sections Page</title>
6
+ <style>
7
+ table {
8
+ font-family: arial, sans-serif;
9
+ font-size: 15px;
10
+ border-collapse: collapse;
11
+ width: 85%;
12
+ }
13
+ td, th {
14
+ border: 1px solid #dddddd;
15
+ text-align: left;
16
+ padding: 8px;
17
+ }
18
+ body {
19
+ margin: 0;
20
+ font-family: Arial, Helvetica, sans-serif;
21
+ }
22
+ .topnav {
23
+ overflow: hidden;
24
+ background-color: #333;
25
+ }
26
+ .topnav a {
27
+ float: left;
28
+ color: #f2f2f2;
29
+ text-align: center;
30
+ padding: 12px 14px;
31
+ text-decoration: none;
32
+ font-size: 15px;
33
+ }
34
+ .topnav a:hover {
35
+ background-color: #ddd;
36
+ color: black;
37
+ }
38
+ .topnav a.active {
39
+ background-color: #04AA6D;
40
+ color: white;
41
+ }
42
+ </style>
43
+ </head>
44
+ <body>
45
+ <div class="indexed-sections-page-body">
46
+ <h2>Indexed Sections Page</h2>
47
+
48
+ <div id="nav_bar" class="topnav">
49
+ <a id="form_link" href="basic_test_page.html">Basic HTML Form</a>
50
+ <a id="media_link" href="media_page.html">Media</a>
51
+ <a id="indexed_sections_link" class="active" href="#">Indexed Sections</a>
52
+ <a id="custom_controls_link" href="custom_controls_page.html">Custom Controls</a>
53
+ </div>
54
+
55
+
56
+ </div>
57
+ </body>
58
+ </html>
@@ -0,0 +1,49 @@
1
+ WEBVTT
2
+
3
+ 1
4
+ 00:00:00.000 --> 00:00:02.500
5
+ Aprendi a me virar e você voltou
6
+
7
+ 2
8
+ 00:00:02.500 --> 00:00:05.000
9
+ do espaço sideral
10
+
11
+ 3
12
+ 00:00:05.100 --> 00:00:10.500
13
+ e agora vejo que você está aqui no baixo astral
14
+
15
+ 4
16
+ 00:00:10.600 --> 00:00:14.000
17
+ eu devia me mudar e ter tomado a sua chave
18
+
19
+ 5
20
+ 00:00:14.100 --> 00:00:17.500
21
+ se soubesse que ia voltar para mim enfernizar
22
+
23
+ 6
24
+ 00:00:17.600 --> 00:00:19.500
25
+ agora vai, sai daqui
26
+
27
+ 7
28
+ 00:00:19.600 --> 00:00:21.500
29
+ Frank!
30
+
31
+ 8
32
+ 00:00:21.600 --> 00:00:24.100
33
+ ponha a cabeça para dentro
34
+
35
+ 9
36
+ 00:00:24.200 --> 00:00:26.500
37
+ antes que eu emprense nessa janela
38
+
39
+ 10
40
+ 00:00:26.600 --> 00:00:29.500
41
+ tá legal
42
+
43
+ 11
44
+ 00:00:29.600 --> 00:00:33.500
45
+ hhmm... hhmmm... hmmm...
46
+
47
+ 12
48
+ 00:00:33.600 --> 00:00:34.000
49
+ FRANK!!!
Binary file