howitzer 2.1.1 → 2.4.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 (129) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +44 -1
  3. data/LICENSE +1 -1
  4. data/README.md +19 -17
  5. data/generators/base_generator.rb +5 -7
  6. data/generators/config/config_generator.rb +3 -4
  7. data/generators/config/templates/boot.rb +2 -2
  8. data/generators/config/templates/capybara.rb +4 -5
  9. data/generators/config/templates/default.yml +21 -11
  10. data/generators/config/templates/drivers/browserstack.rb +31 -4
  11. data/generators/config/templates/drivers/crossbrowsertesting.rb +9 -11
  12. data/generators/config/templates/drivers/headless_chrome.rb +1 -1
  13. data/generators/config/templates/drivers/headless_firefox.rb +23 -0
  14. data/generators/config/templates/drivers/lambdatest.rb +30 -0
  15. data/generators/config/templates/drivers/sauce.rb +30 -2
  16. data/generators/config/templates/drivers/selenium.rb +1 -1
  17. data/generators/config/templates/drivers/selenium_grid.rb +3 -3
  18. data/generators/config/templates/drivers/testingbot.rb +29 -2
  19. data/generators/cucumber/templates/cuke_sniffer.rake +2 -2
  20. data/generators/cucumber/templates/env.rb +8 -0
  21. data/generators/cucumber/templates/hooks.rb +9 -3
  22. data/generators/cucumber/templates/transformers.rb +1 -1
  23. data/generators/prerequisites/templates/factory_bot.rb +2 -1
  24. data/generators/root/root_generator.rb +1 -1
  25. data/generators/root/templates/Gemfile.erb +4 -10
  26. data/generators/rspec/templates/spec_helper.rb +6 -5
  27. data/generators/turnip/templates/spec_helper.rb +6 -5
  28. data/generators/web/templates/example_page.rb +1 -1
  29. data/lib/howitzer/cache.rb +20 -19
  30. data/lib/howitzer/capybara_helpers.rb +59 -14
  31. data/lib/howitzer/email.rb +3 -2
  32. data/lib/howitzer/exceptions.rb +21 -21
  33. data/lib/howitzer/gmail_api/client.rb +13 -4
  34. data/lib/howitzer/log.rb +6 -6
  35. data/lib/howitzer/mail_adapters/gmail.rb +3 -0
  36. data/lib/howitzer/mail_adapters/mailgun.rb +3 -1
  37. data/lib/howitzer/mail_adapters/mailtrap.rb +3 -0
  38. data/lib/howitzer/mailgun_api/client.rb +3 -2
  39. data/lib/howitzer/mailgun_api/connector.rb +1 -0
  40. data/lib/howitzer/mailgun_api/response.rb +1 -2
  41. data/lib/howitzer/mailtrap_api/client.rb +1 -1
  42. data/lib/howitzer/meta/actions.rb +35 -0
  43. data/lib/howitzer/meta/element.rb +40 -0
  44. data/lib/howitzer/meta/entry.rb +62 -0
  45. data/lib/howitzer/meta/iframe.rb +41 -0
  46. data/lib/howitzer/meta/section.rb +30 -0
  47. data/lib/howitzer/meta.rb +11 -0
  48. data/lib/howitzer/utils/string_extensions.rb +6 -2
  49. data/lib/howitzer/version.rb +1 -1
  50. data/lib/howitzer/web/base_section.rb +1 -1
  51. data/lib/howitzer/web/capybara_context_holder.rb +1 -0
  52. data/lib/howitzer/web/capybara_methods_proxy.rb +15 -6
  53. data/lib/howitzer/web/element_dsl.rb +104 -44
  54. data/lib/howitzer/web/iframe_dsl.rb +4 -2
  55. data/lib/howitzer/web/page.rb +14 -14
  56. data/lib/howitzer/web/page_dsl.rb +18 -6
  57. data/lib/howitzer/web/page_validator.rb +27 -26
  58. data/lib/howitzer/web/section.rb +13 -2
  59. data/lib/howitzer/web/section_dsl.rb +65 -30
  60. data/lib/howitzer.rb +40 -0
  61. metadata +31 -157
  62. data/.coveralls.yml +0 -1
  63. data/.gitignore +0 -14
  64. data/.rspec +0 -3
  65. data/.rubocop.yml +0 -51
  66. data/.ruby-gemset +0 -1
  67. data/.travis.yml +0 -7
  68. data/Gemfile +0 -14
  69. data/ISSUE_TEMPLATE.md +0 -16
  70. data/MAINTENANCE.md +0 -32
  71. data/Rakefile +0 -38
  72. data/features/cli_help.feature +0 -31
  73. data/features/cli_new.feature +0 -389
  74. data/features/cli_unknown.feature +0 -17
  75. data/features/cli_update.feature +0 -218
  76. data/features/cli_version.feature +0 -14
  77. data/features/step_definitions/common_steps.rb +0 -34
  78. data/features/support/env.rb +0 -1
  79. data/generators/config/templates/drivers/phantomjs.rb +0 -19
  80. data/generators/config/templates/drivers/poltergeist.rb +0 -11
  81. data/generators/config/templates/drivers/webkit.rb +0 -6
  82. data/generators/root/templates/.gitignore +0 -21
  83. data/generators/root/templates/.rubocop.yml +0 -35
  84. data/generators/turnip/templates/.rspec +0 -1
  85. data/howitzer.gemspec +0 -39
  86. data/lib/howitzer/mail_adapters/debugmail.rb +0 -0
  87. data/spec/config/custom.yml +0 -9
  88. data/spec/spec_helper.rb +0 -73
  89. data/spec/support/generator_helper.rb +0 -21
  90. data/spec/support/logger_helper.rb +0 -13
  91. data/spec/support/shared_examples/capybara_context_holder.rb +0 -33
  92. data/spec/support/shared_examples/capybara_methods_proxy.rb +0 -94
  93. data/spec/support/shared_examples/dynamic_section_methods.rb +0 -35
  94. data/spec/support/shared_examples/element_dsl.rb +0 -242
  95. data/spec/unit/generators/base_generator_spec.rb +0 -283
  96. data/spec/unit/generators/config_generator_spec.rb +0 -59
  97. data/spec/unit/generators/cucumber_generator_spec.rb +0 -62
  98. data/spec/unit/generators/emails_generator_spec.rb +0 -35
  99. data/spec/unit/generators/prerequisites_generator_spec.rb +0 -53
  100. data/spec/unit/generators/root_generator_spec.rb +0 -75
  101. data/spec/unit/generators/rspec_generator_spec.rb +0 -36
  102. data/spec/unit/generators/tasks_generator_spec.rb +0 -31
  103. data/spec/unit/generators/turnip_generator_spec.rb +0 -52
  104. data/spec/unit/generators/web_generator_spec.rb +0 -52
  105. data/spec/unit/lib/cache_spec.rb +0 -85
  106. data/spec/unit/lib/capybara_helpers_spec.rb +0 -697
  107. data/spec/unit/lib/email_spec.rb +0 -186
  108. data/spec/unit/lib/gmail_api/client_spec.rb +0 -26
  109. data/spec/unit/lib/howitzer_spec.rb +0 -69
  110. data/spec/unit/lib/init_spec.rb +0 -2
  111. data/spec/unit/lib/log_spec.rb +0 -122
  112. data/spec/unit/lib/mail_adapters/abstract_spec.rb +0 -62
  113. data/spec/unit/lib/mail_adapters/gmail_spec.rb +0 -128
  114. data/spec/unit/lib/mail_adapters/mailgun_spec.rb +0 -158
  115. data/spec/unit/lib/mail_adapters/mailtrap_spec.rb +0 -130
  116. data/spec/unit/lib/mailgun_api/client_spec.rb +0 -80
  117. data/spec/unit/lib/mailgun_api/connector_spec.rb +0 -54
  118. data/spec/unit/lib/mailgun_api/response_spec.rb +0 -28
  119. data/spec/unit/lib/mailtrap_api/client_spec.rb +0 -67
  120. data/spec/unit/lib/utils/string_extensions_spec.rb +0 -77
  121. data/spec/unit/lib/web/base_section_spec.rb +0 -43
  122. data/spec/unit/lib/web/element_dsl_spec.rb +0 -22
  123. data/spec/unit/lib/web/iframe_dsl_spec.rb +0 -203
  124. data/spec/unit/lib/web/page_dsl_spec.rb +0 -74
  125. data/spec/unit/lib/web/page_spec.rb +0 -378
  126. data/spec/unit/lib/web/page_validator_spec.rb +0 -276
  127. data/spec/unit/lib/web/section_dsl_spec.rb +0 -165
  128. data/spec/unit/lib/web/section_spec.rb +0 -63
  129. data/spec/unit/version_spec.rb +0 -8
@@ -1,203 +0,0 @@
1
- require 'spec_helper'
2
- require 'howitzer/web/page'
3
-
4
- RSpec.describe Howitzer::Web::IframeDsl do
5
- let(:fb_page_class) do
6
- Class.new(Howitzer::Web::Page) do
7
- section :navbar, :xpath, './body' do
8
- element :like_button, '#foo_id'
9
- end
10
- end
11
- end
12
- let(:nested_class) do
13
- module Foo
14
- Class.new(Howitzer::Web::Page) do
15
- section :navbar, :xpath, './body' do
16
- element :like_button, '#foo_id'
17
- end
18
- end
19
- end
20
- end
21
- let(:double_nested_class) do
22
- module Foo
23
- module Bar
24
- Class.new(Howitzer::Web::Page) do
25
- section :navbar, :xpath, './body' do
26
- element :like_button, '#foo_id'
27
- end
28
- end
29
- end
30
- end
31
- end
32
-
33
- let(:web_page_class) do
34
- Class.new(Howitzer::Web::Page)
35
- end
36
-
37
- before do
38
- allow_any_instance_of(fb_page_class).to receive(:check_validations_are_defined!)
39
- allow_any_instance_of(web_page_class).to receive(:check_validations_are_defined!)
40
- stub_const('FbPage', fb_page_class)
41
- stub_const('Foo::FbPage', nested_class)
42
- stub_const('Foo::Bar::FbHomePage', double_nested_class)
43
- allow(Howitzer::Web::Page).to receive(:descendants) { [FbPage, Foo::FbPage, Foo::Bar::FbHomePage] }
44
- end
45
-
46
- describe '.iframe' do
47
- context 'when selector is integer' do
48
- subject do
49
- web_page_class.class_eval do
50
- iframe :fb, 1
51
- end
52
- web_page_class
53
- end
54
-
55
- it 'should create public :fb_iframe instance method' do
56
- expect(subject.instance.public_methods(false)).to include(:fb_iframe)
57
- end
58
- it 'should create public :has_fb_iframe? instance method' do
59
- expect(subject.instance.public_methods(false)).to include(:has_fb_iframe?)
60
- end
61
- it 'should create public :has_no_fb_iframe? instance method' do
62
- expect(subject.instance.public_methods(false)).to include(:has_no_fb_iframe?)
63
- end
64
- it 'should be protected class method' do
65
- expect { subject.iframe :bar }.to raise_error(NoMethodError)
66
- expect(subject.protected_methods(true)).to include(:iframe)
67
- end
68
- end
69
-
70
- context 'when selector is not specified' do
71
- subject do
72
- web_page_class.class_eval do
73
- iframe :fb
74
- end
75
- web_page_class
76
- end
77
-
78
- it 'should raise error' do
79
- expect { subject }.to raise_error(ArgumentError, 'iframe selector arguments must be specified')
80
- end
81
- end
82
-
83
- context 'when class defined explicity' do
84
- subject do
85
- web_page_class.class_eval do
86
- iframe :fb, FbPage, 1
87
- end
88
- web_page_class
89
- end
90
- it 'should find page class specified' do
91
- expect(subject).to eql(web_page_class)
92
- end
93
- end
94
-
95
- context 'when frame nested in module' do
96
- subject do
97
- web_page_class.class_eval do
98
- iframe :foo_fb, 1
99
- end
100
- web_page_class
101
- end
102
- it 'should find page class nested in module' do
103
- expect(subject).to eql(web_page_class)
104
- end
105
- end
106
-
107
- context 'when frame nested in module nested in module' do
108
- subject do
109
- web_page_class.class_eval do
110
- iframe :foo_bar_fb_home, 1
111
- end
112
- web_page_class
113
- end
114
- it 'should find class nested in modules' do
115
- expect(subject).to eql(web_page_class)
116
- end
117
- end
118
- end
119
-
120
- include_examples :capybara_context_holder
121
-
122
- describe 'dynamic_methods' do
123
- let(:web_page_object) { web_page_class.instance }
124
- let(:kontext) { double(:kontext) }
125
- before do
126
- allow(Capybara).to receive(:current_session) { kontext }
127
- end
128
- after { subject }
129
-
130
- describe '#name_iframe' do
131
- let(:block) { proc {} }
132
- context 'when no options' do
133
- subject { web_page_object.fb_iframe(&block) }
134
- before { web_page_class.class_eval { iframe :fb, 'foo' } }
135
- it do
136
- expect(kontext).to receive(:within_frame)
137
- .with('foo') { |&block| block.call }
138
- expect(block).to receive(:call).with(fb_page_class.instance)
139
- expect(fb_page_class).to receive(:displayed?).with(no_args)
140
- end
141
- end
142
- context 'when all possible options' do
143
- subject { web_page_object.fb_iframe(wait: 10, text: 'new', &block) }
144
- before { web_page_class.class_eval { iframe :fb, :xpath, './/foo', match: :first, text: 'origin' } }
145
- it do
146
- expect(kontext).to receive(:within_frame)
147
- .with(:xpath, './/foo', match: :first, wait: 10, text: 'new') { |&block| block.call }
148
- expect(block).to receive(:call).with(fb_page_class.instance)
149
- expect(fb_page_class).to receive(:displayed?).with(no_args)
150
- end
151
- end
152
- end
153
- describe '#has_name_iframe?' do
154
- subject { web_page_object.has_fb_iframe?(wait: 1, text: 'new') }
155
- context 'when first argument is integer' do
156
- before { web_page_class.class_eval { iframe :fb, 1, match: :first, text: 'origin' } }
157
- it do
158
- expect(kontext).to receive(:has_selector?)
159
- .with('iframe:nth-of-type(2)', match: :first, wait: 1, text: 'new')
160
- end
161
- end
162
- context 'when first argument is string' do
163
- before { web_page_class.class_eval { iframe :fb, 'loko', match: :first, text: 'origin' } }
164
- it { expect(kontext).to receive(:has_selector?).with(:frame, 'loko', match: :first, wait: 1, text: 'new') }
165
- end
166
- context 'when first argument is hash' do
167
- before { web_page_class.class_eval { iframe :fb, name: 'loko', match: :first, text: 'origin' } }
168
- it do
169
- expect(kontext).to receive(:has_selector?)
170
- .with(:frame, name: 'loko', match: :first, wait: 1, text: 'new')
171
- end
172
- end
173
- context 'when first argument is symbol' do
174
- before { web_page_class.class_eval { iframe :fb, :xpath, './/foo', match: :first, text: 'origin' } }
175
- it { expect(kontext).to receive(:has_selector?).with(:xpath, './/foo', match: :first, wait: 1, text: 'new') }
176
- end
177
- end
178
- describe '#has_no_name_iframe?' do
179
- subject { web_page_object.has_no_fb_iframe?(wait: 1, text: 'new') }
180
- context 'when first argument is integer' do
181
- before { web_page_class.class_eval { iframe :fb, 1, match: :first, text: 'origin' } }
182
- it do
183
- expect(kontext).to receive(:has_no_selector?)
184
- .with('iframe:nth-of-type(2)', match: :first, wait: 1, text: 'new')
185
- end
186
- end
187
- context 'when first argument is string' do
188
- before { web_page_class.class_eval { iframe :fb, 'loko', match: :first, text: 'origin' } }
189
- it { expect(kontext).to receive(:has_no_selector?).with(:frame, 'loko', match: :first, wait: 1, text: 'new') }
190
- end
191
- context 'when first argument is hash' do
192
- before { web_page_class.class_eval { iframe :fb, name: 'loko', match: :first, text: 'origin' } }
193
- it do
194
- expect(kontext).to receive(:has_no_selector?).with(:frame, name: 'loko', match: :first, wait: 1, text: 'new')
195
- end
196
- end
197
- context 'when first argument is symbol' do
198
- before { web_page_class.class_eval { iframe :fb, :xpath, './/foo', match: :first, text: 'origin' } }
199
- it { expect(kontext).to receive(:has_no_selector?).with(:xpath, './/foo', match: :first, wait: 1, text: 'new') }
200
- end
201
- end
202
- end
203
- end
@@ -1,74 +0,0 @@
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 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
-
67
- context 'when starts other prefix' do
68
- let(:scope) { described_class.new(page) { 1 } }
69
- subject { scope.foo(1, 2, 3) }
70
- before { expect(fake_page).to receive(:foo).with(1, 2, 3) { true } }
71
- it { is_expected.to eq(true) }
72
- end
73
- end
74
- end
@@ -1,378 +0,0 @@
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
-
13
- context 'when custom user_agent specified' do
14
- let(:url_value) { 'http://example.com/users' }
15
- let(:driver) { double }
16
- subject { described_class.open(validate: false) }
17
- before do
18
- allow(Howitzer).to receive(:user_agent) { 'user_agent' }
19
- allow(described_class).to receive(:retryable)
20
- allow(described_class).to receive(:expanded_url)
21
- allow(Howitzer::Log).to receive(:info)
22
- end
23
- context 'with webkit driver' do
24
- before { allow(Howitzer).to receive(:driver) { 'webkit' } }
25
- it do
26
- expect(Capybara).to receive_message_chain(:current_session, :driver) { driver }
27
- expect(driver).to receive(:header).with('User-Agent', Howitzer.user_agent)
28
- subject
29
- end
30
- end
31
- context 'with poltergeist driver' do
32
- before { allow(Howitzer).to receive(:driver) { 'poltergeist' } }
33
- it do
34
- expect(Capybara).to receive_message_chain(:current_session, :driver) { driver }
35
- expect(driver).to receive(:add_headers).with('User-Agent' => Howitzer.user_agent)
36
- subject
37
- end
38
- end
39
- end
40
-
41
- context 'when validate missing' do
42
- context 'when params present' do
43
- let(:url_value) { 'http://example.com/users/1' }
44
- subject { described_class.open(id: 1) }
45
- it do
46
- expect(described_class).to receive(:expanded_url).with({ id: 1 }, nil) { url_value }.once.ordered
47
- expect(Howitzer::Log).to receive(:info)
48
- .with("Open #{described_class} page by '#{url_value}' url").once.ordered
49
- expect(described_class).to receive(:retryable).ordered.once.and_call_original
50
- expect(session).to receive(:visit).with(url_value).once.ordered
51
- expect(described_class).to receive(:given).once.ordered.and_return(true)
52
- expect(subject).to eq(true)
53
- end
54
- end
55
- context 'when custom processor specified' do
56
- let(:custom_processor) { double }
57
- let(:url_value) { 'http://example.com/users/1' }
58
- subject { described_class.open(id: 1, url_processor: custom_processor) }
59
- it do
60
- expect(described_class).to receive(:expanded_url).with({ id: 1 }, custom_processor) { url_value }.once.ordered
61
- expect(Howitzer::Log).to receive(:info)
62
- .with("Open #{described_class} page by '#{url_value}' url").once.ordered
63
- expect(described_class).to receive(:retryable).ordered.once.and_call_original
64
- expect(session).to receive(:visit).with(url_value).once.ordered
65
- expect(described_class).to receive(:given).once.ordered.and_return(true)
66
- expect(subject).to eq(true)
67
- end
68
- end
69
- context 'when params missing' do
70
- let(:url_value) { 'http://example.com/users' }
71
- subject { described_class.open }
72
- it do
73
- expect(described_class).to receive(:expanded_url).with({}, nil).and_return(url_value).once.ordered
74
- expect(Howitzer::Log).to receive(:info)
75
- .with("Open #{described_class} page by '#{url_value}' url").once.ordered
76
- expect(described_class).to receive(:retryable).ordered.once.and_call_original
77
- expect(session).to receive(:visit).with(url_value).once.ordered
78
- expect(described_class).to receive(:given).once.ordered.and_return(true)
79
- expect(subject).to eq(true)
80
- end
81
- end
82
- end
83
- context 'when validate: false' do
84
- let(:url_value) { 'http://example.com/users' }
85
- subject { described_class.open(validate: false) }
86
- it do
87
- expect(described_class).to receive(:expanded_url).with({}, nil).and_return(url_value).once.ordered
88
- expect(Howitzer::Log).to receive(:info).with("Open #{described_class} page by '#{url_value}' url").once.ordered
89
- expect(described_class).to receive(:retryable).ordered.once.and_call_original
90
- expect(session).to receive(:visit).with(url_value).once.ordered
91
- expect(described_class).not_to receive(:given)
92
- expect(subject).to be_nil
93
- end
94
- end
95
- context 'when validate: true with params' do
96
- let(:url_value) { 'http://example.com/users/1' }
97
- subject { described_class.open(validate: true, id: 1) }
98
- it do
99
- expect(described_class).to receive(:expanded_url).with({ id: 1 }, nil).and_return(url_value).once.ordered
100
- expect(Howitzer::Log).to receive(:info).with("Open #{described_class} page by '#{url_value}' url").once.ordered
101
- expect(described_class).to receive(:retryable).ordered.once.and_call_original
102
- expect(session).to receive(:visit).with(url_value).once.ordered
103
- expect(described_class).to receive(:given).once.ordered.and_return(true)
104
- expect(subject).to eq(true)
105
- end
106
- end
107
- end
108
-
109
- describe '.given' do
110
- subject { described_class.given }
111
- before do
112
- expect(described_class).to receive(:displayed?).with(no_args).once
113
- expect(described_class).to receive(:instance).and_return(true)
114
- end
115
- it { is_expected.to be_truthy }
116
- end
117
-
118
- describe '.title' do
119
- let(:page) { double }
120
- subject { described_class.instance.title }
121
- before do
122
- allow_any_instance_of(described_class).to receive(:check_validations_are_defined!).and_return(true)
123
- allow(session).to receive(:current_url).and_return('google.com')
124
- end
125
- it do
126
- expect(session).to receive(:title)
127
- subject
128
- end
129
- end
130
-
131
- describe '.current_page' do
132
- subject { described_class.current_page }
133
- context 'when matched_pages has no pages' do
134
- before { allow(described_class).to receive(:matched_pages).and_return([]) }
135
- it { is_expected.to eq(described_class::UnknownPage) }
136
- end
137
- context 'when matched_pages has more than 1 page' do
138
- let(:foo_page) { double(inspect: 'FooPage') }
139
- let(:bar_page) { double(inspect: 'BarPage') }
140
- before do
141
- allow_any_instance_of(described_class).to receive(:check_validations_are_defined!).and_return(true)
142
- allow(session).to receive(:current_url).and_return('http://test.com')
143
- allow(session).to receive(:title) { 'Test site' }
144
- allow(described_class).to receive(:matched_pages).and_return([foo_page, bar_page])
145
- end
146
- it do
147
- expect { subject }.to raise_error(
148
- Howitzer::AmbiguousPageMatchingError,
149
- "Current page matches more that one page class (FooPage, BarPage).\n" \
150
- "\tCurrent url: http://test.com\n\tCurrent title: Test site"
151
- )
152
- end
153
- end
154
- context 'when matched_pages has only 1 page' do
155
- let(:foo_page) { double(to_s: 'FooPage') }
156
- before { allow(described_class).to receive(:matched_pages).and_return([foo_page]) }
157
- it { is_expected.to eq(foo_page) }
158
- end
159
- end
160
-
161
- describe '.displayed?' do
162
- subject { described_class.displayed? }
163
- context 'when page is opened' do
164
- before { allow(described_class).to receive(:opened?).and_return(true) }
165
- it { is_expected.to eq(true) }
166
- end
167
- context 'when page is not opened' do
168
- before do
169
- allow(described_class).to receive(:current_page).and_return('FooPage')
170
- allow(session).to receive(:current_url).and_return('http://test.com')
171
- allow(session).to receive(:title).and_return('Test site')
172
- allow(described_class).to receive(:opened?).and_return(false)
173
- end
174
- it do
175
- expect { subject }.to raise_error(
176
- Howitzer::IncorrectPageError,
177
- "Current page: FooPage, expected: #{described_class}.\n" \
178
- "\tCurrent url: http://test.com\n\tCurrent title: Test site"
179
- )
180
- end
181
- end
182
- end
183
-
184
- describe '.current_url' do
185
- before { allow(Capybara).to receive_message_chain(:current_session, :current_url).and_return('http://example.com') }
186
- it 'should return current url page' do
187
- expect(Howitzer::Web::Page.current_url).to eq('http://example.com')
188
- end
189
- end
190
-
191
- describe '.site' do
192
- let!(:base_class) do
193
- Class.new(described_class) do
194
- site 'https://base.com'
195
- end
196
- end
197
- let!(:child_class1) do
198
- Class.new(base_class) do
199
- site 'https://child.com'
200
- end
201
- end
202
- let!(:child_class2) do
203
- Class.new(base_class)
204
- end
205
- let!(:child_class3) do
206
- Class.new(described_class)
207
- end
208
- it { expect(described_class.send(:site_value)).to eq('http://login:pass@my.website.com') }
209
- it { expect(base_class.send(:site_value)).to eq('https://base.com') }
210
- it { expect(child_class1.send(:site_value)).to eq('https://child.com') }
211
- it { expect(child_class2.send(:site_value)).to eq('https://base.com') }
212
- it { expect(child_class3.send(:site_value)).to eq('http://login:pass@my.website.com') }
213
- it 'should be protected' do
214
- expect { described_class.site('http://example.com') }.to raise_error(NoMethodError)
215
- end
216
- end
217
-
218
- describe '.expanded_url' do
219
- context 'when default url processor' do
220
- context 'when params present' do
221
- subject { test_page.expanded_url(id: 1) }
222
- context 'when page url specified' do
223
- context 'when BlankPage' do
224
- let(:test_page) { Howitzer::Web::BlankPage }
225
- it { is_expected.to eq('about:blank') }
226
- end
227
- context 'when other page' do
228
- let(:test_page) do
229
- Class.new(described_class) do
230
- site 'http://example.com'
231
- path '/users{/id}'
232
- end
233
- end
234
- it { is_expected.to eq('http://example.com/users/1') }
235
- end
236
- context 'when root not specified' do
237
- let(:test_page) do
238
- Class.new(described_class) do
239
- path '/users{/id}'
240
- end
241
- end
242
- it { is_expected.to eq('http://login:pass@my.website.com/users/1') }
243
- end
244
- end
245
- end
246
- context 'when custom url processor' do
247
- let(:test_page) do
248
- Class.new(described_class) do
249
- site 'http://example.com'
250
- path '/users{/id}'
251
- end
252
- end
253
- let(:custom_processor_class) do
254
- Class.new do
255
- def self.restore(_name, value)
256
- value.tr('-', ' ')
257
- end
258
-
259
- def self.match(_name)
260
- '.*'
261
- end
262
-
263
- def self.validate(_name, value)
264
- !(value =~ /^[\w ]+$/).nil?
265
- end
266
-
267
- def self.transform(_name, value)
268
- value.tr(' ', '+')
269
- end
270
- end
271
- end
272
- subject { test_page.expanded_url({ id: 'hello world' }, custom_processor_class) }
273
- it { is_expected.to eq('http://example.com/users/hello+world') }
274
- end
275
- context 'when page url missing' do
276
- subject { described_class.expanded_url }
277
- it do
278
- expect { subject }.to raise_error(
279
- ::Howitzer::NoPathForPageError,
280
- "Please specify path for '#{described_class}' page. Example: path '/home'"
281
- )
282
- end
283
- end
284
- end
285
- context 'when params missing' do
286
- let(:test_page) do
287
- Class.new(described_class) do
288
- site 'http://example.com'
289
- path '/users'
290
- end
291
- end
292
- subject { test_page.expanded_url }
293
- it { is_expected.to eq('http://example.com/users') }
294
- end
295
- end
296
-
297
- describe '.path' do
298
- subject { described_class.send(:path, value) }
299
- before { subject }
300
- context 'when value is number' do
301
- let(:value) { 1 }
302
- it do
303
- expect(described_class.send(:path_value)).to eql '1'
304
- expect(described_class.private_methods(true)).to include(:path_value)
305
- end
306
- end
307
- context 'when value is string' do
308
- let(:value) { '/users' }
309
- it do
310
- expect(described_class.send(:path_value)).to eql '/users'
311
- end
312
- end
313
- end
314
-
315
- describe '#initialize' do
316
- subject { described_class.send(:new) }
317
- before do
318
- expect_any_instance_of(described_class).to receive(:check_validations_are_defined!).once.and_return(true)
319
- end
320
- context 'when maximized_window is true' do
321
- let(:driver) { double }
322
- before { allow(Howitzer).to receive(:maximized_window) { true } }
323
- it do
324
- expect_any_instance_of(described_class).to receive_message_chain('current_window.maximize')
325
- subject
326
- end
327
- end
328
- context 'when maximized_window is true and driver is headless_chrome' do
329
- before do
330
- allow(Howitzer).to receive(:maximized_window) { true }
331
- allow(Capybara).to receive(:current_driver) { 'headless_chrome' }
332
- end
333
- it do
334
- expect_any_instance_of(described_class).not_to receive('current_window.maximize')
335
- subject
336
- end
337
- end
338
- context 'when maximized_window is false' do
339
- before { allow(Howitzer).to receive(:maximized_window) { false } }
340
- it do
341
- expect_any_instance_of(described_class).not_to receive('current_window.maximize')
342
- subject
343
- end
344
- end
345
- end
346
-
347
- describe 'inherited callback' do
348
- let(:page_class) { Class.new(described_class) }
349
- it 'can not be instantiated with new' do
350
- expect { page_class.new }.to raise_error(NoMethodError, "private method `new' called for #{page_class}")
351
- end
352
- end
353
-
354
- describe '#reload' do
355
- let(:wait_for_url) { double }
356
- subject { described_class.instance.reload }
357
- let(:visit) { double }
358
- before do
359
- allow(session).to receive(:current_url).and_return('google.com')
360
- end
361
- it do
362
- expect(Howitzer::Log).to receive(:info).and_return("Reload 'google.com'")
363
- expect(session).to receive(:visit).with('google.com')
364
- subject
365
- end
366
- end
367
-
368
- describe '#capybara_context' do
369
- subject { described_class.instance.capybara_context }
370
- before { expect(Capybara).to receive(:current_session).and_return(:context) }
371
- it { is_expected.to eq(:context) }
372
- end
373
-
374
- describe 'includes proxied capybara methods' do
375
- let(:reciever) { described_class.instance }
376
- include_examples :capybara_methods_proxy
377
- end
378
- end