howitzer 2.0.0 → 2.0.1

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +21 -1
  4. data/features/cli_new.feature +1 -0
  5. data/features/cli_update.feature +1 -0
  6. data/generators/base_generator.rb +3 -1
  7. data/generators/config/templates/capybara.rb +1 -1
  8. data/generators/config/templates/default.yml +4 -2
  9. data/generators/cucumber/cucumber_generator.rb +1 -0
  10. data/generators/cucumber/templates/common_steps.rb +1 -1
  11. data/generators/cucumber/templates/env.rb +0 -28
  12. data/generators/cucumber/templates/hooks.rb +29 -0
  13. data/generators/prerequisites/templates/user.rb +2 -0
  14. data/generators/prerequisites/templates/users.rb +2 -2
  15. data/generators/root/templates/Gemfile.erb +1 -1
  16. data/generators/rspec/templates/spec_helper.rb +9 -2
  17. data/generators/turnip/templates/spec_helper.rb +9 -2
  18. data/generators/web/templates/example_page.rb +0 -1
  19. data/howitzer.gemspec +1 -3
  20. data/lib/howitzer.rb +7 -0
  21. data/lib/howitzer/cache.rb +1 -1
  22. data/lib/howitzer/capybara_helpers.rb +2 -2
  23. data/lib/howitzer/email.rb +26 -8
  24. data/lib/howitzer/exceptions.rb +19 -19
  25. data/lib/howitzer/mail_adapters/abstract.rb +4 -3
  26. data/lib/howitzer/mail_adapters/mailgun.rb +6 -5
  27. data/lib/howitzer/mailgun_api/client.rb +1 -1
  28. data/lib/howitzer/version.rb +1 -1
  29. data/lib/howitzer/web/base_section.rb +3 -3
  30. data/lib/howitzer/web/capybara_context_holder.rb +19 -0
  31. data/lib/howitzer/web/capybara_methods_proxy.rb +27 -19
  32. data/lib/howitzer/web/element_dsl.rb +52 -13
  33. data/lib/howitzer/web/iframe_dsl.rb +3 -7
  34. data/lib/howitzer/web/page.rb +14 -21
  35. data/lib/howitzer/web/page_dsl.rb +32 -4
  36. data/lib/howitzer/web/page_validator.rb +15 -16
  37. data/lib/howitzer/web/section_dsl.rb +3 -7
  38. data/spec/config/custom.yml +1 -1
  39. data/spec/spec_helper.rb +1 -7
  40. data/spec/support/shared_examples/capybara_context_holder.rb +3 -3
  41. data/spec/support/shared_examples/element_dsl.rb +128 -18
  42. data/spec/unit/generators/base_generator_spec.rb +15 -16
  43. data/spec/unit/generators/cucumber_generator_spec.rb +2 -0
  44. data/spec/unit/generators/root_generator_spec.rb +1 -1
  45. data/spec/unit/lib/capybara_helpers_spec.rb +2 -2
  46. data/spec/unit/lib/email_spec.rb +37 -6
  47. data/spec/unit/lib/{howitzer.rb → howitzer_spec.rb} +9 -0
  48. data/spec/unit/lib/mail_adapters/abstract_spec.rb +1 -1
  49. data/spec/unit/lib/mail_adapters/mailgun_spec.rb +4 -4
  50. data/spec/unit/lib/web/base_section_spec.rb +3 -1
  51. data/spec/unit/lib/web/element_dsl_spec.rb +7 -2
  52. data/spec/unit/lib/web/page_dsl_spec.rb +22 -0
  53. data/spec/unit/lib/web/page_spec.rb +79 -44
  54. data/spec/unit/lib/web/page_validator_spec.rb +94 -51
  55. data/spec/unit/lib/web/section_spec.rb +4 -2
  56. metadata +10 -8
@@ -28,6 +28,7 @@ RSpec.describe 'Generators' do
28
28
  },
29
29
  { name: '/features/support', is_directory: true },
30
30
  { name: '/features/support/env.rb', is_directory: false, size: template_file_size('cucumber', 'env.rb') },
31
+ { name: '/features/support/hooks.rb', is_directory: false, size: template_file_size('cucumber', 'hooks.rb') },
31
32
  {
32
33
  name: '/features/support/transformers.rb',
33
34
  is_directory: false,
@@ -43,6 +44,7 @@ RSpec.describe 'Generators' do
43
44
  " * Cucumber integration to the framework ...
44
45
  Added 'features/step_definitions/common_steps.rb' file
45
46
  Added 'features/support/env.rb' file
47
+ Added 'features/support/hooks.rb' file
46
48
  Added 'features/support/transformers.rb' file
47
49
  Added 'features/example.feature' file
48
50
  Added 'tasks/cucumber.rake' file\n"
@@ -16,7 +16,7 @@ RSpec.describe 'Generators' do
16
16
  [
17
17
  { name: '/.gitignore', is_directory: false, size: 196 },
18
18
  { name: '/.rubocop.yml', is_directory: false, size: 584 },
19
- { name: '/Gemfile', is_directory: false, size: 605 },
19
+ { name: '/Gemfile', is_directory: false, size: 625 },
20
20
  { name: '/Rakefile', is_directory: false, size: template_file_size('root', 'Rakefile') }
21
21
  ]
22
22
  end
@@ -681,8 +681,8 @@ RSpec.describe Howitzer::CapybaraHelpers do
681
681
  describe '.load_driver_gem!' do
682
682
  subject { load_driver_gem!(:webkit, 'capybara-webkit', 'capybara-webkit') }
683
683
  context 'when possible to require' do
684
- before { allow(self).to receive(:require).with(:webkit) { true } }
685
- it { expect { subject }.not_to raise_error(LoadError) }
684
+ before { allow(self).to receive(:require).with('capybara-webkit') { true } }
685
+ it { expect { subject }.not_to raise_error }
686
686
  end
687
687
  context 'when impossible to require' do
688
688
  it do
@@ -37,22 +37,43 @@ RSpec.describe Howitzer::Email do
37
37
  describe '.subject' do
38
38
  it do
39
39
  described_class.send(:subject, message_subject)
40
- expect(described_class.instance_variable_get(:@subject)).to eql message_subject
40
+ expect(described_class.send(:subject_value)).to eql message_subject
41
+ expect(described_class.private_methods(true)).to include(:subject_value)
41
42
  end
42
43
  it 'should be protected' do
43
44
  expect { described_class.subject(message_subject) }.to raise_error(NoMethodError)
44
45
  end
45
46
  end
46
47
 
48
+ describe '.wait_time' do
49
+ subject { Class.new(described_class) }
50
+ it 'should be protected' do
51
+ expect { subject.wait_time(10) }.to raise_error(NoMethodError)
52
+ end
53
+
54
+ context 'when specified' do
55
+ before { subject.send(:wait_time, 10) }
56
+ it do
57
+ expect(subject.send(:wait_time_value)).to eql 10
58
+ expect(subject.private_methods(true)).to include(:wait_time_value)
59
+ end
60
+ end
61
+
62
+ context 'when missing' do
63
+ it do
64
+ expect(subject.send(:wait_time_value)).to eql 60
65
+ end
66
+ end
67
+ end
68
+
47
69
  describe '.find_by_recipient' do
48
70
  let(:recipient) { 'test@user.com' }
49
71
 
50
72
  context 'simple subject without parameters' do
51
- subject { described_class.find_by_recipient(recipient) }
52
73
  before { described_class.class_eval { subject 'Some title' } }
53
74
  it do
54
- expect(described_class.adapter).to receive(:find).with(recipient, 'Some title').once
55
- subject
75
+ expect(described_class.adapter).to receive(:find).with(recipient, 'Some title', wait: 60).once
76
+ described_class.find_by_recipient(recipient)
56
77
  end
57
78
  end
58
79
 
@@ -60,7 +81,7 @@ RSpec.describe Howitzer::Email do
60
81
  subject { described_class.find_by_recipient(recipient, name: 'Vasya') }
61
82
  before { described_class.class_eval { subject 'Some title from :name' } }
62
83
  it do
63
- expect(described_class.adapter).to receive(:find).with(recipient, 'Some title from Vasya').once
84
+ expect(described_class.adapter).to receive(:find).with(recipient, 'Some title from Vasya', wait: 60).once
64
85
  subject
65
86
  end
66
87
  end
@@ -69,12 +90,22 @@ RSpec.describe Howitzer::Email do
69
90
  subject { described_class.find_by_recipient(recipient, foo: 1, bar: 2) }
70
91
  before { described_class.class_eval { subject 'Some title with :foo and :bar' } }
71
92
  it do
72
- expect(described_class.adapter).to receive(:find).with(recipient, 'Some title with 1 and 2').once
93
+ expect(described_class.adapter).to receive(:find).with(recipient, 'Some title with 1 and 2', wait: 60).once
73
94
  subject
74
95
  end
75
96
  end
76
97
 
77
98
  context 'missing subject' do
99
+ subject { described_class.find_by_recipient(recipient) }
100
+ before do
101
+ described_class.instance_eval { undef :subject_value }
102
+ end
103
+ it do
104
+ expect { subject }.to raise_error(Howitzer::NoEmailSubjectError)
105
+ end
106
+ end
107
+
108
+ context 'nil subject' do
78
109
  subject { described_class.find_by_recipient(recipient) }
79
110
  before { described_class.class_eval { subject nil } }
80
111
  it do
@@ -28,4 +28,13 @@ RSpec.describe 'Howitzer' do
28
28
  it { expect(Howitzer.app_uri.site).to eq('http://redmine.strongqa.com') }
29
29
  end
30
30
  end
31
+ describe '.mailgun_idle_timeout' do
32
+ subject { Howitzer.mailgun_idle_timeout }
33
+ before do
34
+ expect_any_instance_of(Object).to receive(:puts).with(
35
+ "WARNING! 'mailgun_idle_timeout' setting is deprecated. Please replace with 'mail_wait_time' setting."
36
+ )
37
+ end
38
+ it { is_expected.to eq(0.5) }
39
+ end
31
40
  end
@@ -10,7 +10,7 @@ RSpec.describe Howitzer::MailAdapters::Abstract do
10
10
  let(:email_object) { Howitzer::Email.adapter.new(message) }
11
11
 
12
12
  describe '.find' do
13
- subject { described_class.find(recipient, message_subject) }
13
+ subject { described_class.find(recipient, message_subject, _wait: 10) }
14
14
  it { expect { subject }.to raise_error(NotImplementedError) }
15
15
  end
16
16
 
@@ -29,7 +29,7 @@ RSpec.describe 'Mailgun Email Adapter' do
29
29
  describe '.find' do
30
30
  let(:mailgun_message) { double(to_h: message) }
31
31
  let(:events) { double(to_h: { 'items' => [event] }) }
32
- subject { Howitzer::MailAdapters::Mailgun.find(recipient, message_subject) }
32
+ subject { Howitzer::MailAdapters::Mailgun.find(recipient, message_subject, wait: 0.01) }
33
33
 
34
34
  context 'when message is found' do
35
35
  let(:event) do
@@ -50,10 +50,10 @@ RSpec.describe 'Mailgun Email Adapter' do
50
50
  allow(Howitzer::MailgunApi::Connector.instance.client).to receive(:get).with(
51
51
  'mailgun@test.domain/events',
52
52
  params: { event: 'stored' }
53
- ).ordered.once { events }
53
+ ) { events }
54
54
  allow(Howitzer::MailgunApi::Connector.instance.client).to receive(:get_url).with(
55
55
  'https://si.api.mailgun.net/v3/domains/mg.strongqa.com/messages/1234567890'
56
- ).ordered.once { mailgun_message }
56
+ ) { mailgun_message }
57
57
  end
58
58
  it do
59
59
  expect(Howitzer::Email.adapter).to receive(:new).with(message).once
@@ -80,7 +80,7 @@ RSpec.describe 'Mailgun Email Adapter' do
80
80
  allow(Howitzer::MailgunApi::Connector.instance.client).to receive(:get).with(
81
81
  'mailgun@test.domain/events',
82
82
  params: { event: 'stored' }
83
- ).at_least(:twice).ordered { events }
83
+ ) { events }
84
84
  end
85
85
  it do
86
86
  expect { subject }.to raise_error(
@@ -9,7 +9,9 @@ RSpec.describe Howitzer::Web::BaseSection do
9
9
 
10
10
  let(:klass) { Class.new(described_class) }
11
11
  let(:klass_object) { klass.new(parent, capybara_context) }
12
- before { allow(klass_object).to receive(:capybara_context) { kontext } }
12
+ it 'returns correct capybara context' do
13
+ expect(klass_object.capybara_context).to eq(capybara_context)
14
+ end
13
15
 
14
16
  include_examples :element_dsl
15
17
  end
@@ -5,13 +5,18 @@ RSpec.describe Howitzer::Web::ElementDsl do
5
5
  let(:klass) do
6
6
  Class.new do
7
7
  include Howitzer::Web::ElementDsl
8
- def capybara_context
9
- Capybara.current_session
8
+ def capybara_scopes
9
+ @_scopes ||= [Capybara.current_session]
10
10
  end
11
11
  end
12
12
  end
13
13
  let(:klass_object) { klass.new }
14
14
 
15
+ it 'returns correct capybara context' do
16
+ allow(Capybara).to receive(:current_session) { 'session' }
17
+ expect(klass_object.capybara_context).to eq('session')
18
+ end
19
+
15
20
  include_examples :element_dsl
16
21
  include_examples :capybara_context_holder
17
22
  end
@@ -42,6 +42,28 @@ RSpec.describe Howitzer::Web::PageDsl::PageScope do
42
42
  it { expect(subject.class).to eq(RSpec::Matchers::BuiltIn::Has) }
43
43
  end
44
44
 
45
+ context 'when out' do
46
+ let(:outer_context) do
47
+ Class.new do
48
+ def initialize(klass)
49
+ @klass = klass
50
+ @a = 5
51
+ end
52
+
53
+ def scope
54
+ @klass.new(nil) { 1 }
55
+ end
56
+
57
+ def secret
58
+ '***'
59
+ end
60
+ end
61
+ end
62
+ let(:scope) { outer_context.new(described_class).scope }
63
+ it { expect(scope.out(:@a)).to eq(5) }
64
+ it { expect(scope.out(:secret)).to eq('***') }
65
+ end
66
+
45
67
  context 'when starts other prefix' do
46
68
  let(:scope) { described_class.new(page) { 1 } }
47
69
  subject { scope.foo(1, 2, 3) }
@@ -14,7 +14,21 @@ RSpec.describe Howitzer::Web::Page do
14
14
  let(:url_value) { 'http://example.com/users/1' }
15
15
  subject { described_class.open(id: 1) }
16
16
  it do
17
- expect(described_class).to receive(:expanded_url).with(id: 1) { url_value }.once.ordered
17
+ expect(described_class).to receive(:expanded_url).with({ id: 1 }, nil) { 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 custom processor specified' do
27
+ let(:custom_processor) { double }
28
+ let(:url_value) { 'http://example.com/users/1' }
29
+ subject { described_class.open(id: 1, url_processor: custom_processor) }
30
+ it do
31
+ expect(described_class).to receive(:expanded_url).with({ id: 1 }, custom_processor) { url_value }.once.ordered
18
32
  expect(Howitzer::Log).to receive(:info)
19
33
  .with("Open #{described_class} page by '#{url_value}' url").once.ordered
20
34
  expect(described_class).to receive(:retryable).ordered.once.and_call_original
@@ -27,7 +41,7 @@ RSpec.describe Howitzer::Web::Page do
27
41
  let(:url_value) { 'http://example.com/users' }
28
42
  subject { described_class.open }
29
43
  it do
30
- expect(described_class).to receive(:expanded_url).with({}) { url_value }.once.ordered
44
+ expect(described_class).to receive(:expanded_url).with({}, nil) { url_value }.once.ordered
31
45
  expect(Howitzer::Log).to receive(:info)
32
46
  .with("Open #{described_class} page by '#{url_value}' url").once.ordered
33
47
  expect(described_class).to receive(:retryable).ordered.once.and_call_original
@@ -41,7 +55,7 @@ RSpec.describe Howitzer::Web::Page do
41
55
  let(:url_value) { 'http://example.com/users' }
42
56
  subject { described_class.open(validate: false) }
43
57
  it do
44
- expect(described_class).to receive(:expanded_url).with({}) { url_value }.once.ordered
58
+ expect(described_class).to receive(:expanded_url).with({}, nil) { url_value }.once.ordered
45
59
  expect(Howitzer::Log).to receive(:info).with("Open #{described_class} page by '#{url_value}' url").once.ordered
46
60
  expect(described_class).to receive(:retryable).ordered.once.and_call_original
47
61
  expect(session).to receive(:visit).with(url_value).once.ordered
@@ -53,7 +67,7 @@ RSpec.describe Howitzer::Web::Page do
53
67
  let(:url_value) { 'http://example.com/users/1' }
54
68
  subject { described_class.open(validate: true, id: 1) }
55
69
  it do
56
- expect(described_class).to receive(:expanded_url).with(id: 1) { url_value }.once.ordered
70
+ expect(described_class).to receive(:expanded_url).with({ id: 1 }, nil) { url_value }.once.ordered
57
71
  expect(Howitzer::Log).to receive(:info).with("Open #{described_class} page by '#{url_value}' url").once.ordered
58
72
  expect(described_class).to receive(:retryable).ordered.once.and_call_original
59
73
  expect(session).to receive(:visit).with(url_value).once.ordered
@@ -162,41 +176,72 @@ RSpec.describe Howitzer::Web::Page do
162
176
  let!(:child_class3) do
163
177
  Class.new(described_class)
164
178
  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') }
179
+ it { expect(described_class.send(:site_value)).to eq('http://login:pass@my.website.com') }
180
+ it { expect(base_class.send(:site_value)).to eq('https://base.com') }
181
+ it { expect(child_class1.send(:site_value)).to eq('https://child.com') }
182
+ it { expect(child_class2.send(:site_value)).to eq('https://base.com') }
183
+ it { expect(child_class3.send(:site_value)).to eq('http://login:pass@my.website.com') }
170
184
  it 'should be protected' do
171
185
  expect { described_class.site('http://example.com') }.to raise_error(NoMethodError)
172
186
  end
173
187
  end
174
188
 
175
189
  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}'
190
+ context 'when default url processor' do
191
+ context 'when params present' do
192
+ subject { test_page.expanded_url(id: 1) }
193
+ context 'when page url specified' do
194
+ context 'when BlankPage' do
195
+ let(:test_page) { Howitzer::Web::BlankPage }
196
+ it { is_expected.to eq('about:blank') }
197
+ end
198
+ context 'when other page' do
199
+ let(:test_page) do
200
+ Class.new(described_class) do
201
+ site 'http://example.com'
202
+ path '/users{/id}'
203
+ end
204
+ end
205
+ it { is_expected.to eq('http://example.com/users/1') }
206
+ end
207
+ context 'when root not specified' do
208
+ let(:test_page) do
209
+ Class.new(described_class) do
210
+ path '/users{/id}'
211
+ end
188
212
  end
213
+ it { is_expected.to eq('http://login:pass@my.website.com/users/1') }
214
+ end
215
+ end
216
+ end
217
+ context 'when custom url processor' do
218
+ let(:test_page) do
219
+ Class.new(described_class) do
220
+ site 'http://example.com'
221
+ path '/users{/id}'
189
222
  end
190
- it { is_expected.to eq('http://example.com/users/1') }
191
223
  end
192
- context 'when root not specified' do
193
- let(:test_page) do
194
- Class.new(described_class) do
195
- path '/users{/id}'
224
+ let(:custom_processor_class) do
225
+ Class.new do
226
+ def self.restore(_name, value)
227
+ value.tr('-', ' ')
228
+ end
229
+
230
+ def self.match(_name)
231
+ '.*'
232
+ end
233
+
234
+ def self.validate(_name, value)
235
+ !(value =~ /^[\w ]+$/).nil?
236
+ end
237
+
238
+ def self.transform(_name, value)
239
+ value.tr(' ', '+')
196
240
  end
197
241
  end
198
- it { is_expected.to eq('http://login:pass@my.website.com/users/1') }
199
242
  end
243
+ subject { test_page.expanded_url({ id: 'hello world' }, custom_processor_class) }
244
+ it { is_expected.to eq('http://example.com/users/hello+world') }
200
245
  end
201
246
  context 'when page url missing' do
202
247
  subject { described_class.expanded_url }
@@ -225,11 +270,16 @@ RSpec.describe Howitzer::Web::Page do
225
270
  before { subject }
226
271
  context 'when value is number' do
227
272
  let(:value) { 1 }
228
- it { expect(described_class.instance_variable_get(:@path_template)).to eq('1') }
273
+ it do
274
+ expect(described_class.send(:path_value)).to eql '1'
275
+ expect(described_class.private_methods(true)).to include(:path_value)
276
+ end
229
277
  end
230
278
  context 'when value is string' do
231
279
  let(:value) { '/users' }
232
- it { expect(described_class.instance_variable_get(:@path_template)).to eq('/users') }
280
+ it do
281
+ expect(described_class.send(:path_value)).to eql '/users'
282
+ end
233
283
  end
234
284
  end
235
285
 
@@ -257,21 +307,6 @@ RSpec.describe Howitzer::Web::Page do
257
307
 
258
308
  describe 'inherited callback' do
259
309
  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
310
  it 'can not be instantiated with new' do
276
311
  expect { page_class.new }.to raise_error(NoMethodError, "private method `new' called for #{page_class}")
277
312
  end
@@ -58,7 +58,7 @@ RSpec.describe Howitzer::Web::PageValidator do
58
58
 
59
59
  describe '.validate' do
60
60
  before do
61
- described_class.validations[web_page.class.name] = nil
61
+ described_class.validations[web_page.class] = nil
62
62
  end
63
63
  let(:additional_value) { nil }
64
64
  subject { web_page.class.validate(name, *[value, additional_value].compact) }
@@ -69,14 +69,14 @@ RSpec.describe Howitzer::Web::PageValidator do
69
69
  let(:value) { /foo/ }
70
70
  it do
71
71
  is_expected.to be_a(Proc)
72
- expect(described_class.validations[web_page.class.name][:url]).to be_a Proc
72
+ expect(described_class.validations[web_page.class][:url]).to be_a Proc
73
73
  end
74
74
  end
75
75
  context '(as symbol)' do
76
76
  let(:value) { /foo/ }
77
77
  it do
78
78
  is_expected.to be_a(Proc)
79
- expect(described_class.validations[web_page.class.name][:url]).to be_a Proc
79
+ expect(described_class.validations[web_page.class][:url]).to be_a Proc
80
80
  end
81
81
  end
82
82
  end
@@ -85,7 +85,7 @@ RSpec.describe Howitzer::Web::PageValidator do
85
85
  let(:value) { /foo/ }
86
86
  it do
87
87
  is_expected.to be_a(Proc)
88
- expect(described_class.validations[web_page.class.name][:url]).to be_a Proc
88
+ expect(described_class.validations[web_page.class][:url]).to be_a Proc
89
89
  end
90
90
  end
91
91
  end
@@ -96,14 +96,14 @@ RSpec.describe Howitzer::Web::PageValidator do
96
96
  let(:additional_value) { 'some string' }
97
97
  it do
98
98
  is_expected.to be_a(Proc)
99
- expect(described_class.validations[web_page.class.name][:element_presence]).to eql(subject)
99
+ expect(described_class.validations[web_page.class][:element_presence]).to eql(subject)
100
100
  end
101
101
  end
102
102
  context '(as symbol)' do
103
103
  let(:value) { :test_locator }
104
104
  it do
105
105
  is_expected.to be_a(Proc)
106
- expect(described_class.validations[web_page.class.name][:element_presence]).to eql(subject)
106
+ expect(described_class.validations[web_page.class][:element_presence]).to eql(subject)
107
107
  end
108
108
  end
109
109
  end
@@ -113,14 +113,14 @@ RSpec.describe Howitzer::Web::PageValidator do
113
113
  let(:value) { /foo/ }
114
114
  it do
115
115
  is_expected.to be_a(Proc)
116
- expect(described_class.validations[web_page.class.name][:title]).to be_a Proc
116
+ expect(described_class.validations[web_page.class][:title]).to be_a Proc
117
117
  end
118
118
  end
119
119
  context '(as symbol)' do
120
120
  let(:value) { /foo/ }
121
121
  it do
122
122
  is_expected.to be_a(Proc)
123
- expect(described_class.validations[web_page.class.name][:title]).to be_a Proc
123
+ expect(described_class.validations[web_page.class][:title]).to be_a Proc
124
124
  end
125
125
  end
126
126
  end
@@ -133,18 +133,9 @@ RSpec.describe Howitzer::Web::PageValidator do
133
133
  end
134
134
  end
135
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
136
  describe '.opened?' do
146
- subject { web_page_class.opened? }
147
137
  context 'when no one validation is defined' do
138
+ subject { web_page_class.opened? }
148
139
  it do
149
140
  expect { subject }.to raise_error(
150
141
  Howitzer::NoValidationError,
@@ -153,30 +144,91 @@ RSpec.describe Howitzer::Web::PageValidator do
153
144
  end
154
145
  end
155
146
  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
147
+ context 'when sync is default' do
148
+ subject { web_page_class.opened? }
149
+ before do
150
+ web_page_class.class_eval do
151
+ include Singleton
152
+ element :login, '#id'
153
+ validate :url, /foo/
154
+ validate :title, /Foo page/
155
+ validate :element_presence, :login
156
+ end
157
+ end
158
+ context 'when all matches' do
159
+ before do
160
+ allow(web_page_class.instance).to receive(:current_url) { 'http://test.com/foo' }
161
+ allow(web_page_class.instance).to receive(:has_title?) { 'Foo page' }
162
+ allow(web_page_class.instance).to receive(:has_login_element?).with(no_args) { true }
163
+ end
164
+ it { is_expected.to be_truthy }
165
+ end
166
+ context 'when first validation fails' do
167
+ before do
168
+ expect(web_page_class.instance).to receive(:current_url).once { 'http://test.com/bar' }
169
+ expect(web_page_class.instance).to receive(:has_title?).never
170
+ allow(web_page_class).to receive(:has_login_element?).with(no_args).never
171
+ end
172
+ it { is_expected.to be_falsey }
163
173
  end
164
174
  end
165
- context 'when all matches' do
175
+
176
+ context 'when sync is true' do
177
+ subject { web_page_class.opened?(sync: true) }
166
178
  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 }
179
+ web_page_class.class_eval do
180
+ include Singleton
181
+ element :login, '#id'
182
+ validate :url, /foo/
183
+ validate :title, /Foo page/
184
+ validate :element_presence, :login
185
+ end
186
+ end
187
+ context 'when all matches' do
188
+ before do
189
+ allow(web_page_class.instance).to receive(:current_url) { 'http://test.com/foo' }
190
+ allow(web_page_class.instance).to receive(:has_title?) { 'Foo page' }
191
+ allow(web_page_class.instance).to receive(:has_login_element?).with(no_args) { true }
192
+ end
193
+ it { is_expected.to be_truthy }
194
+ end
195
+ context 'when first validation fails' do
196
+ before do
197
+ expect(web_page_class.instance).to receive(:current_url).once { 'http://test.com/bar' }
198
+ expect(web_page_class.instance).to receive(:has_title?).never
199
+ allow(web_page_class).to receive(:has_login_element?).with(no_args).never
200
+ end
201
+ it { is_expected.to be_falsey }
170
202
  end
171
- it { is_expected.to be_truthy }
172
203
  end
173
- context 'when first validation fails' do
204
+
205
+ context 'when sync is false' do
206
+ subject { web_page_class.opened?(sync: false) }
174
207
  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
208
+ web_page_class.class_eval do
209
+ include Singleton
210
+ element :login, '#id'
211
+ validate :url, /foo/
212
+ validate :title, /Foo page/
213
+ validate :element_presence, :login
214
+ end
215
+ end
216
+ context 'when all matches' do
217
+ before do
218
+ allow(web_page_class.instance).to receive(:current_url) { 'http://test.com/foo' }
219
+ allow(web_page_class.instance).to receive(:title) { 'Foo page' }
220
+ allow(web_page_class.instance).to receive(:has_no_login_element?).with(no_args) { false }
221
+ end
222
+ it { is_expected.to be_truthy }
223
+ end
224
+ context 'when first validation fails' do
225
+ before do
226
+ expect(web_page_class.instance).to receive(:current_url).once { 'http://test.com/bar' }
227
+ expect(web_page_class.instance).to receive(:title).never
228
+ allow(web_page_class).to receive(:has_no_login_element?).with(no_args).never
229
+ end
230
+ it { is_expected.to be_falsey }
178
231
  end
179
- it { is_expected.to be_falsey }
180
232
  end
181
233
  end
182
234
  end
@@ -189,30 +241,21 @@ RSpec.describe Howitzer::Web::PageValidator do
189
241
  let!(:web_page1_class) do
190
242
  Class.new do
191
243
  include Howitzer::Web::PageValidator
192
- def self.name
193
- 'TestWebPage1Class'
194
- end
195
-
196
- def self.opened?
197
- true
198
- end
199
244
  end
200
245
  end
201
-
202
246
  let!(:web_page2_class) do
203
247
  Class.new do
204
248
  include Howitzer::Web::PageValidator
205
- def self.name
206
- 'TestWebPage2Class'
207
- end
208
-
209
- def self.opened?
210
- false
211
- end
212
249
  end
213
250
  end
214
251
  subject { web_page2_class.matched_pages }
215
- before { described_class.instance_variable_set(:@pages, [web_page1_class, web_page2_class]) }
252
+ before do
253
+ allow(Howitzer::Web::PageValidator).to receive(:validations).with(no_args) do
254
+ { web_page1_class => 1, web_page2_class => 2 }
255
+ end
256
+ expect(web_page1_class).to receive(:opened?).with(sync: false) { true }
257
+ expect(web_page2_class).to receive(:opened?).with(sync: false) { false }
258
+ end
216
259
  it { is_expected.to eq([web_page1_class]) }
217
260
  end
218
261
  end