prof 0.29.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/LEGAL +13 -0
  3. data/lib/prof/cloud_foundry.rb +145 -0
  4. data/lib/prof/environment/cloud_foundry.rb +150 -0
  5. data/lib/prof/environment/pcf_drinks.rb +156 -0
  6. data/lib/prof/environment_manager.rb +93 -0
  7. data/lib/prof/external_spec/helpers/capybara.rb +58 -0
  8. data/lib/prof/external_spec/helpers/debug.rb +53 -0
  9. data/lib/prof/external_spec/helpers/file_helper.rb +35 -0
  10. data/lib/prof/external_spec/helpers/product_path.rb +23 -0
  11. data/lib/prof/external_spec/shared_examples/deployment.rb +23 -0
  12. data/lib/prof/external_spec/shared_examples/ops_manager_upgrade.rb +32 -0
  13. data/lib/prof/external_spec/shared_examples/service.rb +105 -0
  14. data/lib/prof/external_spec/shared_examples/service_broker.rb +25 -0
  15. data/lib/prof/external_spec/spec_helper.rb +35 -0
  16. data/lib/prof/marketplace_service.rb +20 -0
  17. data/lib/prof/matchers/metadata.rb +180 -0
  18. data/lib/prof/matchers/only_support_ssl_with_cipher_set.rb +102 -0
  19. data/lib/prof/matchers/ssl.rb +67 -0
  20. data/lib/prof/matchers/tile_configuration.rb +47 -0
  21. data/lib/prof/ops_manager/rails_500_error.rb +15 -0
  22. data/lib/prof/ops_manager/web_app_internals/page/checkbox_field.rb +38 -0
  23. data/lib/prof/ops_manager/web_app_internals/page/click_field.rb +40 -0
  24. data/lib/prof/ops_manager/web_app_internals/page/dashboard.rb +100 -0
  25. data/lib/prof/ops_manager/web_app_internals/page/flash_message.rb +53 -0
  26. data/lib/prof/ops_manager/web_app_internals/page/form.rb +130 -0
  27. data/lib/prof/ops_manager/web_app_internals/page/form_error.rb +43 -0
  28. data/lib/prof/ops_manager/web_app_internals/page/form_field.rb +51 -0
  29. data/lib/prof/ops_manager/web_app_internals/page/form_fields.rb +35 -0
  30. data/lib/prof/ops_manager/web_app_internals/page/installation_progress.rb +149 -0
  31. data/lib/prof/ops_manager/web_app_internals/page/login.rb +53 -0
  32. data/lib/prof/ops_manager/web_app_internals/page/modal.rb +85 -0
  33. data/lib/prof/ops_manager/web_app_internals/page/rails_500.rb +41 -0
  34. data/lib/prof/ops_manager/web_app_internals/page/select_field.rb +27 -0
  35. data/lib/prof/ops_manager/web_app_internals/page/tile_settings.rb +105 -0
  36. data/lib/prof/ops_manager/web_app_internals.rb +63 -0
  37. data/lib/prof/ops_manager.rb +141 -0
  38. data/lib/prof/ops_manager_log_fetcher.rb +30 -0
  39. data/lib/prof/product.rb +59 -0
  40. data/lib/prof/pushed_test_app.rb +40 -0
  41. data/lib/prof/service_instance.rb +21 -0
  42. data/lib/prof/ssh_gateway.rb +104 -0
  43. data/lib/prof/ssl/check.rb +79 -0
  44. data/lib/prof/ssl/cipher_set.rb +56 -0
  45. data/lib/prof/ssl/result.rb +27 -0
  46. data/lib/prof/ssl/results.rb +74 -0
  47. data/lib/prof/test_app.rb +19 -0
  48. data/lib/prof/tile.rb +25 -0
  49. data/lib/prof/uaa_client.rb +66 -0
  50. data/lib/prof/version.rb +13 -0
  51. metadata +403 -0
@@ -0,0 +1,47 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ require 'rspec/expectations'
12
+
13
+ RSpec::Matchers.define :have_configuration_fields_on do |tile|
14
+ match do |_ops_manager|
15
+ @tile = tile
16
+ (expected_field_names - actual_field_names).empty?
17
+ end
18
+
19
+ chain :including do |*fields|
20
+ @expected_field_names = fields
21
+ end
22
+
23
+ failure_message do |_actual|
24
+ [
25
+ 'expected:',
26
+ "\t#{expected_field_names.inspect}",
27
+ 'to be present in:',
28
+ "\t#{actual_field_names}",
29
+ 'but these were not found',
30
+ "\t#{(expected_field_names - actual_field_names).inspect}"
31
+ ].join("\n")
32
+ end
33
+
34
+ def expected_field_names
35
+ raise 'Please set including' if @expected_field_names.nil?
36
+
37
+ @expected_field_names
38
+ end
39
+
40
+ def actual_config
41
+ @actual_config ||= ops_manager.tile_configuration(@tile)
42
+ end
43
+
44
+ def actual_field_names
45
+ actual_config.map { |_header, fields| fields.keys }.flatten
46
+ end
47
+ end
@@ -0,0 +1,15 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ module Prof
12
+ class OpsManager
13
+ class Rails500Error < StandardError; end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ require 'prof/ops_manager/web_app_internals/page/form_field'
12
+
13
+ module Prof
14
+ class OpsManager
15
+ class WebAppInternals
16
+ module Page
17
+ class CheckboxField < FormField
18
+ def initialize(name:, value:, checked:)
19
+ super(name: name, value: value)
20
+ @checked = checked
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :checked
26
+
27
+ def selector
28
+ super + "[value$='#{value}']"
29
+ end
30
+
31
+ def set_value(field)
32
+ field.set(checked)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ require 'prof/ops_manager/web_app_internals/page/form_field'
12
+
13
+ module Prof
14
+ class OpsManager
15
+ class WebAppInternals
16
+ module Page
17
+ class ClickField < FormField
18
+ def initialize(name:, expected_state: )
19
+ super(name: name, value: nil)
20
+ @expected_state = expected_state
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :expected_state
26
+
27
+ def selector
28
+ super + ":not([type=hidden])"
29
+ end
30
+
31
+ def set_value(field)
32
+ unless field.checked? == expected_state
33
+ field.click
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,100 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ require 'prof/ops_manager/web_app_internals/page/installation_progress'
12
+ require 'prof/ops_manager/web_app_internals/page/modal'
13
+ require 'prof/ops_manager/web_app_internals/page/tile_settings'
14
+
15
+ module Prof
16
+ class OpsManager
17
+ class WebAppInternals
18
+ module Page
19
+ class Dashboard
20
+
21
+ class ModalPresent < StandardError; end
22
+
23
+ def initialize(opts = {})
24
+ @page = opts.fetch(:page)
25
+ end
26
+
27
+ def tile(tile)
28
+ begin
29
+ page.find("#show-#{tile.name}-configure-action").click
30
+ rescue Capybara::ElementNotFound
31
+ page.visit(page.current_url)
32
+ page.find("#show-#{tile.name}-configure-action").click
33
+ end
34
+
35
+ TileSettings.new(page: page)
36
+ end
37
+
38
+ def tile_configure(target_tile, configuration)
39
+ tile(target_tile).configure(configuration)
40
+ end
41
+
42
+ def tile_configuration(target_tile)
43
+ tile_setting_page = tile(target_tile)
44
+
45
+ Hash.new.tap do |config|
46
+ tile_setting_page.setting_names.each do |setting_name|
47
+ config[setting_name] = tile_setting_page.settings_for(setting_name)
48
+ end
49
+
50
+ tile_setting_page.return_to_dashboard
51
+ end
52
+ end
53
+
54
+ def apply_setting(target_tile, field_name, field_value)
55
+ tile(target_tile).set_field_value('Resource Config', field_name, field_value).return_to_dashboard
56
+ end
57
+
58
+ def tile_configured?(target_tile)
59
+ page.find("#show-#{target_tile.name}-configure-action")['data-progress'] == '100'
60
+ rescue Capybara::ElementNotFound
61
+ false
62
+ end
63
+
64
+ def tile_uninstall(target_tile)
65
+ page.find("#show-#{target_tile.name}-configure-action ~ #open-delete-#{target_tile.name}-modal").click
66
+ modal.confirm
67
+ rescue Capybara::ElementNotFound
68
+ end
69
+
70
+ def apply_changes
71
+ check_no_modal!
72
+
73
+ page.click_link_or_button 'Apply changes'
74
+ InstallationProgress.new(page: page)
75
+ end
76
+
77
+ def pending_changes?
78
+ pending_changes.any?
79
+ end
80
+
81
+ def pending_changes
82
+ page.all('.pending-changes-list li').map(&:text)
83
+ end
84
+
85
+ private
86
+
87
+ attr_reader :page
88
+
89
+ def check_no_modal!
90
+ raise ModalPresent, "A modal was present with text: '#{modal.message}'" if modal.present?
91
+ end
92
+
93
+ def modal
94
+ Modal.new(page: page)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ module Prof
12
+ class OpsManager
13
+ class WebAppInternals
14
+ module Page
15
+ class FlashMessage
16
+ def initialize(opts = {})
17
+ @page = opts.fetch(:page)
18
+ end
19
+
20
+ def text
21
+ page.find('.flash-message:not(.in-progress)', wait: 60).text
22
+ end
23
+
24
+ def success?
25
+ !error? && page.all('.flash-message.success').any?
26
+ end
27
+
28
+ def error?
29
+ page.all('.flash-message.error').any?
30
+ end
31
+
32
+ def installation_in_progress?
33
+ page.all('.flash-message.in-progress').any?
34
+ end
35
+
36
+ def icmp_error?
37
+ return false unless error?
38
+ error = page.all('.flash-message.error').first.text
39
+ error.include? 'ignorable if ICMP is disabled'
40
+ end
41
+
42
+ def ignore_warnings
43
+ page.find('#ignore-install-action').click
44
+ end
45
+
46
+ private
47
+
48
+ attr_reader :page
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,130 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ require 'prof/ops_manager/web_app_internals/page/form_error'
12
+ require 'prof/ops_manager/web_app_internals/page/flash_message'
13
+ require 'prof/ops_manager/web_app_internals/page/form_fields'
14
+ require 'prof/ops_manager/web_app_internals/page/form_field'
15
+ require 'prof/ops_manager/web_app_internals/page/select_field'
16
+ require 'prof/ops_manager/web_app_internals/page/checkbox_field'
17
+ require 'prof/ops_manager/web_app_internals/page/click_field'
18
+
19
+ module Prof
20
+ class OpsManager
21
+ class WebAppInternals
22
+ module Page
23
+ class Form
24
+ def initialize(opts = {})
25
+ @page = opts.fetch(:page)
26
+ @form_element = opts.fetch(:form_element)
27
+ end
28
+
29
+ def update(config = {}, &_block)
30
+ case config
31
+ when Array
32
+ update_list(config)
33
+ when Hash, FormFields
34
+ raise "Add button on page #{page.current_url}, maybe you should update a list?" if add_button
35
+
36
+ update_fields(config)
37
+ else
38
+ raise "Unrecognised config #{config.inspect}"
39
+ end
40
+
41
+ yield self, page if block_given?
42
+
43
+ form_element.click_on 'Save'
44
+
45
+ # raise "Failed to save, the server 500ed" if page.status_code.to_i >= 500
46
+ raise "Failed to save, no success message. #{error_message}" unless success?
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :form_element, :page
52
+
53
+ def update_list(list)
54
+ raise "No add button on page #{page.current_url}, are you sure you want to update a list?" unless add_button
55
+ clear_list
56
+
57
+ list.each do |item_config|
58
+ add_button.click
59
+
60
+ update_fields(item_config)
61
+ end
62
+ end
63
+
64
+ def clear_list
65
+ form_element.all('.with-delete-record').each(&:click)
66
+ end
67
+
68
+ def add_button
69
+ form_element.first(:link_or_button, 'Add')
70
+ end
71
+
72
+ def update_fields(config)
73
+ if(config.is_a? FormFields)
74
+ update_fields_from_form_fields(config)
75
+ else
76
+ update_fields_from_string_hash(config)
77
+ end
78
+ end
79
+
80
+ def update_fields_from_string_hash(config)
81
+ config.each do |field, value|
82
+ selector = field_to_selector(field)
83
+ input = form_element.all(selector).last
84
+
85
+ raise "Could not find element with selector #{selector}" unless input
86
+
87
+ if input.tag_name == 'select'
88
+ input.find(:option, value).select_option
89
+ else
90
+ input.set(value)
91
+ end
92
+ end
93
+ end
94
+
95
+ def update_fields_from_form_fields(config)
96
+ config.each do |field|
97
+ field.set(form_element)
98
+ end
99
+ end
100
+
101
+ def field_to_selector(field)
102
+ if field.include?('[') && field.include?(']')
103
+ "[name='#{field}']"
104
+ else
105
+ "[name$='#{field}]']"
106
+ end
107
+ end
108
+
109
+ def success?
110
+ flash_message.success?
111
+ end
112
+
113
+ def error_message
114
+ "#{flash_message.text} #{errors.join(', ')}"
115
+ end
116
+
117
+ def flash_message
118
+ FlashMessage.new(page: page)
119
+ end
120
+
121
+ def errors
122
+ form_element.all('.help-block').map do |error_element|
123
+ FormError.new(error_element: error_element)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,43 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ module Prof
12
+ class OpsManager
13
+ class WebAppInternals
14
+ module Page
15
+ class FormError
16
+ def initialize(opts = {})
17
+ @error_element = opts.fetch(:error_element)
18
+ end
19
+
20
+ def name
21
+ /[^\[]*\[([^\]]+)\]$/.match(full_name).to_a[1]
22
+ end
23
+
24
+ def error
25
+ error_element.text
26
+ end
27
+
28
+ def to_s
29
+ "#{name} #{error}"
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :error_element
35
+
36
+ def full_name
37
+ error_element.find('~ input')[:name]
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ module Prof
12
+ class OpsManager
13
+ class WebAppInternals
14
+ module Page
15
+ class FormField
16
+
17
+ def initialize(name:, value:)
18
+ @name = name
19
+ @value = value
20
+ end
21
+
22
+ def set(form_element)
23
+ field = find_field(form_element)
24
+ raise "Could not find element with name #{name} and selector #{selector}" unless field
25
+ set_value(field)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :name, :value
31
+
32
+ def find_field(form_element)
33
+ form_element.all(selector).last
34
+ end
35
+
36
+ def set_value(field)
37
+ field.set(value)
38
+ end
39
+
40
+ def selector
41
+ if name.include?('[') && name.include?(']')
42
+ "[name='#{name}']"
43
+ else
44
+ "[name$='[#{name}]']"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
2
+ # All rights reserved.
3
+ # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
4
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
5
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
6
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
7
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
8
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
9
+ #
10
+
11
+ module Prof
12
+ class OpsManager
13
+ class WebAppInternals
14
+ module Page
15
+ class FormFields
16
+ include Enumerable
17
+
18
+ def initialize(fields)
19
+ @fields = fields
20
+ end
21
+
22
+ def each
23
+ fields.each do |field|
24
+ yield field
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :fields
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end