/
spec_helper.rb
217 lines (187 loc) · 6 KB
/
spec_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
require 'bundler/setup'
require 'puppeteer'
require 'rollbar'
Rollbar.configure do |config|
if ENV['ROLLBAR_ACCESS_TOKEN']
config.access_token = ENV['ROLLBAR_ACCESS_TOKEN']
else
config.enabled = false
end
end
module PuppeteerEnvExtension
# @return [String] chrome, firefox
def product
(%w(chrome firefox) & [ENV['PUPPETEER_PRODUCT_RSPEC']]).first || 'chrome'
end
def chrome?
product == 'chrome'
end
def firefox?
product == 'firefox'
end
end
Puppeteer::Env.include(PuppeteerEnvExtension)
RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
config.example_status_persistence_file_path = '.rspec_status'
# Disable RSpec exposing methods globally on `Module` and `main`
config.disable_monkey_patching!
config.expect_with(:rspec) do |c|
c.syntax = :expect
end
launch_options = {
product: Puppeteer.env.product,
executable_path: ENV['PUPPETEER_EXECUTABLE_PATH_RSPEC'],
}.compact
if Puppeteer.env.debug? && !Puppeteer.env.ci?
launch_options[:headless] = false
end
if ENV['PUPPETEER_NO_SANDBOX_RSPEC']
args = launch_options[:args] || []
args << '--no-sandbox'
launch_options[:args] = args
end
# Every browser automation test case should spend less than 15sec.
if Puppeteer.env.ci?
config.around(:each, type: :puppeteer) do |example|
Timeout.timeout(15) { example.run }
end
end
config.around(:each, type: :puppeteer) do |example|
if ENV['PENDING_CHECK'] && !example.metadata[:pending]
skip 'Pending check mode'
end
@default_launch_options = launch_options
@puppeteer_headless = launch_options[:headless] != false
# if example.metadata[:disable_web_security]
# # Enable cross-origin access for cookies_spec
# # ref: https://github.com/puppeteer/puppeteer/issues/4053
# launch_options[:args] = [
# '--disable-web-security',
# '--disable-features=IsolateOrigins,site-per-process',
# ]
# end
if example.metadata[:enable_site_per_process_flag]
args = launch_options[:args] || []
args << '--site-per-process'
args << '--host-rules=MAP * 127.0.0.1'
launch_options[:args] = args
end
if example.metadata[:puppeteer].to_s == 'browser'
Puppeteer.launch(**launch_options) do |browser|
@puppeteer_browser = browser
example.run
end
elsif example.metadata[:browser_context].to_s == 'incognito'
Puppeteer.launch(**launch_options) do |browser|
@puppeteer_browser_context = browser.create_incognito_browser_context
@puppeteer_page = @puppeteer_browser_context.new_page
begin
example.run
ensure
@puppeteer_page.close
end
end
else
if Puppeteer.env.firefox?
Puppeteer.launch(**launch_options) do |browser|
# Firefox often fails page.focus by reusing the page with 'browser.pages.first'.
# So create new page for each spec.
@puppeteer_page = browser.new_page
begin
example.run
ensure
@puppeteer_page.close
end
end
else
Puppeteer.launch(**launch_options) do |browser|
@puppeteer_page = browser.new_page
example.run
end
end
end
end
# Unit test doesn't connect to internet. No need to wait for 30sec. Set it to 7.5sec.
config.before(:each, type: :puppeteer) do
stub_const("Puppeteer::TimeoutSettings::DEFAULT_TIMEOUT", 7500)
end
config.define_derived_metadata(file_path: %r(/spec/integration/)) do |metadata|
metadata[:type] = :puppeteer
end
module PuppeteerMethods
def headless?
@puppeteer_headless
end
def browser
@puppeteer_browser or raise NoMethodError.new('undefined method "browser" (If you intended to use puppeteer#browser, you have to add `puppeteer: :browser` to metadata.)')
end
def browser_context
@puppeteer_browser_context or raise NoMethodError.new('undefined method "browser_context"')
end
def page
@puppeteer_page or raise NoMethodError.new('undefined method "page"')
end
def default_launch_options
@default_launch_options or raise NoMethodError.new('undefined method "default_launch_options"')
end
end
config.include PuppeteerMethods, type: :puppeteer
test_with_sinatra = Module.new do
attr_reader :server_port, :server_prefix, :server_cross_process_prefix, :server_empty_page, :sinatra
end
config.include(test_with_sinatra, sinatra: true)
config.around(sinatra: true) do |example|
require 'net/http'
require 'sinatra/base'
require 'timeout'
sinatra_app = Sinatra.new
sinatra_app.disable(:protection)
sinatra_app.set(:quiet, true)
sinatra_app.set(:public_folder, File.join(__dir__, 'assets'))
sinatra_app.set(:logging, false)
@server_port = 4567
@server_prefix = "http://localhost:#{@server_port}"
@server_cross_process_prefix = "http://127.0.0.1:#{@server_port}"
@server_empty_page = "#{@server_prefix}/empty.html"
sinatra_app.get('/_ping') { '_pong' }
# Start server and wait for server ready.
# FIXME should change port when Errno::EADDRINUSE
Thread.new { sinatra_app.run!(port: 4567) }
Timeout.timeout(3) do
loop do
Net::HTTP.get(URI("#{server_prefix}/_ping"))
break
rescue Errno::EADDRNOTAVAIL
sleep 1
rescue Errno::ECONNREFUSED
sleep 0.1
end
end
begin
@sinatra = sinatra_app
example.run
ensure
sinatra_app.quit!
end
end
end
module ItFailsFirefox
def it_fails_firefox(*args, **kwargs, &block)
if Puppeteer.env.firefox?
if ENV['PENDING_CHECK']
# Executed but not marked as failure.
# Fails if pass.
pending(*args, **kwargs, &block)
else
# Not executed, just skip.
skip(*args, **kwargs, &block)
end
else
it(*args, **kwargs, &block)
end
end
end
RSpec::Core::ExampleGroup.extend(ItFailsFirefox)
require_relative './golden_matcher'
require_relative './utils'