Repository navigation
Expand file tree
/
Copy pathexport_test.go
More file actions
356 lines (302 loc) · 16 KB
/
Copy pathexport_test.go
File metadata and controls
356 lines (302 loc) · 16 KB
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
package biloba
import (
"context"
"time"
"github.com/onsi/biloba/engine"
)
// CapOutlineForTest exposes capOutlineWithCap so that outline_test.go can
// exercise the truncation path with a small byte cap.
func CapOutlineForTest(s string, maxBytes int) string {
return capOutlineWithCap(s, maxBytes)
}
// InlineImagesSupportedForTest exposes inlineImagesSupported for screenshots_test.go.
func InlineImagesSupportedForTest() bool {
return inlineImagesSupported()
}
// InlineScreenshotsEnabledForTest exposes inlineScreenshotsEnabled for screenshots_test.go.
func (b *Biloba) InlineScreenshotsEnabledForTest() bool {
return b.inlineScreenshotsEnabled()
}
// SanitizeForFilenameForTest exposes sanitizeForFilename for use in screenshots_test.go.
func SanitizeForFilenameForTest(s string) string {
return sanitizeForFilename(s)
}
// LocateHeadlessShellForTest exposes locateHeadlessShell for headless_shell_test.go.
func LocateHeadlessShellForTest(explicit string) string {
return locateHeadlessShell(explicit)
}
// HeadlessShellBinaryNameForTest exposes the shared platform-specific shell name.
func HeadlessShellBinaryNameForTest() string {
return headlessShellBinaryName()
}
// HeadlessShellInstructionsForTest exposes headlessShellInstructions for headless_shell_test.go.
func HeadlessShellInstructionsForTest() string {
return headlessShellInstructions()
}
// ChromeMajorVersionForTest exposes chromeMajorVersion for headless_shell_test.go.
func ChromeMajorVersionForTest(product string) int {
return chromeMajorVersion(product)
}
// MinimumSupportedChromeMajorForTest exposes minimumSupportedChromeMajor for headless_shell_test.go.
func MinimumSupportedChromeMajorForTest() int {
return minimumSupportedChromeMajor
}
// InstallHeadlessShellForTest exposes installHeadlessShell for headless_shell_test.go.
func InstallHeadlessShellForTest() (string, error) {
return installHeadlessShell()
}
// SetHeadlessShellResolverForTest replaces the engine resolver for deterministic adapter specs.
func SetHeadlessShellResolverForTest(resolver func(context.Context, string, bool) (string, bool, error)) func() {
previous := resolveHeadlessShell
resolveHeadlessShell = resolver
return func() { resolveHeadlessShell = previous }
}
// ResolveHeadlessShellForTest exercises the public Go adapter's error and progress behavior.
func ResolveHeadlessShellForTest(ginkgoT GinkgoTInterface, explicit string, autoInstall bool) (string, error) {
return resolveHeadlessShellPath(ginkgoT, &spinUpConfig{headlessShellPath: explicit, autoInstall: autoInstall})
}
// SandboxDecisionForTest applies the given SpinUpOptions (ChromeSandbox among them) to a fresh
// spinUpConfig exactly as SpinUpChrome does, then feeds the result to engine.ChromeSandboxDisabled
// for the given mode - proving ChromeSandbox reaches the same decision SpinUpChrome consults,
// without actually launching a browser.
func SandboxDecisionForTest(mode engine.ChromeMode, options ...SpinUpOption) (disabled bool, reason string) {
cfg := &spinUpConfig{}
for _, option := range options {
option(cfg)
}
return engine.ChromeSandboxDisabled(mode, cfg.sandbox)
}
// SafeAllTabScreenshotsForTest exposes safeAllTabScreenshots for integration tests.
func (b *Biloba) SafeAllTabScreenshotsForTest(width, height int) []TabScreenshotForTest {
shots := b.safeAllTabScreenshots(context.Background(), b.AllTabs(), b.gt.Name(), width, height, engine.CaptureFullScreenshotContext)
out := make([]TabScreenshotForTest, len(shots))
for i, s := range shots {
out[i] = TabScreenshotForTest{Title: s.title, FilePath: s.filePath, Failure: s.failure, ImgcatScreenshot: s.imgcatScreenshot}
}
return out
}
// ProgressReporterForTest renders what Ginkgo gets from Biloba's progress reporter.
func (b *Biloba) ProgressReporterForTest() string { return b.progressReporter(b.gt.Name()) }
// FailureArtifactConfigForTest exposes the resolved on-failure artifact configuration
// (after options and environment-driven policy are applied) for screenshots_test.go.
func (b *Biloba) FailureArtifactConfigForTest() (failureOutlines, failureScreenshots, inlineScreenshots bool, screenshotsDir string) {
return b.failureOutlines, b.failureScreenshots, b.inlineScreenshots, b.screenshotsDir
}
// DefaultAutomationScreenshotsDirForTest exposes the automation default directory constant.
func DefaultAutomationScreenshotsDirForTest() string {
return defaultAutomationScreenshotsDir
}
// SetAutomationDetectedForTest overrides the CI/agent detector so tests can pin a deterministic
// mode regardless of the environment they happen to run in. It returns a restore func.
func SetAutomationDetectedForTest(fn func() bool) func() {
prev := automationDetected
automationDetected = fn
return func() { automationDetected = prev }
}
// SetNavigationTimeoutForTest overrides navigationTimeout so navigation_test.go can exercise the
// wedged-navigation path without waiting the full production bound. Returns a restore func.
func SetNavigationTimeoutForTest(d time.Duration) func() {
prev := navigationTimeout
navigationTimeout = d
return func() { navigationTimeout = prev }
}
// SetLaunchAttemptTimeoutForTest shortens how long each SpinUpChrome launch attempt waits for
// Chrome's DevTools line, so a spec can drive the retry with a Chrome that never prints one.
// Returns a restore func.
func SetLaunchAttemptTimeoutForTest(d time.Duration) func() {
prev := launchAttemptTimeout
launchAttemptTimeout = d
return func() { launchAttemptTimeout = prev }
}
// SetCDPTimeoutsForTest shrinks the CDP backstop deadlines (see cdp.go) so cdp_test.go can exercise
// the wedged-Chrome path in milliseconds instead of waiting out the production bounds. Returns a
// restore func.
func SetCDPTimeoutsForTest(command time.Duration, await time.Duration) func() {
prevCommand, prevAwait := cdpTimeout, cdpAwaitTimeout
cdpTimeout, cdpAwaitTimeout = command, await
return func() { cdpTimeout, cdpAwaitTimeout = prevCommand, prevAwait }
}
// SetWedgedCDPForTest overrides the wedge-injection seam so cdp_test.go can simulate a Chrome that
// accepts a command and never answers - without actually wedging a renderer, which would peg a CPU
// for the rest of the run. Returns a restore func.
func SetWedgedCDPForTest(fn func() bool) func() {
return SetWedgedCDPWhenForTest(func(string) bool { return fn() })
}
// SetWedgedCDPWhenForTest is SetWedgedCDPForTest for the commands fn picks by what they do (the
// description runEngine is given: "look up the tab's browser context"). Returns a restore func.
func SetWedgedCDPWhenForTest(fn func(what string) bool) func() {
prev := simulateWedgedCDP
simulateWedgedCDP = fn
return func() { simulateWedgedCDP = prev }
}
// PageCrashedForTest exposes this tab's Inspector.targetCrashed flag for cdp_test.go.
func (b *Biloba) PageCrashedForTest() bool { return b.pageCrashed() }
// TabClosedForTest reports whether Biloba has seen Chrome detach this tab, for tabs_test.go.
func (b *Biloba) TabClosedForTest() bool { return b.destroyedSignal().Crashed() }
// SetTransientReadErrorForTest overrides the location()/title() read-error injection seam so
// navigation_test.go can simulate the transient CDP error a live navigation can legitimately throw
// (e.g. a target swapped mid-navigation) without reproducing the underlying race. Returns a restore
// func.
func SetTransientReadErrorForTest(fn func() error) func() {
prev := simulateTransientReadError
simulateTransientReadError = fn
return func() { simulateTransientReadError = prev }
}
// SafeAllTabConsoleErrorsForTest exposes safeAllTabConsoleErrors for logging_test.go - the captured
// console.error/console.assert messages Biloba replays at the top of the failure block.
func (b *Biloba) SafeAllTabConsoleErrorsForTest() []string {
return b.safeAllTabConsoleErrors(b.AllTabs())
}
// DetachedNodeNoteForTest exposes the poll-trajectory recorder's detached-node annotation (the
// "matched N× then stopped matching" signal) for dom_test.go.
func (b *Biloba) DetachedNodeNoteForTest() string {
return b.probes.renderDetachedNode()
}
// PollTrajectoryForTest exposes the poll-trajectory recorder's rendered value series - exactly what
// attachFailureArtifactsIfFailed would put under "Poll trajectory" - for probe_trajectory_test.go.
func (b *Biloba) PollTrajectoryForTest() string {
return b.probes.render()
}
// OccludedClicksNoteForTest exposes this tab's recorded occluded-click notes for interactions_test.go.
func (b *Biloba) OccludedClicksNoteForTest() string {
return b.occlusions.render()
}
// ResetPollDiagnosticsForTest exposes resetPollDiagnostics so a spec can start from a clean slate.
func (b *Biloba) ResetPollDiagnosticsForTest() {
b.resetPollDiagnostics()
}
// ShadowedHandlersNoteForTest exposes this tab's shadowed-network-handler note for network_test.go.
func (b *Biloba) ShadowedHandlersNoteForTest() string {
return b.renderShadowedHandlers()
}
// UnreadableResponseBodyNoteForTest exposes this tab's unreadable-response-body note for
// network_test.go.
func (b *Biloba) UnreadableResponseBodyNoteForTest() string {
return b.unreadableResponseBodies.render()
}
// SetVisualDirsForTest points the root's visual-regression directories - the committed baselines and
// the (gitignored) artifacts destination HaveScreenshot writes actual/diff PNGs to - at
// test-controlled locations, so visual_test.go can generate its baselines into a per-spec TempDir
// instead of committing pixels that vary by machine. Returns a restore func: the suite's b is shared
// and created once, so a leaked value would corrupt every later spec.
func (b *Biloba) SetVisualDirsForTest(baselinesDir string, screenshotsDir string) func() {
prevBaselines, prevScreenshots := b.root.baselinesDir, b.root.screenshotsDir
b.root.baselinesDir, b.root.screenshotsDir = baselinesDir, screenshotsDir
return func() { b.root.baselinesDir, b.root.screenshotsDir = prevBaselines, prevScreenshots }
}
// SetInlineScreenshotsForTest flips the shared root's inline-screenshots flag - the one
// BilobaConfigInlineScreenshots sets and automation detection clears - so visual_test.go can assert
// both sides of the human/agent gate on the diff image without standing up a second Biloba. Returns
// a restore func.
func (b *Biloba) SetInlineScreenshotsForTest(enabled bool) func() {
prev := b.root.inlineScreenshots
b.root.inlineScreenshots = enabled
return func() { b.root.inlineScreenshots = prev }
}
// SetUpdateScreenshotsForTest flips the BILOBA_UPDATE_SCREENSHOTS behavior for visual_test.go.
// Returns a restore func.
func (b *Biloba) SetUpdateScreenshotsForTest(update bool) func() {
prev := b.root.updateScreenshots
b.root.updateScreenshots = update
return func() { b.root.updateScreenshots = prev }
}
// ScreenshotSettleScheduleForTest exposes the gaps update mode leaves between the captures it
// compares, in order, so visual_test.go can assert on the schedule itself rather than on wall-clock
// timings that a loaded machine makes noisy.
func ScreenshotSettleScheduleForTest() []time.Duration {
schedule := []time.Duration{}
for n := range screenshotSettleAttempts - 1 {
schedule = append(schedule, screenshotSettleGap(n))
}
return schedule
}
// EmulateColorSchemeForTest applies a prefers-color-scheme override on this tab (or, with the empty
// string, restores the tab's own media), so visual_test.go can simulate the capture whose deferred teardown never
// landed and assert that the next Prepare() cleans it up.
func (b *Biloba) EmulateColorSchemeForTest(scheme string) error {
return b.emulateColorScheme(scheme)
}
// LeakEmulationForTest applies a geolocation, a time zone, an offline network, a disabled cache, and
// a notifications permission for origin without registering their DeferCleanups, so emulation_test.go
// can simulate teardowns that never landed and assert that the next Prepare() clears them.
func (b *Biloba) LeakEmulationForTest(timezone, origin string) error {
for _, apply := range []func() error{
func() error {
return applyEmulation(b, "geolocation", geolocationSetting, &Geolocation{Latitude: 1, Longitude: 2, Accuracy: 3}, sendGeolocation)
},
func() error {
return applyEmulation(b, "time zone", timezoneSetting, timezone, engine.SetTimezoneContext)
},
func() error {
return applyEmulation(b, "network state", networkStateSetting, NetworkState{Offline: true}, sendNetworkState)
},
func() error { return applyEmulation(b, "HTTP cache setting", cacheSetting, true, b.sendCacheDisabled) },
func() error {
return b.restorePermissions(map[string]map[Permission]PermissionState{origin: {PermissionNotifications: PermissionGranted}})
},
} {
if err := apply(); err != nil {
return err
}
}
return nil
}
// TruthyEnvForTest exposes truthyEnv (and its unrecognised-value warning) for visual_test.go,
// so the spelling table can be exercised without standing up a Biloba per spelling.
func (b *Biloba) TruthyEnvForTest(name string) bool { return b.truthyEnv(name) }
// ScreenshotToleranceForTest exposes the resolved suite-wide visual tolerance.
func (b *Biloba) ScreenshotToleranceForTest() (fraction float64, channel int) {
return b.root.screenshotTolerance.fraction, b.root.screenshotTolerance.channel
}
// UpdateScreenshotsForTest exposes the resolved BILOBA_UPDATE_SCREENSHOTS setting.
func (b *Biloba) UpdateScreenshotsForTest() bool { return b.root.updateScreenshots }
// VisualBaselinesDirForTest exposes the resolved baselines directory.
func (b *Biloba) VisualBaselinesDirForTest() string { return b.visualBaselinesDir() }
// VisualArtifactsDirForTest exposes the resolved actual/diff artifacts directory.
func (b *Biloba) VisualArtifactsDirForTest() string { return b.visualArtifactsDir() }
// TabScreenshotForTest is a test-accessible view of tabScreenshot.
type TabScreenshotForTest struct {
Title string
FilePath string
Failure string
ImgcatScreenshot string
}
// ChromeDownloadLimitForTest exposes the number of concurrent downloads Chrome accepts before it
// starts dropping them, so downloads_test.go can saturate the limit without hardcoding it.
func ChromeDownloadLimitForTest() int {
return _CHROME_DOWNLOAD_LIMIT
}
// FrameOutOfProcessForTest reports whether a frame handle drives an out-of-process frame, so
// frames_test.go can prove its fixture exercises the process model it claims to.
func (b *Biloba) FrameOutOfProcessForTest() bool { return b.frame != nil && b.frame.outOfProcess }
// FramesSoFarForTest returns what a running screencast has recorded so far, in arrival order, so
// screencast_test.go can wait for frames instead of sleeping for them.
func (rec *ScreencastRecording) FramesSoFarForTest() []ScreencastFrame {
rec.lock.Lock()
defer rec.lock.Unlock()
frames := make([]ScreencastFrame, len(rec.recorded))
for i, frame := range rec.recorded {
frames[i] = ScreencastFrame(frame)
}
return frames
}
// PausedClockReportForTest is the paused-clock entry a failure report would add for this tab now.
func (b *Biloba) PausedClockReportForTest() string { return b.pausedClockReport() }
// SetBilobaRegistrationForTest replaces the call that registers biloba.js to run at the start of
// every new document, so a spec can make the registration fail. Returns a restore func.
func SetBilobaRegistrationForTest(register func(context.Context, string) error) func() {
previous := registerBilobaOnNewDocument
registerBilobaOnNewDocument = register
return func() { registerBilobaOnNewDocument = previous }
}
// BilobaReloadsForTest is how many times biloba.js has been sent whole into a page by this process
// (reloadBiloba). A spec reads it before and after a navigation and query to pin that the
// document-start registration, not a re-send, put _biloba there.
func BilobaReloadsForTest() int64 { return bilobaReloads.Load() }
// SetTabAttachProbeForTest shrinks registerTabFor's attach watchdog to timeout and runs returned as
// each attach attempt returns, before the probe records whether it attached. Returns a restore func.
func SetTabAttachProbeForTest(timeout time.Duration, returned func()) func() {
previousTimeout, previousReturned := tabAttachTimeout, attachAttemptReturned
tabAttachTimeout, attachAttemptReturned = timeout, returned
return func() { tabAttachTimeout, attachAttemptReturned = previousTimeout, previousReturned }
}