howitzer 1.1.1 → 2.0.0

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 (166) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +32 -0
  4. data/.travis.yml +1 -4
  5. data/.yardopts +1 -2
  6. data/CHANGELOG.md +28 -1
  7. data/Gemfile +6 -0
  8. data/LICENSE +1 -1
  9. data/README.md +55 -85
  10. data/Rakefile +7 -7
  11. data/bin/howitzer +56 -31
  12. data/features/cli_new.feature +162 -79
  13. data/features/cli_update.feature +114 -21
  14. data/features/step_definitions/common_steps.rb +29 -9
  15. data/features/support/env.rb +1 -1
  16. data/features/support/transformers.rb +2 -2
  17. data/generators/base_generator.rb +121 -49
  18. data/generators/config/config_generator.rb +8 -5
  19. data/generators/config/templates/boot.rb +14 -0
  20. data/generators/config/templates/capybara.rb +156 -0
  21. data/generators/config/templates/custom.yml +2 -3
  22. data/generators/config/templates/default.yml +50 -82
  23. data/generators/cucumber/cucumber_generator.rb +9 -9
  24. data/generators/cucumber/templates/common_steps.rb +4 -4
  25. data/generators/cucumber/templates/cucumber.rake +63 -54
  26. data/generators/cucumber/templates/env.rb +24 -23
  27. data/generators/cucumber/templates/transformers.rb +23 -15
  28. data/generators/emails/emails_generator.rb +4 -2
  29. data/generators/emails/templates/example_email.rb +4 -4
  30. data/generators/prerequisites/prerequisites_generator.rb +24 -0
  31. data/generators/prerequisites/templates/base.rb +22 -0
  32. data/generators/prerequisites/templates/factory_girl.rb +30 -0
  33. data/generators/prerequisites/templates/user.rb +7 -0
  34. data/generators/prerequisites/templates/users.rb +12 -0
  35. data/generators/root/root_generator.rb +11 -7
  36. data/generators/root/templates/.rubocop.yml +32 -0
  37. data/generators/root/templates/Gemfile.erb +27 -0
  38. data/generators/root/templates/Rakefile +6 -8
  39. data/generators/rspec/rspec_generator.rb +7 -7
  40. data/generators/rspec/templates/example_spec.rb +1 -1
  41. data/generators/rspec/templates/rspec.rake +48 -29
  42. data/generators/rspec/templates/spec_helper.rb +33 -32
  43. data/generators/tasks/tasks_generator.rb +4 -2
  44. data/generators/tasks/templates/common.rake +1 -16
  45. data/generators/turnip/templates/.rspec +1 -0
  46. data/generators/turnip/templates/common_steps.rb +25 -0
  47. data/generators/turnip/templates/example.feature +8 -0
  48. data/generators/turnip/templates/spec_helper.rb +56 -0
  49. data/generators/turnip/templates/turnip.rake +61 -0
  50. data/generators/turnip/templates/turnip_helper.rb +6 -0
  51. data/generators/turnip/turnip_generator.rb +26 -0
  52. data/generators/web/templates/example_page.rb +15 -0
  53. data/generators/web/templates/menu_section.rb +13 -0
  54. data/generators/web/web_generator.rb +22 -0
  55. data/howitzer.gemspec +14 -21
  56. data/lib/howitzer.rb +47 -7
  57. data/lib/howitzer/cache.rb +70 -0
  58. data/lib/howitzer/capybara_helpers.rb +194 -0
  59. data/lib/howitzer/email.rb +96 -104
  60. data/lib/howitzer/exceptions.rb +10 -6
  61. data/lib/howitzer/log.rb +120 -0
  62. data/lib/howitzer/mail_adapters.rb +7 -0
  63. data/lib/howitzer/mail_adapters/abstract.rb +84 -0
  64. data/lib/howitzer/mail_adapters/mailgun.rb +115 -0
  65. data/lib/howitzer/mailgun_api.rb +9 -0
  66. data/lib/howitzer/mailgun_api/client.rb +79 -0
  67. data/lib/howitzer/mailgun_api/connector.rb +37 -0
  68. data/lib/howitzer/mailgun_api/response.rb +28 -0
  69. data/lib/howitzer/tasks/framework.rake +2 -2
  70. data/lib/howitzer/utils.rb +7 -1
  71. data/lib/howitzer/utils/string_extensions.rb +66 -0
  72. data/lib/howitzer/version.rb +2 -1
  73. data/lib/howitzer/web.rb +11 -0
  74. data/lib/howitzer/web/base_section.rb +27 -0
  75. data/lib/howitzer/web/blank_page.rb +12 -0
  76. data/lib/howitzer/web/capybara_methods_proxy.rb +29 -0
  77. data/lib/howitzer/web/element_dsl.rb +109 -0
  78. data/lib/howitzer/web/iframe_dsl.rb +93 -0
  79. data/lib/howitzer/web/page.rb +173 -0
  80. data/lib/howitzer/web/page_dsl.rb +64 -0
  81. data/lib/howitzer/web/page_validator.rb +118 -0
  82. data/lib/howitzer/web/section.rb +27 -0
  83. data/lib/howitzer/web/section_dsl.rb +154 -0
  84. data/spec/config/custom.yml +10 -1
  85. data/spec/spec_helper.rb +37 -19
  86. data/spec/support/generator_helper.rb +12 -11
  87. data/spec/support/logger_helper.rb +10 -9
  88. data/spec/support/mailgun_unit_client.rb +52 -44
  89. data/spec/support/shared_examples/capybara_context_holder.rb +33 -0
  90. data/spec/support/shared_examples/capybara_methods_proxy.rb +94 -0
  91. data/spec/support/shared_examples/dynamic_section_methods.rb +35 -0
  92. data/spec/support/shared_examples/element_dsl.rb +119 -0
  93. data/spec/unit/generators/base_generator_spec.rb +64 -33
  94. data/spec/unit/generators/config_generator_spec.rb +11 -7
  95. data/spec/unit/generators/cucumber_generator_spec.rb +26 -17
  96. data/spec/unit/generators/emails_generator_spec.rb +10 -6
  97. data/spec/unit/generators/prerequisites_generator_spec.rb +53 -0
  98. data/spec/unit/generators/root_generator_spec.rb +50 -13
  99. data/spec/unit/generators/rspec_generator_spec.rb +9 -9
  100. data/spec/unit/generators/tasks_generator_spec.rb +6 -6
  101. data/spec/unit/generators/turnip_generator_spec.rb +52 -0
  102. data/spec/unit/generators/web_generator_spec.rb +52 -0
  103. data/spec/unit/lib/cache_spec.rb +85 -0
  104. data/spec/unit/lib/capybara_helpers_spec.rb +696 -0
  105. data/spec/unit/lib/email_spec.rb +104 -91
  106. data/spec/unit/lib/howitzer.rb +31 -0
  107. data/spec/unit/lib/init_spec.rb +0 -1
  108. data/spec/unit/lib/log_spec.rb +122 -0
  109. data/spec/unit/lib/mail_adapters/abstract_spec.rb +62 -0
  110. data/spec/unit/lib/mail_adapters/mailgun_spec.rb +163 -0
  111. data/spec/unit/lib/mailgun_api/client_spec.rb +58 -0
  112. data/spec/unit/lib/mailgun_api/connector_spec.rb +54 -0
  113. data/spec/unit/lib/mailgun_api/response_spec.rb +28 -0
  114. data/spec/unit/lib/utils/string_extensions_spec.rb +77 -0
  115. data/spec/unit/lib/web/base_section_spec.rb +41 -0
  116. data/spec/unit/lib/web/element_dsl_spec.rb +17 -0
  117. data/spec/unit/lib/web/iframe_dsl_spec.rb +99 -0
  118. data/spec/unit/lib/web/page_dsl_spec.rb +52 -0
  119. data/spec/unit/lib/web/page_spec.rb +304 -0
  120. data/spec/unit/lib/web/page_validator_spec.rb +218 -0
  121. data/spec/unit/lib/web/section_dsl_spec.rb +165 -0
  122. data/spec/unit/lib/web/section_spec.rb +61 -0
  123. data/spec/unit/version_spec.rb +1 -1
  124. metadata +116 -203
  125. data/GETTING_STARTED.md +0 -774
  126. data/generators/cucumber/templates/cucumber.yml +0 -10
  127. data/generators/pages/pages_generator.rb +0 -21
  128. data/generators/pages/templates/example_menu.rb +0 -15
  129. data/generators/pages/templates/example_page.rb +0 -15
  130. data/generators/root/templates/Gemfile +0 -7
  131. data/generators/root/templates/boot.rb +0 -10
  132. data/lib/howitzer/blank_page.rb +0 -6
  133. data/lib/howitzer/capybara/dsl_ex.rb +0 -15
  134. data/lib/howitzer/capybara/settings.rb +0 -343
  135. data/lib/howitzer/helpers.rb +0 -230
  136. data/lib/howitzer/init.rb +0 -1
  137. data/lib/howitzer/mailgun/client.rb +0 -65
  138. data/lib/howitzer/mailgun/connector.rb +0 -34
  139. data/lib/howitzer/mailgun/response.rb +0 -28
  140. data/lib/howitzer/patches/rawler_patched.rb +0 -86
  141. data/lib/howitzer/settings.rb +0 -27
  142. data/lib/howitzer/utils/data_generator/data_storage.rb +0 -88
  143. data/lib/howitzer/utils/data_generator/gen.rb +0 -135
  144. data/lib/howitzer/utils/locator_store.rb +0 -217
  145. data/lib/howitzer/utils/log.rb +0 -139
  146. data/lib/howitzer/utils/page_validator.rb +0 -133
  147. data/lib/howitzer/vendor/firebug-1.12.1-fx.xpi +0 -0
  148. data/lib/howitzer/vendor/firepath-0.9.7-fx.xpi +0 -0
  149. data/lib/howitzer/web_page.rb +0 -253
  150. data/spec/active_resource.rb +0 -0
  151. data/spec/config/default.yml +0 -26
  152. data/spec/support/boot_helper.rb +0 -15
  153. data/spec/unit/generators/pages_generator_spec.rb +0 -33
  154. data/spec/unit/lib/capybara/dsl_ex_spec.rb +0 -60
  155. data/spec/unit/lib/capybara/settings_spec.rb +0 -441
  156. data/spec/unit/lib/helpers_spec.rb +0 -1129
  157. data/spec/unit/lib/mailgun/client_spec.rb +0 -36
  158. data/spec/unit/lib/mailgun/connector_spec.rb +0 -70
  159. data/spec/unit/lib/mailgun/response_spec.rb +0 -28
  160. data/spec/unit/lib/settings_spec.rb +0 -17
  161. data/spec/unit/lib/utils/data_generator/data_storage_spec.rb +0 -80
  162. data/spec/unit/lib/utils/data_generator/gen_spec.rb +0 -90
  163. data/spec/unit/lib/utils/locator_store_spec.rb +0 -157
  164. data/spec/unit/lib/utils/log_spec.rb +0 -107
  165. data/spec/unit/lib/utils/page_validator_spec.rb +0 -265
  166. data/spec/unit/lib/web_page_spec.rb +0 -346
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'howitzer/web/page_dsl'
3
+
4
+ RSpec.describe Howitzer::Web::PageDsl do
5
+ let(:page) { Class.new { include Howitzer::Web::PageDsl } }
6
+
7
+ describe '.on' do
8
+ subject { page.on { 1 } }
9
+ before { expect(Howitzer::Web::PageDsl::PageScope).to receive(:new).with(page) }
10
+ it { is_expected.to be_nil }
11
+ end
12
+ end
13
+
14
+ RSpec.describe Howitzer::Web::PageDsl::PageScope do
15
+ let(:fake_page) { double }
16
+ let(:page) { Class.new }
17
+ before { allow(page).to receive(:given) { fake_page } }
18
+
19
+ describe '.new' do
20
+ subject { described_class.new(page) { bar } }
21
+ before { expect_any_instance_of(described_class).to receive(:bar).with(no_args) { true } }
22
+ it { is_expected.to be_a(described_class) }
23
+ end
24
+
25
+ describe '#is_expected' do
26
+ let(:scope) { described_class.new(page) { 1 } }
27
+ subject { scope.is_expected }
28
+ before { expect(scope).to receive(:expect).with(fake_page) { true } }
29
+ it { is_expected.to eq(true) }
30
+ end
31
+
32
+ describe '#method_missing' do
33
+ context 'when starts with be_' do
34
+ let(:scope) { described_class.new(page) { 1 } }
35
+ subject { scope.be_a(described_class) }
36
+ it { expect(subject.class).to eq(RSpec::Matchers::BuiltIn::BeAKindOf) }
37
+ end
38
+
39
+ context 'when starts with have_' do
40
+ let(:scope) { described_class.new(page) { 1 } }
41
+ subject { scope.have_content(described_class) }
42
+ it { expect(subject.class).to eq(RSpec::Matchers::BuiltIn::Has) }
43
+ end
44
+
45
+ context 'when starts other prefix' do
46
+ let(:scope) { described_class.new(page) { 1 } }
47
+ subject { scope.foo(1, 2, 3) }
48
+ before { expect(fake_page).to receive(:foo).with(1, 2, 3) { true } }
49
+ it { is_expected.to eq(true) }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,304 @@
1
+ require 'spec_helper'
2
+ require 'howitzer/web/page'
3
+ require 'howitzer/web/blank_page'
4
+
5
+ RSpec.describe Howitzer::Web::Page do
6
+ let(:session) { double(:session) }
7
+ before { allow(Capybara).to receive(:current_session) { session } }
8
+ describe '.open' do
9
+ let(:retryable) { double }
10
+ let(:check_correct_page_loaded) { double }
11
+ let(:other_instance) { described_class.instance }
12
+ context 'when validate missing' do
13
+ context 'when params present' do
14
+ let(:url_value) { 'http://example.com/users/1' }
15
+ subject { described_class.open(id: 1) }
16
+ it do
17
+ expect(described_class).to receive(:expanded_url).with(id: 1) { url_value }.once.ordered
18
+ expect(Howitzer::Log).to receive(:info)
19
+ .with("Open #{described_class} page by '#{url_value}' url").once.ordered
20
+ expect(described_class).to receive(:retryable).ordered.once.and_call_original
21
+ expect(session).to receive(:visit).with(url_value).once.ordered
22
+ expect(described_class).to receive(:given).once.ordered { true }
23
+ expect(subject).to eq(true)
24
+ end
25
+ end
26
+ context 'when params missing' do
27
+ let(:url_value) { 'http://example.com/users' }
28
+ subject { described_class.open }
29
+ it do
30
+ expect(described_class).to receive(:expanded_url).with({}) { url_value }.once.ordered
31
+ expect(Howitzer::Log).to receive(:info)
32
+ .with("Open #{described_class} page by '#{url_value}' url").once.ordered
33
+ expect(described_class).to receive(:retryable).ordered.once.and_call_original
34
+ expect(session).to receive(:visit).with(url_value).once.ordered
35
+ expect(described_class).to receive(:given).once.ordered { true }
36
+ expect(subject).to eq(true)
37
+ end
38
+ end
39
+ end
40
+ context 'when validate: false' do
41
+ let(:url_value) { 'http://example.com/users' }
42
+ subject { described_class.open(validate: false) }
43
+ it do
44
+ expect(described_class).to receive(:expanded_url).with({}) { url_value }.once.ordered
45
+ expect(Howitzer::Log).to receive(:info).with("Open #{described_class} page by '#{url_value}' url").once.ordered
46
+ expect(described_class).to receive(:retryable).ordered.once.and_call_original
47
+ expect(session).to receive(:visit).with(url_value).once.ordered
48
+ expect(described_class).not_to receive(:given)
49
+ expect(subject).to be_nil
50
+ end
51
+ end
52
+ context 'when validate: true with params' do
53
+ let(:url_value) { 'http://example.com/users/1' }
54
+ subject { described_class.open(validate: true, id: 1) }
55
+ it do
56
+ expect(described_class).to receive(:expanded_url).with(id: 1) { url_value }.once.ordered
57
+ expect(Howitzer::Log).to receive(:info).with("Open #{described_class} page by '#{url_value}' url").once.ordered
58
+ expect(described_class).to receive(:retryable).ordered.once.and_call_original
59
+ expect(session).to receive(:visit).with(url_value).once.ordered
60
+ expect(described_class).to receive(:given).once.ordered { true }
61
+ expect(subject).to eq(true)
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '.given' do
67
+ subject { described_class.given }
68
+ before do
69
+ expect(described_class).to receive(:displayed?).with(no_args).once
70
+ expect(described_class).to receive(:instance) { true }
71
+ end
72
+ it { is_expected.to be_truthy }
73
+ end
74
+
75
+ describe '.title' do
76
+ let(:page) { double }
77
+ subject { described_class.instance.title }
78
+ before do
79
+ allow_any_instance_of(described_class).to receive(:check_validations_are_defined!) { true }
80
+ allow(session).to receive(:current_url) { 'google.com' }
81
+ end
82
+ it do
83
+ expect(session).to receive(:title)
84
+ subject
85
+ end
86
+ end
87
+
88
+ describe '.current_page' do
89
+ subject { described_class.current_page }
90
+ context 'when matched_pages has no pages' do
91
+ before { allow(described_class).to receive(:matched_pages) { [] } }
92
+ it { is_expected.to eq(described_class::UnknownPage) }
93
+ end
94
+ context 'when matched_pages has more than 1 page' do
95
+ let(:foo_page) { double(inspect: 'FooPage') }
96
+ let(:bar_page) { double(inspect: 'BarPage') }
97
+ before do
98
+ allow_any_instance_of(described_class).to receive(:check_validations_are_defined!) { true }
99
+ allow(session).to receive(:current_url) { 'http://test.com' }
100
+ allow(session).to receive(:title) { 'Test site' }
101
+ allow(described_class).to receive(:matched_pages) { [foo_page, bar_page] }
102
+ end
103
+ it do
104
+ expect { subject }.to raise_error(
105
+ Howitzer::AmbiguousPageMatchingError,
106
+ "Current page matches more that one page class (FooPage, BarPage).\n" \
107
+ "\tCurrent url: http://test.com\n\tCurrent title: Test site"
108
+ )
109
+ end
110
+ end
111
+ context 'when matched_pages has only 1 page' do
112
+ let(:foo_page) { double(to_s: 'FooPage') }
113
+ before { allow(described_class).to receive(:matched_pages) { [foo_page] } }
114
+ it { is_expected.to eq(foo_page) }
115
+ end
116
+ end
117
+
118
+ describe '.displayed?' do
119
+ subject { described_class.displayed? }
120
+ context 'when page is opened' do
121
+ before { allow(described_class).to receive(:opened?) { true } }
122
+ it { is_expected.to eq(true) }
123
+ end
124
+ context 'when page is not opened' do
125
+ before do
126
+ allow(described_class).to receive(:current_page) { 'FooPage' }
127
+ allow(session).to receive(:current_url) { 'http://test.com' }
128
+ allow(session).to receive(:title) { 'Test site' }
129
+ allow(described_class).to receive(:opened?) { false }
130
+ end
131
+ it do
132
+ expect { subject }.to raise_error(
133
+ Howitzer::IncorrectPageError,
134
+ "Current page: FooPage, expected: #{described_class}.\n" \
135
+ "\tCurrent url: http://test.com\n\tCurrent title: Test site"
136
+ )
137
+ end
138
+ end
139
+ end
140
+
141
+ describe '.current_url' do
142
+ before { allow(Capybara).to receive_message_chain(:current_session, :current_url) { 'http://example.com' } }
143
+ it 'should return current url page' do
144
+ expect(Howitzer::Web::Page.current_url).to eq('http://example.com')
145
+ end
146
+ end
147
+
148
+ describe '.site' do
149
+ let!(:base_class) do
150
+ Class.new(described_class) do
151
+ site 'https://base.com'
152
+ end
153
+ end
154
+ let!(:child_class1) do
155
+ Class.new(base_class) do
156
+ site 'https://child.com'
157
+ end
158
+ end
159
+ let!(:child_class2) do
160
+ Class.new(base_class)
161
+ end
162
+ let!(:child_class3) do
163
+ Class.new(described_class)
164
+ end
165
+ it { expect(described_class.send(:app_host)).to eq('http://login:pass@my.website.com') }
166
+ it { expect(base_class.send(:app_host)).to eq('https://base.com') }
167
+ it { expect(child_class1.send(:app_host)).to eq('https://child.com') }
168
+ it { expect(child_class2.send(:app_host)).to eq('https://base.com') }
169
+ it { expect(child_class3.send(:app_host)).to eq('http://login:pass@my.website.com') }
170
+ it 'should be protected' do
171
+ expect { described_class.site('http://example.com') }.to raise_error(NoMethodError)
172
+ end
173
+ end
174
+
175
+ describe '.expanded_url' do
176
+ context 'when params present' do
177
+ subject { test_page.expanded_url(id: 1) }
178
+ context 'when page url specified' do
179
+ context 'when BlankPage' do
180
+ let(:test_page) { Howitzer::Web::BlankPage }
181
+ it { is_expected.to eq('about:blank') }
182
+ end
183
+ context 'when other page' do
184
+ let(:test_page) do
185
+ Class.new(described_class) do
186
+ site 'http://example.com'
187
+ path '/users{/id}'
188
+ end
189
+ end
190
+ it { is_expected.to eq('http://example.com/users/1') }
191
+ end
192
+ context 'when root not specified' do
193
+ let(:test_page) do
194
+ Class.new(described_class) do
195
+ path '/users{/id}'
196
+ end
197
+ end
198
+ it { is_expected.to eq('http://login:pass@my.website.com/users/1') }
199
+ end
200
+ end
201
+ context 'when page url missing' do
202
+ subject { described_class.expanded_url }
203
+ it do
204
+ expect { subject }.to raise_error(
205
+ ::Howitzer::NoPathForPageError,
206
+ "Please specify path for '#{described_class}' page. Example: path '/home'"
207
+ )
208
+ end
209
+ end
210
+ end
211
+ context 'when params missing' do
212
+ let(:test_page) do
213
+ Class.new(described_class) do
214
+ site 'http://example.com'
215
+ path '/users'
216
+ end
217
+ end
218
+ subject { test_page.expanded_url }
219
+ it { is_expected.to eq('http://example.com/users') }
220
+ end
221
+ end
222
+
223
+ describe '.path' do
224
+ subject { described_class.send(:path, value) }
225
+ before { subject }
226
+ context 'when value is number' do
227
+ let(:value) { 1 }
228
+ it { expect(described_class.instance_variable_get(:@path_template)).to eq('1') }
229
+ end
230
+ context 'when value is string' do
231
+ let(:value) { '/users' }
232
+ it { expect(described_class.instance_variable_get(:@path_template)).to eq('/users') }
233
+ end
234
+ end
235
+
236
+ describe '#initialize' do
237
+ subject { described_class.send(:new) }
238
+ before do
239
+ expect_any_instance_of(described_class).to receive(:check_validations_are_defined!).once { true }
240
+ end
241
+ context 'when maximized_window is true' do
242
+ let(:driver) { double }
243
+ before { allow(Howitzer).to receive(:maximized_window) { true } }
244
+ it do
245
+ expect_any_instance_of(described_class).to receive_message_chain('current_window.maximize')
246
+ subject
247
+ end
248
+ end
249
+ context 'when maximized_window is false' do
250
+ before { allow(Howitzer).to receive(:maximized_window) { false } }
251
+ it do
252
+ expect_any_instance_of(described_class).not_to receive('current_window.maximize')
253
+ subject
254
+ end
255
+ end
256
+ end
257
+
258
+ describe 'inherited callback' do
259
+ let(:page_class) { Class.new(described_class) }
260
+ context 'when abstract class without validations' do
261
+ let!(:page_class) do
262
+ Howitzer::Web::PageValidator.instance_variable_set(:@pages, [])
263
+ Class.new(described_class)
264
+ end
265
+ it { expect(Howitzer::Web::PageValidator.pages).to eq([]) }
266
+ end
267
+ context 'when class has validations' do
268
+ let!(:page_class) do
269
+ allow(described_class).to receive(:validations) { { title: /some text/ } }
270
+ Howitzer::Web::PageValidator.instance_variable_set(:@pages, [])
271
+ Class.new(described_class)
272
+ end
273
+ it { expect(Howitzer::Web::PageValidator.pages).to eq([page_class]) }
274
+ end
275
+ it 'can not be instantiated with new' do
276
+ expect { page_class.new }.to raise_error(NoMethodError, "private method `new' called for #{page_class}")
277
+ end
278
+ end
279
+
280
+ describe '#reload' do
281
+ let(:wait_for_url) { double }
282
+ subject { described_class.instance.reload }
283
+ let(:visit) { double }
284
+ before do
285
+ allow(session).to receive(:current_url) { 'google.com' }
286
+ end
287
+ it do
288
+ expect(Howitzer::Log).to receive(:info) { "Reload 'google.com'" }
289
+ expect(session).to receive(:visit).with('google.com')
290
+ subject
291
+ end
292
+ end
293
+
294
+ describe '#capybara_context' do
295
+ subject { described_class.instance.capybara_context }
296
+ before { expect(Capybara).to receive(:current_session) { :context } }
297
+ it { is_expected.to eq(:context) }
298
+ end
299
+
300
+ describe 'includes proxied capybara methods' do
301
+ let(:reciever) { described_class.instance }
302
+ include_examples :capybara_methods_proxy
303
+ end
304
+ end
@@ -0,0 +1,218 @@
1
+ require 'spec_helper'
2
+ require 'howitzer/web/page_validator'
3
+ require 'howitzer/web/element_dsl'
4
+
5
+ RSpec.describe Howitzer::Web::PageValidator do
6
+ describe '.validations' do
7
+ it { expect(subject.validations).to be_a(Hash) }
8
+ end
9
+
10
+ let(:web_page_class) do
11
+ Class.new do
12
+ include Howitzer::Web::ElementDsl
13
+ include Howitzer::Web::PageValidator
14
+ def self.name
15
+ 'TestWebPageClass'
16
+ end
17
+ end
18
+ end
19
+ let(:web_page) { web_page_class.new }
20
+ describe '#check_validations_are_defined!' do
21
+ subject { web_page.check_validations_are_defined! }
22
+ context 'when no validation specified' do
23
+ it do
24
+ expect { subject }.to raise_error(
25
+ Howitzer::NoValidationError,
26
+ "No any page validation was found for 'TestWebPageClass' page"
27
+ )
28
+ end
29
+ end
30
+ context 'when title validation is specified' do
31
+ before do
32
+ web_page.class.validate :title, /Foo/
33
+ end
34
+ it { expect { subject }.to_not raise_error }
35
+ end
36
+ context 'when url validation is specified' do
37
+ before do
38
+ web_page.class.validate :url, /Foo/
39
+ end
40
+ it { expect { subject }.to_not raise_error }
41
+ end
42
+ context 'when element_presence validation is specified' do
43
+ context 'when simple selector' do
44
+ before do
45
+ web_page.class.validate :element_presence, :test_locator
46
+ end
47
+ it { expect { subject }.to_not raise_error }
48
+ end
49
+
50
+ context 'when lambda selector' do
51
+ before do
52
+ web_page.class.validate :element_presence, :test_locator, 'some_text'
53
+ end
54
+ it { expect { subject }.to_not raise_error }
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '.validate' do
60
+ before do
61
+ described_class.validations[web_page.class.name] = nil
62
+ end
63
+ let(:additional_value) { nil }
64
+ subject { web_page.class.validate(name, *[value, additional_value].compact) }
65
+ context 'when name = :url' do
66
+ context 'as string' do
67
+ let(:name) { 'url' }
68
+ context '(as string)' do
69
+ let(:value) { /foo/ }
70
+ it do
71
+ is_expected.to be_a(Proc)
72
+ expect(described_class.validations[web_page.class.name][:url]).to be_a Proc
73
+ end
74
+ end
75
+ context '(as symbol)' do
76
+ let(:value) { /foo/ }
77
+ it do
78
+ is_expected.to be_a(Proc)
79
+ expect(described_class.validations[web_page.class.name][:url]).to be_a Proc
80
+ end
81
+ end
82
+ end
83
+ context 'as symbol' do
84
+ let(:name) { :url }
85
+ let(:value) { /foo/ }
86
+ it do
87
+ is_expected.to be_a(Proc)
88
+ expect(described_class.validations[web_page.class.name][:url]).to be_a Proc
89
+ end
90
+ end
91
+ end
92
+ context 'when name = :element_presence' do
93
+ let(:name) { :element_presence }
94
+ context '(as string)' do
95
+ let(:value) { 'test_locator' }
96
+ let(:additional_value) { 'some string' }
97
+ it do
98
+ is_expected.to be_a(Proc)
99
+ expect(described_class.validations[web_page.class.name][:element_presence]).to eql(subject)
100
+ end
101
+ end
102
+ context '(as symbol)' do
103
+ let(:value) { :test_locator }
104
+ it do
105
+ is_expected.to be_a(Proc)
106
+ expect(described_class.validations[web_page.class.name][:element_presence]).to eql(subject)
107
+ end
108
+ end
109
+ end
110
+ context 'when name = :title' do
111
+ let(:name) { :title }
112
+ context '(as string)' do
113
+ let(:value) { /foo/ }
114
+ it do
115
+ is_expected.to be_a(Proc)
116
+ expect(described_class.validations[web_page.class.name][:title]).to be_a Proc
117
+ end
118
+ end
119
+ context '(as symbol)' do
120
+ let(:value) { /foo/ }
121
+ it do
122
+ is_expected.to be_a(Proc)
123
+ expect(described_class.validations[web_page.class.name][:title]).to be_a Proc
124
+ end
125
+ end
126
+ end
127
+ context 'when other name' do
128
+ let(:name) { :unknown }
129
+ let(:value) { '' }
130
+ it do
131
+ expect { subject }.to raise_error(Howitzer::UnknownValidationError, "unknown 'unknown' validation type")
132
+ end
133
+ end
134
+ end
135
+
136
+ describe '.pages' do
137
+ subject { described_class.pages }
138
+ it do
139
+ expect(subject).not_to include(Symbol)
140
+ subject << Symbol
141
+ expect(subject).to include(Symbol)
142
+ end
143
+ end
144
+
145
+ describe '.opened?' do
146
+ subject { web_page_class.opened? }
147
+ context 'when no one validation is defined' do
148
+ it do
149
+ expect { subject }.to raise_error(
150
+ Howitzer::NoValidationError,
151
+ "No any page validation was found for 'TestWebPageClass' page"
152
+ )
153
+ end
154
+ end
155
+ context 'when all validations are defined' do
156
+ before do
157
+ web_page_class.class_eval do
158
+ include Singleton
159
+ element :login, '#id'
160
+ validate :url, /foo/
161
+ validate :title, /Foo page/
162
+ validate :element_presence, :login
163
+ end
164
+ end
165
+ context 'when all matches' do
166
+ before do
167
+ allow(web_page_class.instance).to receive(:current_url) { 'http://test.com/foo' }
168
+ allow(web_page_class.instance).to receive(:title) { 'Foo page' }
169
+ allow(web_page_class).to receive(:has_login_element?).with(no_args) { true }
170
+ end
171
+ it { is_expected.to be_truthy }
172
+ end
173
+ context 'when first validation fails' do
174
+ before do
175
+ expect(web_page_class.instance).to receive(:current_url).once { 'http://test.com/bar' }
176
+ expect(web_page_class.instance).to receive(:title).never
177
+ allow(web_page_class).to receive(:has_login_element?).with(no_args).never
178
+ end
179
+ it { is_expected.to be_falsey }
180
+ end
181
+ end
182
+ end
183
+
184
+ describe 'web_page.validations' do
185
+ it { expect(web_page_class.validations).to be_a(Hash) }
186
+ end
187
+
188
+ describe '#matched_pages' do
189
+ let!(:web_page1_class) do
190
+ Class.new do
191
+ include Howitzer::Web::PageValidator
192
+ def self.name
193
+ 'TestWebPage1Class'
194
+ end
195
+
196
+ def self.opened?
197
+ true
198
+ end
199
+ end
200
+ end
201
+
202
+ let!(:web_page2_class) do
203
+ Class.new do
204
+ include Howitzer::Web::PageValidator
205
+ def self.name
206
+ 'TestWebPage2Class'
207
+ end
208
+
209
+ def self.opened?
210
+ false
211
+ end
212
+ end
213
+ end
214
+ subject { web_page2_class.matched_pages }
215
+ before { described_class.instance_variable_set(:@pages, [web_page1_class, web_page2_class]) }
216
+ it { is_expected.to eq([web_page1_class]) }
217
+ end
218
+ end