ops_manager_ui_drivers 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +13 -0
  7. data/README.md +39 -0
  8. data/Rakefile +12 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/ci/run_specs.sh +11 -0
  12. data/lib/ops_manager_ui_drivers.rb +10 -0
  13. data/lib/ops_manager_ui_drivers/page_helpers.rb +52 -0
  14. data/lib/ops_manager_ui_drivers/version.rb +3 -0
  15. data/lib/ops_manager_ui_drivers/version11/api_1_1.rb +40 -0
  16. data/lib/ops_manager_ui_drivers/version11/available_products.rb +24 -0
  17. data/lib/ops_manager_ui_drivers/version11/install_progress.rb +24 -0
  18. data/lib/ops_manager_ui_drivers/version11/login.rb +24 -0
  19. data/lib/ops_manager_ui_drivers/version11/network_configuration.rb +31 -0
  20. data/lib/ops_manager_ui_drivers/version11/ntp_servers.rb +28 -0
  21. data/lib/ops_manager_ui_drivers/version11/ops_manager_director.rb +27 -0
  22. data/lib/ops_manager_ui_drivers/version11/product_dashboard.rb +73 -0
  23. data/lib/ops_manager_ui_drivers/version11/vcenter_credentials.rb +31 -0
  24. data/lib/ops_manager_ui_drivers/version11/vsphere_configuration.rb +31 -0
  25. data/lib/ops_manager_ui_drivers/version11/web_ui.rb +34 -0
  26. data/lib/ops_manager_ui_drivers/version12/api_1_2.rb +40 -0
  27. data/lib/ops_manager_ui_drivers/version12/available_products.rb +24 -0
  28. data/lib/ops_manager_ui_drivers/version12/install_progress.rb +24 -0
  29. data/lib/ops_manager_ui_drivers/version12/login.rb +24 -0
  30. data/lib/ops_manager_ui_drivers/version12/network_configuration.rb +32 -0
  31. data/lib/ops_manager_ui_drivers/version12/ntp_servers.rb +28 -0
  32. data/lib/ops_manager_ui_drivers/version12/ops_manager_director.rb +27 -0
  33. data/lib/ops_manager_ui_drivers/version12/product_dashboard.rb +73 -0
  34. data/lib/ops_manager_ui_drivers/version12/vcenter_credentials.rb +31 -0
  35. data/lib/ops_manager_ui_drivers/version12/vsphere_configuration.rb +30 -0
  36. data/lib/ops_manager_ui_drivers/version12/web_ui.rb +34 -0
  37. data/lib/ops_manager_ui_drivers/version13/api_1_3.rb +40 -0
  38. data/lib/ops_manager_ui_drivers/version13/availability_zones.rb +55 -0
  39. data/lib/ops_manager_ui_drivers/version13/available_products.rb +24 -0
  40. data/lib/ops_manager_ui_drivers/version13/iaas_configuration.rb +65 -0
  41. data/lib/ops_manager_ui_drivers/version13/install_progress.rb +43 -0
  42. data/lib/ops_manager_ui_drivers/version13/job_availability_zone_mapping_helper.rb +70 -0
  43. data/lib/ops_manager_ui_drivers/version13/job_network_mapping_helper.rb +47 -0
  44. data/lib/ops_manager_ui_drivers/version13/job_status_helper.rb +17 -0
  45. data/lib/ops_manager_ui_drivers/version13/networks.rb +83 -0
  46. data/lib/ops_manager_ui_drivers/version13/ops_manager_director.rb +140 -0
  47. data/lib/ops_manager_ui_drivers/version13/product_availability_zones.rb +38 -0
  48. data/lib/ops_manager_ui_drivers/version13/product_dashboard.rb +157 -0
  49. data/lib/ops_manager_ui_drivers/version13/product_logs.rb +53 -0
  50. data/lib/ops_manager_ui_drivers/version13/product_resource_configuration.rb +46 -0
  51. data/lib/ops_manager_ui_drivers/version13/product_status_helper.rb +64 -0
  52. data/lib/ops_manager_ui_drivers/version13/setup.rb +40 -0
  53. data/lib/ops_manager_ui_drivers/version13/web_ui.rb +106 -0
  54. data/lib/ops_manager_ui_drivers/version14/api_1_4.rb +40 -0
  55. data/lib/ops_manager_ui_drivers/version14/availability_zones.rb +59 -0
  56. data/lib/ops_manager_ui_drivers/version14/available_products.rb +24 -0
  57. data/lib/ops_manager_ui_drivers/version14/iaas_configuration.rb +89 -0
  58. data/lib/ops_manager_ui_drivers/version14/job_availability_zone_mapping_helper.rb +70 -0
  59. data/lib/ops_manager_ui_drivers/version14/job_network_mapping_helper.rb +47 -0
  60. data/lib/ops_manager_ui_drivers/version14/job_status_helper.rb +17 -0
  61. data/lib/ops_manager_ui_drivers/version14/networks.rb +58 -0
  62. data/lib/ops_manager_ui_drivers/version14/ops_manager_director.rb +252 -0
  63. data/lib/ops_manager_ui_drivers/version14/product_availability_zones.rb +38 -0
  64. data/lib/ops_manager_ui_drivers/version14/product_configuration.rb +34 -0
  65. data/lib/ops_manager_ui_drivers/version14/product_dashboard.rb +175 -0
  66. data/lib/ops_manager_ui_drivers/version14/product_form.rb +47 -0
  67. data/lib/ops_manager_ui_drivers/version14/product_logs.rb +38 -0
  68. data/lib/ops_manager_ui_drivers/version14/product_resource_configuration.rb +46 -0
  69. data/lib/ops_manager_ui_drivers/version14/product_status_helper.rb +64 -0
  70. data/lib/ops_manager_ui_drivers/version14/setup.rb +40 -0
  71. data/lib/ops_manager_ui_drivers/version14/state_change_progress.rb +43 -0
  72. data/lib/ops_manager_ui_drivers/version14/web_ui.rb +104 -0
  73. data/lib/ops_manager_ui_drivers/version15/availability_zones.rb +59 -0
  74. data/lib/ops_manager_ui_drivers/version15/available_products.rb +24 -0
  75. data/lib/ops_manager_ui_drivers/version15/iaas_configuration.rb +105 -0
  76. data/lib/ops_manager_ui_drivers/version15/job_availability_zone_mapping_helper.rb +70 -0
  77. data/lib/ops_manager_ui_drivers/version15/job_network_mapping_helper.rb +47 -0
  78. data/lib/ops_manager_ui_drivers/version15/job_status_helper.rb +17 -0
  79. data/lib/ops_manager_ui_drivers/version15/networks.rb +55 -0
  80. data/lib/ops_manager_ui_drivers/version15/ops_manager_director.rb +261 -0
  81. data/lib/ops_manager_ui_drivers/version15/product_availability_zones.rb +38 -0
  82. data/lib/ops_manager_ui_drivers/version15/product_configuration.rb +34 -0
  83. data/lib/ops_manager_ui_drivers/version15/product_dashboard.rb +176 -0
  84. data/lib/ops_manager_ui_drivers/version15/product_form.rb +47 -0
  85. data/lib/ops_manager_ui_drivers/version15/product_logs.rb +38 -0
  86. data/lib/ops_manager_ui_drivers/version15/product_resource_configuration.rb +63 -0
  87. data/lib/ops_manager_ui_drivers/version15/product_status_helper.rb +64 -0
  88. data/lib/ops_manager_ui_drivers/version15/setup.rb +44 -0
  89. data/lib/ops_manager_ui_drivers/version15/state_change_progress.rb +43 -0
  90. data/lib/ops_manager_ui_drivers/version15/web_ui.rb +104 -0
  91. data/lib/ops_manager_ui_drivers/wait_helper.rb +51 -0
  92. data/ops_manager_ui_drivers.gemspec +29 -0
  93. metadata +233 -0
@@ -0,0 +1,140 @@
1
+ module OpsManagerUiDrivers
2
+ module Version13
3
+ class OpsManagerDirector
4
+ def initialize(browser:)
5
+ @browser = browser
6
+ end
7
+
8
+ def configure_microbosh(test_settings)
9
+ @product = test_settings.persistent_ops_manager.v13.microbosh_product_name
10
+
11
+ configure_iaas(test_settings)
12
+
13
+ config_director(ntp_servers: test_settings.ops_manager.ntp_servers)
14
+
15
+ add_azs(test_settings.ops_manager.availability_zones)
16
+
17
+ assign_availability_zone(test_settings.ops_manager.availability_zones)
18
+
19
+ add_networks(test_settings.ops_manager.networks)
20
+
21
+ assign_networks(test_settings.ops_manager)
22
+ end
23
+
24
+ private
25
+ attr_reader :browser
26
+
27
+ def product
28
+ @product || 'microbosh'
29
+ end
30
+
31
+ def configure_iaas(test_settings)
32
+ case test_settings.iaas_type
33
+ when OpsManagerUiDrivers::VCLOUD_IAAS_TYPE then
34
+ configure_vcloud(
35
+ vcd_url: test_settings.ops_manager.vcloud.creds.url,
36
+ organization: test_settings.ops_manager.vcloud.creds.organization,
37
+ user: test_settings.ops_manager.vcloud.creds.user,
38
+ password: test_settings.ops_manager.vcloud.creds.password,
39
+ datacenter: test_settings.ops_manager.vcloud.vdc.name,
40
+ storage_profile: test_settings.ops_manager.vcloud.vdc.storage_profile,
41
+ )
42
+ when OpsManagerUiDrivers::VSPHERE_IAAS_TYPE then
43
+ configure_vcenter(
44
+ ip: test_settings.ops_manager.vcenter.creds.ip,
45
+ username: test_settings.ops_manager.vcenter.creds.username,
46
+ password: test_settings.ops_manager.vcenter.creds.password,
47
+ datacenter: test_settings.ops_manager.vcenter.datacenter,
48
+ datastores: test_settings.ops_manager.vcenter.datastore,
49
+ )
50
+ end
51
+ end
52
+
53
+ def add_azs(iaas_availability_zones)
54
+ iaas_availability_zones && iaas_availability_zones.each do |az|
55
+ availability_zones.add_az(az['name'], az['cluster'], az['resource_pool'])
56
+ end
57
+ end
58
+
59
+ def add_networks(iaas_networks)
60
+ iaas_networks && iaas_networks.each do |network|
61
+ networks.add_network(
62
+ name: network['name'],
63
+ iaas_network_identifier: network['identifier'],
64
+ subnet: network['subnet'],
65
+ dns: network['dns'],
66
+ gateway: network['gateway'],
67
+ reserved_ip_ranges: network['reserved_ips'],
68
+ )
69
+ end
70
+ end
71
+
72
+ def config_director(ntp_servers:)
73
+ browser.click_on 'Director Config'
74
+ browser.fill_in('director_configuration[ntp_servers_string]', with: ntp_servers)
75
+ browser.click_on 'Save'
76
+ end
77
+
78
+ def assign_availability_zone(iaas_availability_zones)
79
+ if iaas_availability_zones
80
+ browser.click_on 'Assign Availability Zones'
81
+ browser.select(iaas_availability_zones.first['name'])
82
+ browser.click_on 'Save'
83
+ end
84
+ end
85
+
86
+ def assign_networks(ops_manager)
87
+ deployment_network = ops_manager.networks[0]
88
+
89
+ infrastructure_network =
90
+ ops_manager.networks[1] ? ops_manager.networks[1] : ops_manager.networks[0]
91
+
92
+ assign_networks_on_browser(
93
+ infrastructure_network: infrastructure_network['name'],
94
+ deployment_network: deployment_network['name'],
95
+ )
96
+ end
97
+
98
+ def assign_networks_on_browser(infrastructure_network:, deployment_network:)
99
+ browser.click_on 'Assign Networks'
100
+
101
+ browser.within browser.find '#director_network_assignments_infrastructure_network' do
102
+ browser.select infrastructure_network
103
+ end
104
+
105
+ browser.within browser.find '#director_network_assignments_deployment_network' do
106
+ browser.select deployment_network
107
+ end
108
+ browser.click_on 'Save'
109
+ end
110
+
111
+ def configure_vcenter(ip:, username:, password:, datacenter:, datastores:)
112
+ iaas_configuration.configure_iaas do
113
+ iaas_configuration.set_vsphere_credentials(vcenter_ip: ip, username: username, password: password)
114
+ iaas_configuration.set_datacenter(datacenter)
115
+ iaas_configuration.set_datastores(datastores)
116
+ end
117
+ end
118
+
119
+ def configure_vcloud(vcd_url:, organization:, user:, password:, datacenter:, storage_profile:)
120
+ iaas_configuration.configure_iaas do
121
+ iaas_configuration.set_vcloud_credentials(vcd_url: vcd_url, organization: organization, user: user, password: password)
122
+ iaas_configuration.set_datacenter(datacenter)
123
+ iaas_configuration.set_storage_profile(storage_profile)
124
+ end
125
+ end
126
+
127
+ def iaas_configuration
128
+ @iaas_configuration ||= Version13::IaasConfiguration.new(browser: browser, product: product)
129
+ end
130
+
131
+ def availability_zones
132
+ @availability_zones ||= Version13::AvailabilityZones.new(browser: browser, product: product)
133
+ end
134
+
135
+ def networks
136
+ @networks ||= Version13::Networks.new(browser: browser, product: product)
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,38 @@
1
+ module OpsManagerUiDrivers
2
+ module Version13
3
+ class WebUi
4
+ class ProductAvailabilityZones
5
+ def initialize(browser:, product:)
6
+ @browser = browser
7
+ @product = product
8
+ end
9
+
10
+ def assign_availability_zones(singleton_availability_zone:, availability_zones:)
11
+ open_form
12
+ browser.choose(singleton_availability_zone)
13
+ # we don't change the assignments in clean install yet,
14
+ # otherwise we'd want to clear them out first
15
+ availability_zones.each do |az_name|
16
+ browser.check(az_name)
17
+ end
18
+ save_form
19
+ end
20
+
21
+ private
22
+ attr_reader :browser, :product
23
+
24
+ def open_form
25
+ browser.visit '/'
26
+ browser.click_on "show-#{product}-configure-action"
27
+ browser.click_on "show-#{product}-job-availability-zone-assignment-action"
28
+ end
29
+
30
+ def save_form
31
+ browser.click_on 'Save'
32
+
33
+ browser.expect(browser.page).to browser.have_css('.flash-message.success')
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,157 @@
1
+ module OpsManagerUiDrivers
2
+ module Version13
3
+ class ProductDashboard
4
+ def initialize(browser:)
5
+ @browser = browser
6
+ @allowed_ignorable_errors = []
7
+ end
8
+
9
+ def apply_updates
10
+ open_dashboard
11
+ browser.click_on 'install-action'
12
+ fail 'Install failed verification' if nonignorable_verification_failed?
13
+ allow_cpu_verification_errors
14
+ allow_privilege_verification_errors
15
+
16
+ ignore_allowable_errors
17
+ assert_installation_started
18
+ end
19
+
20
+ def import_installation_file(file_path)
21
+ open_dashboard
22
+ browser.click_on 'toggle-installation-dropdown-action'
23
+ browser.click_on 'show-import-backup'
24
+ browser.attach_file 'import[file]', file_path
25
+ browser.click_on 'import-backup'
26
+ end
27
+
28
+ def upgrade_microbosh
29
+ open_dashboard
30
+ browser.find('p', text: 'Ops Manager Director').trigger(:mouseover)
31
+ browser.click_on 'upgrade-microbosh'
32
+ end
33
+
34
+ def delete_product(product_name)
35
+ open_dashboard
36
+ browser.click_on "open-delete-#{product_name}-modal"
37
+ wait_for_modal_css_transition_to_complete
38
+ browser.click_on "delete-#{product_name}-action"
39
+ end
40
+
41
+ def import_product_from(full_path)
42
+ open_dashboard
43
+ browser.attach_file('component_add[file]', full_path, {visible: false})
44
+ end
45
+
46
+ def product_available?(product_name, product_version)
47
+ open_dashboard
48
+ browser.all("li.#{product_name} input#component_version[value='#{product_version}']", {visible: false}).any?
49
+ end
50
+
51
+ def upgrade_product(product_name)
52
+ open_dashboard
53
+ browser.find(".product.#{product_name} p").trigger(:mouseover)
54
+ browser.click_on "upgrade-#{product_name}"
55
+ expect_no_flash_errors
56
+ end
57
+
58
+ def version_for_product(product_name)
59
+ open_dashboard
60
+ browser.find("#show-#{product_name}-configure-action .version").text
61
+ end
62
+
63
+ def delete_whole_installation
64
+ open_dashboard
65
+ browser.click_on 'toggle-installation-dropdown-action'
66
+ browser.click_on 'show-delete-installation-modal-action'
67
+ wait_for_modal_css_transition_to_complete
68
+ browser.click_on 'delete-installation-action'
69
+ end
70
+
71
+ def delete_installation_available?
72
+ open_dashboard
73
+ browser.click_on 'toggle-installation-dropdown-action'
74
+ browser.all('#show-delete-installation-modal-action').any?
75
+ end
76
+
77
+ def deletion_in_progress?
78
+ open_dashboard
79
+ browser.all('#delete-in-progress-marker').any?
80
+ end
81
+
82
+ def reset_state
83
+ revert_pending_changes if revert_available?
84
+ delete_whole_installation if delete_installation_available?
85
+ end
86
+
87
+ private
88
+
89
+ attr_reader :browser
90
+
91
+ def assert_installation_started
92
+ browser.expect(browser.page).to browser.have_text('Installation in Progress')
93
+ end
94
+
95
+ def nonignorable_verification_failed?
96
+ browser.all('.flash-message.error').any? && browser.all('#ignore-install-action').empty?
97
+ end
98
+
99
+ def allow_cpu_verification_errors
100
+ cpu_verification_regex = /Installation requires \d+ CPU cores/
101
+ return if @allowed_ignorable_errors.include?(cpu_verification_regex)
102
+
103
+ @allowed_ignorable_errors << cpu_verification_regex
104
+ end
105
+
106
+ def allow_privilege_verification_errors
107
+ priveleges_regex = /privileges are required/i
108
+ return if @allowed_ignorable_errors.include?(priveleges_regex)
109
+
110
+ @allowed_ignorable_errors << priveleges_regex
111
+ end
112
+
113
+ def ignore_allowable_errors
114
+ flash_errors = browser.all('.flash-message.error')
115
+
116
+ if flash_errors.any?
117
+ unexpected_errors = flash_errors.reject do |error|
118
+ @allowed_ignorable_errors.select do |expected_error|
119
+ error.text =~ expected_error
120
+ end.any?
121
+ end
122
+
123
+ if unexpected_errors.empty?
124
+ browser.click_on 'ignore-install-action'
125
+ else
126
+ fail "Unexepcted ignorable errors: #{unexpected_errors.map(&:text).inspect}"
127
+ end
128
+ end
129
+ end
130
+
131
+ def expect_no_flash_errors
132
+ if (flash_error = browser.all('.flash-message.error').first)
133
+ fail flash_error.text
134
+ end
135
+ end
136
+
137
+ def wait_for_modal_css_transition_to_complete
138
+ sleep 5 # Have to wait for the CSS shade effect
139
+ end
140
+
141
+ def open_dashboard
142
+ browser.visit '/'
143
+ end
144
+
145
+ def revert_pending_changes
146
+ open_dashboard
147
+ browser.click_on 'open-revert-installation-modal-action'
148
+ wait_for_modal_css_transition_to_complete
149
+ browser.click_on 'revert-installation-action'
150
+ end
151
+
152
+ def revert_available?
153
+ browser.all('#open-revert-installation-modal-action').any?
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,53 @@
1
+ require 'date'
2
+
3
+ module OpsManagerUiDrivers
4
+ module Version13
5
+ class ProductLogs
6
+ def initialize(browser:, product_name:)
7
+ @browser = browser
8
+ @product_name = product_name
9
+ end
10
+
11
+ def request_job_logs(job_name)
12
+ visit_product_status_page
13
+ browser.find(%Q(a[id^="download-#{job_name}-"][id$="-0-log-action"])).click
14
+ end
15
+
16
+ def most_recent_log_creation_time
17
+ visit_product_logs_page
18
+
19
+ most_recent_logs_timestamp
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :product_name, :browser
25
+
26
+ def visit_product_configure_page
27
+ browser.visit('/')
28
+ browser.click_on("show-#{product_name}-configure-action")
29
+ end
30
+
31
+ def visit_product_status_page
32
+ visit_product_configure_page
33
+ browser.click_on('show-status-action')
34
+ end
35
+
36
+ def visit_product_logs_page
37
+ visit_product_configure_page
38
+ browser.click_on('show-logs-action')
39
+ end
40
+
41
+ def most_recent_logs
42
+ browser.all('#downloaded_logs tr').select { |e| e.find(%Q(a[href^="/products/#{product_name}"])) }.last
43
+ end
44
+
45
+ def most_recent_logs_timestamp
46
+ return unless (log_row = most_recent_logs)
47
+
48
+ date_string = log_row.all('td').last.text
49
+ DateTime.parse(date_string)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,46 @@
1
+ module OpsManagerUiDrivers
2
+ module Version13
3
+ class ProductResourceConfiguration
4
+ attr_reader :product_name
5
+
6
+ def initialize(browser:, product_name:)
7
+ @browser = browser
8
+ @product_name = product_name
9
+ end
10
+
11
+ def set_instances_for_job(job_name, instance_count)
12
+ open_form
13
+ browser.find_field("product_resources_form[#{job_name}][instances][value]").set(instance_count)
14
+ save_form
15
+ end
16
+
17
+ def set_elb_for_job(job_name, elb_name)
18
+ open_form
19
+ browser.find_field("product_resources_form[#{job_name}][elb_name]").set(elb_name)
20
+ save_form
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :browser
26
+
27
+ def open_form
28
+ browser.visit '/'
29
+ browser.click_on "show-#{product_name}-configure-action"
30
+ browser.click_on "show-#{product_name}-resource-sizes-action"
31
+ end
32
+
33
+ def save_form
34
+ browser.click_on 'Save'
35
+
36
+ unless browser.has_css?('.flash-message.success')
37
+ if browser.has_css?('.flash-message.error')
38
+ raise browser.find('.flash-message.error').text
39
+ else
40
+ raise 'unexpected failure'
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,64 @@
1
+ module OpsManagerUiDrivers
2
+ module Version13
3
+ class ProductStatusHelper
4
+ def initialize(product_name:, browser:)
5
+ @product_name = product_name
6
+ @browser = browser
7
+ end
8
+
9
+ def job_status(job_name)
10
+ open_page
11
+
12
+ wait_for_loading_indicator_to_disappear
13
+
14
+ browser.within "##{product_name}-status" do
15
+ job_row = browser.find(:xpath, ".//tr[@data-ip-name = '#{job_name}']")
16
+
17
+ Version13::JobStatusHelper.from_job_row(job_row)
18
+ end
19
+ end
20
+
21
+ def job_status_in_az(job_name, az_guid)
22
+ open_page
23
+
24
+ wait_for_loading_indicator_to_disappear
25
+
26
+ browser.within "##{product_name}-#{az_guid}-status-table" do
27
+ job_row = browser.find(:xpath, ".//tr[@data-ip-name = '#{job_name}']")
28
+
29
+ Version13::JobStatusHelper.from_job_row(job_row)
30
+ end
31
+ end
32
+
33
+ def resource_pool_for_job_in_az(job_name, az_guid, vsphere_connection)
34
+ job_status = job_status_in_az("#{job_name}-partition-#{az_guid}", az_guid)
35
+
36
+ job_ip = job_status.ips.fetch(0)
37
+
38
+ vm = vsphere_connection.searchIndex.FindByIp(ip: job_ip, vmSearch: true)
39
+ vm.resourcePool.name
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :browser, :product_name
45
+
46
+ def open_page
47
+ browser.visit '/'
48
+
49
+ browser.click_on "show-#{dasherized_product_name}-configure-action"
50
+ browser.click_on 'show-status-action'
51
+ end
52
+
53
+ def wait_for_loading_indicator_to_disappear
54
+ Capybara.using_wait_time 10 do
55
+ browser.all('.status-loading', count: 0) # blocks until there are no spinners
56
+ end
57
+ end
58
+
59
+ def dasherized_product_name
60
+ product_name.to_s.gsub(/[_]/, '-')
61
+ end
62
+ end
63
+ end
64
+ end