testcentricity_web 4.1.6 → 4.1.7

Sign up to get free protection for your applications and to get access to all the features.
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