-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsauceVisualCheck.ts
133 lines (122 loc) · 4.37 KB
/
sauceVisualCheck.ts
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
import { ensureError, getFullPageConfig, isSkipMode } from '@saucelabs/visual';
import { parseIgnoreOptions, toIgnoreRegionIn } from '../../utils/regions';
import { getMetaInfo, getVisualApi } from '../../utils/api';
import { VISUAL_BUILD_ID_KEY } from '../../utils/constants';
import { NightwatchAPI } from 'nightwatch';
import { NightwatchCustomCommandsModel } from 'nightwatch/types/custom-command';
import { CheckOptions, RunnerSettings } from '../../types';
import { Runnable } from 'mocha';
type APIType = NightwatchAPI & {
capabilities: Record<string, any>;
options: RunnerSettings;
};
export default class SauceVisualCheck implements NightwatchCustomCommandsModel {
// These are used for Cucumber
static featureName = '';
static scenarioName = '';
// Mocha context can be passed, but
// - not for all runners,
// - not always as the third argument
async command(name: string, optionsArg = {}, mochaContextArg = {}) {
console.log(`Checking ${name}`);
if (isSkipMode()) {
console.log(`Checking ${name}: SKIPPED`);
global.skipped = (global.skipped ?? 0) + 1;
return null;
}
// @ts-expect-error API doesn't allow us to type the options / extra values from webdriver.
const nightwatchBrowserObject: APIType = this.api as unknown as APIType;
//
// Check if the first argument is a Mocha context
const isMochaContext = (arg: Runnable | Record<any, any>) =>
arg.title &&
// TODO: Replace with a non-private member / usage.
// @ts-ignore
arg.ctx?._runnable?.title;
const [options, mochaContext] = (
isMochaContext(optionsArg)
? [{}, optionsArg]
: [optionsArg, mochaContextArg]
) as [CheckOptions, Runnable];
//
// Getting the suite and testname from the current test
let module = '';
let defaultTestName = '';
if (nightwatchBrowserObject && nightwatchBrowserObject.currentTest) {
module = nightwatchBrowserObject.currentTest.module || '';
defaultTestName = nightwatchBrowserObject.currentTest.name || '';
}
//
// With CucumberJS we don't get the data, so we use the static values that are being set in on of the
// global hooks during the eventBroadcaster TestCaseStarted
// Mocha is done through the mochaContext
const suiteName =
mochaContext?.title || SauceVisualCheck.featureName || module || '';
const testName =
// TODO: Replace with a non-private member / usage.
// @ts-ignore
mochaContext?.ctx?._runnable?.title ||
SauceVisualCheck.scenarioName ||
defaultTestName ||
'';
// Ignore magic
const ignoreOptions = options.ignore ?? [];
const resolvedIgnoreOptions = parseIgnoreOptions(ignoreOptions);
const ignoreRegions =
ignoreOptions.length > 0
? await toIgnoreRegionIn(resolvedIgnoreOptions)
: [];
//
// Get more info about the session
const {
capabilities,
sessionId,
options: {
webdriver: { host, port } = {},
sauceVisualService: {
captureDom: globalCaptureDom = false,
fullPage,
} = {},
},
} = nightwatchBrowserObject;
const sauceConfig = {
hostname: host,
port: port,
user: process.env.SAUCE_USERNAME,
key: process.env.SAUCE_ACCESS_KEY,
};
const jobId = capabilities['jobUuid'] || sessionId;
const buildId = process.env[VISUAL_BUILD_ID_KEY] || '';
if (!buildId) {
nightwatchBrowserObject.assert.fail('No buildId found');
return null;
}
const api = getVisualApi(sauceConfig);
const metaInfo = await getMetaInfo(api, sessionId, jobId);
let result: Awaited<
ReturnType<typeof api.createSnapshotFromWebDriver>
> | null = null;
try {
result = await api.createSnapshotFromWebDriver({
sessionId,
jobId,
buildUuid: buildId,
name: name,
ignoreRegions,
sessionMetadata: metaInfo,
suiteName,
testName,
fullPageConfig: getFullPageConfig(fullPage, options.fullPage),
clipSelector: options.clipSelector,
captureDom: options.captureDom ?? globalCaptureDom,
});
global.uploadedDiffIds.push(
...result.diffs.nodes.flatMap((diff) => diff.id),
);
} catch (e) {
const errorMessage = ensureError(e).message ?? 'Unknown error';
nightwatchBrowserObject.assert.fail(errorMessage);
}
return result;
}
}