@percy/core 1.27.0-alpha.0 → 1.27.0-beta.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.
- package/dist/api.js +2 -4
- package/dist/config.js +42 -33
- package/dist/network.js +71 -12
- package/dist/page.js +9 -1
- package/dist/snapshot.js +10 -2
- package/dist/utils.js +2 -1
- package/package.json +12 -8
- package/dist/work.js +0 -30
package/dist/api.js
CHANGED
|
@@ -4,9 +4,7 @@ import { createRequire } from 'module';
|
|
|
4
4
|
import logger from '@percy/logger';
|
|
5
5
|
import { normalize } from '@percy/config/utils';
|
|
6
6
|
import { getPackageJSON, Server, percyAutomateRequestHandler } from './utils.js';
|
|
7
|
-
|
|
8
|
-
import WebdriverUtils from '@percy/webdriver-utils'; // eslint-disable-line import/no-extraneous-dependencies
|
|
9
|
-
|
|
7
|
+
import WebdriverUtils from '@percy/webdriver-utils';
|
|
10
8
|
// need require.resolve until import.meta.resolve can be transpiled
|
|
11
9
|
export const PERCY_DOM = createRequire(import.meta.url).resolve('@percy/dom');
|
|
12
10
|
|
|
@@ -140,7 +138,7 @@ export function createPercyServer(percy, port) {
|
|
|
140
138
|
.route('post', '/percy/flush', async (req, res) => res.json(200, {
|
|
141
139
|
success: await percy.flush(req.body).then(() => true)
|
|
142
140
|
})).route('post', '/percy/automateScreenshot', async (req, res) => {
|
|
143
|
-
req = percyAutomateRequestHandler(req);
|
|
141
|
+
req = percyAutomateRequestHandler(req, percy.build);
|
|
144
142
|
res.json(200, {
|
|
145
143
|
success: await percy.upload(await new WebdriverUtils(req.body).automateScreenshot()).then(() => true)
|
|
146
144
|
});
|
package/dist/config.js
CHANGED
|
@@ -541,6 +541,39 @@ export const snapshotSchema = {
|
|
|
541
541
|
}
|
|
542
542
|
}
|
|
543
543
|
};
|
|
544
|
+
const regionsSchema = {
|
|
545
|
+
type: 'array',
|
|
546
|
+
items: {
|
|
547
|
+
type: 'object',
|
|
548
|
+
additionalProperties: false,
|
|
549
|
+
properties: {
|
|
550
|
+
selector: {
|
|
551
|
+
type: 'string'
|
|
552
|
+
},
|
|
553
|
+
coOrdinates: {
|
|
554
|
+
type: 'object',
|
|
555
|
+
properties: {
|
|
556
|
+
top: {
|
|
557
|
+
type: 'integer',
|
|
558
|
+
minimum: 0
|
|
559
|
+
},
|
|
560
|
+
left: {
|
|
561
|
+
type: 'integer',
|
|
562
|
+
minimum: 0
|
|
563
|
+
},
|
|
564
|
+
bottom: {
|
|
565
|
+
type: 'integer',
|
|
566
|
+
minimum: 0
|
|
567
|
+
},
|
|
568
|
+
right: {
|
|
569
|
+
type: 'integer',
|
|
570
|
+
minimum: 0
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
};
|
|
544
577
|
|
|
545
578
|
// Comparison upload options
|
|
546
579
|
export const comparisonSchema = {
|
|
@@ -639,39 +672,15 @@ export const comparisonSchema = {
|
|
|
639
672
|
additionalProperties: false,
|
|
640
673
|
required: ['ignoreElementsData'],
|
|
641
674
|
properties: {
|
|
642
|
-
ignoreElementsData:
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
coOrdinates: {
|
|
652
|
-
type: 'object',
|
|
653
|
-
properties: {
|
|
654
|
-
top: {
|
|
655
|
-
type: 'integer',
|
|
656
|
-
minimum: 0
|
|
657
|
-
},
|
|
658
|
-
left: {
|
|
659
|
-
type: 'integer',
|
|
660
|
-
minimum: 0
|
|
661
|
-
},
|
|
662
|
-
bottom: {
|
|
663
|
-
type: 'integer',
|
|
664
|
-
minimum: 0
|
|
665
|
-
},
|
|
666
|
-
right: {
|
|
667
|
-
type: 'integer',
|
|
668
|
-
minimum: 0
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
+
ignoreElementsData: regionsSchema
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
consideredElementsData: {
|
|
679
|
+
type: 'object',
|
|
680
|
+
additionalProperties: false,
|
|
681
|
+
required: ['considerElementsData'],
|
|
682
|
+
properties: {
|
|
683
|
+
considerElementsData: regionsSchema
|
|
675
684
|
}
|
|
676
685
|
}
|
|
677
686
|
}
|
package/dist/network.js
CHANGED
|
@@ -5,16 +5,18 @@ import { normalizeURL, hostnameMatches, createResource, waitFor } from './utils.
|
|
|
5
5
|
const MAX_RESOURCE_SIZE = 25 * 1024 ** 2; // 25MB
|
|
6
6
|
const ALLOWED_STATUSES = [200, 201, 301, 302, 304, 307, 308];
|
|
7
7
|
const ALLOWED_RESOURCES = ['Document', 'Stylesheet', 'Image', 'Media', 'Font', 'Other'];
|
|
8
|
+
const ABORTED_MESSAGE = 'Request was aborted by browser';
|
|
8
9
|
|
|
9
10
|
// The Interceptor class creates common handlers for dealing with intercepting asset requests
|
|
10
11
|
// for a given page using various devtools protocol events and commands.
|
|
11
12
|
export class Network {
|
|
12
|
-
static TIMEOUT =
|
|
13
|
+
static TIMEOUT = undefined;
|
|
13
14
|
log = logger('core:discovery');
|
|
14
15
|
#pending = new Map();
|
|
15
16
|
#requests = new Map();
|
|
16
17
|
#intercepts = new Map();
|
|
17
18
|
#authentications = new Set();
|
|
19
|
+
#aborted = new Set();
|
|
18
20
|
constructor(page, options) {
|
|
19
21
|
this.page = page;
|
|
20
22
|
this.timeout = options.networkIdleTimeout ?? 100;
|
|
@@ -25,6 +27,7 @@ export class Network {
|
|
|
25
27
|
page.session.browser.version.userAgent.replace('Headless', '');
|
|
26
28
|
this.intercept = options.intercept;
|
|
27
29
|
this.meta = options.meta;
|
|
30
|
+
this._initializeNetworkIdleWaitTimeout();
|
|
28
31
|
}
|
|
29
32
|
watch(session) {
|
|
30
33
|
session.on('Network.requestWillBeSent', this._handleRequestWillBeSent);
|
|
@@ -76,6 +79,23 @@ export class Network {
|
|
|
76
79
|
});
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
// Validates that requestId is still valid as sometimes request gets cancelled and we have already executed
|
|
83
|
+
// _forgetRequest for the same, but we still attempt to make a call for it and it fails
|
|
84
|
+
// with Protocol error (Fetch.failRequest): Invalid InterceptionId.
|
|
85
|
+
async send(session, method, params) {
|
|
86
|
+
/* istanbul ignore else: currently all send have requestId */
|
|
87
|
+
if (params.requestId) {
|
|
88
|
+
/* istanbul ignore if: race condition, very hard to mock this */
|
|
89
|
+
if (this.isAborted(params.requestId)) {
|
|
90
|
+
throw new Error(ABORTED_MESSAGE);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return await session.send(method, params);
|
|
94
|
+
}
|
|
95
|
+
isAborted(requestId) {
|
|
96
|
+
return this.#aborted.has(requestId);
|
|
97
|
+
}
|
|
98
|
+
|
|
79
99
|
// Throw a better network timeout error
|
|
80
100
|
_throwTimeoutError(msg, filter = () => true) {
|
|
81
101
|
if (this.log.shouldLog('debug')) {
|
|
@@ -115,7 +135,7 @@ export class Network {
|
|
|
115
135
|
response = 'ProvideCredentials';
|
|
116
136
|
this.#authentications.add(requestId);
|
|
117
137
|
}
|
|
118
|
-
await
|
|
138
|
+
await this.send(session, 'Fetch.continueWithAuth', {
|
|
119
139
|
requestId: event.requestId,
|
|
120
140
|
authChallengeResponse: {
|
|
121
141
|
response,
|
|
@@ -221,7 +241,7 @@ export class Network {
|
|
|
221
241
|
if (!request) return;
|
|
222
242
|
request.response = response;
|
|
223
243
|
request.response.buffer = async () => {
|
|
224
|
-
let result = await
|
|
244
|
+
let result = await this.send(session, 'Network.getResponseBody', {
|
|
225
245
|
requestId
|
|
226
246
|
});
|
|
227
247
|
return Buffer.from(result.body, result.base64Encoded ? 'base64' : 'utf-8');
|
|
@@ -252,8 +272,18 @@ export class Network {
|
|
|
252
272
|
/* istanbul ignore if: race condition paranioa */
|
|
253
273
|
if (!request) return;
|
|
254
274
|
|
|
255
|
-
//
|
|
256
|
-
|
|
275
|
+
// If request was aborted, keep track of it as we need to cancel any in process callbacks for
|
|
276
|
+
// such a request to avoid Invalid InterceptionId errors
|
|
277
|
+
// Note: 404s also show up under ERR_ABORTED and not ERR_FAILED
|
|
278
|
+
if (event.errorText === 'net::ERR_ABORTED') {
|
|
279
|
+
let message = `Request aborted for ${request.url}: ${event.errorText}`;
|
|
280
|
+
this.log.debug(message, {
|
|
281
|
+
...this.meta,
|
|
282
|
+
url: request.url
|
|
283
|
+
});
|
|
284
|
+
this.#aborted.add(request.requestId);
|
|
285
|
+
} else if (event.errorText !== 'net::ERR_FAILED') {
|
|
286
|
+
// do not log generic messages since the real error was likely logged elsewhere
|
|
257
287
|
let message = `Request failed for ${request.url}: ${event.errorText}`;
|
|
258
288
|
this.log.debug(message, {
|
|
259
289
|
...this.meta,
|
|
@@ -262,6 +292,13 @@ export class Network {
|
|
|
262
292
|
}
|
|
263
293
|
this._forgetRequest(request);
|
|
264
294
|
};
|
|
295
|
+
_initializeNetworkIdleWaitTimeout() {
|
|
296
|
+
if (Network.TIMEOUT) return;
|
|
297
|
+
Network.TIMEOUT = parseInt(process.env.PERCY_NETWORK_IDLE_WAIT_TIMEOUT) || 30000;
|
|
298
|
+
if (Network.TIMEOUT > 60000) {
|
|
299
|
+
this.log.warn('Setting PERCY_NETWORK_IDLE_WAIT_TIMEOUT over 60000ms is not recommended. ' + 'If your page needs more than 60000ms to idle due to CPU/Network load, ' + 'its recommended to increase CI resources where this cli is running.');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
265
302
|
}
|
|
266
303
|
|
|
267
304
|
// Returns the normalized origin URL of a request
|
|
@@ -281,18 +318,19 @@ async function sendResponseResource(network, request, session) {
|
|
|
281
318
|
...network.meta,
|
|
282
319
|
url
|
|
283
320
|
};
|
|
321
|
+
let send = (method, params) => network.send(session, method, params);
|
|
284
322
|
try {
|
|
285
323
|
let resource = network.intercept.getResource(url);
|
|
286
324
|
network.log.debug(`Handling request: ${url}`, meta);
|
|
287
325
|
if (!(resource !== null && resource !== void 0 && resource.root) && hostnameMatches(disallowedHostnames, url)) {
|
|
288
326
|
log.debug('- Skipping disallowed hostname', meta);
|
|
289
|
-
await
|
|
327
|
+
await send('Fetch.failRequest', {
|
|
290
328
|
requestId: request.interceptId,
|
|
291
329
|
errorReason: 'Aborted'
|
|
292
330
|
});
|
|
293
331
|
} else if (resource && (resource.root || resource.provided || !disableCache)) {
|
|
294
332
|
log.debug(resource.root ? '- Serving root resource' : '- Resource cache hit', meta);
|
|
295
|
-
await
|
|
333
|
+
await send('Fetch.fulfillRequest', {
|
|
296
334
|
requestId: request.interceptId,
|
|
297
335
|
responseCode: resource.status || 200,
|
|
298
336
|
body: Buffer.from(resource.content).toString('base64'),
|
|
@@ -302,18 +340,35 @@ async function sendResponseResource(network, request, session) {
|
|
|
302
340
|
}))
|
|
303
341
|
});
|
|
304
342
|
} else {
|
|
305
|
-
await
|
|
343
|
+
await send('Fetch.continueRequest', {
|
|
306
344
|
requestId: request.interceptId
|
|
307
345
|
});
|
|
308
346
|
}
|
|
309
347
|
} catch (error) {
|
|
310
348
|
/* istanbul ignore next: too hard to test (create race condition) */
|
|
311
349
|
if (session.closing && error.message.includes('close')) return;
|
|
350
|
+
|
|
351
|
+
// if failure is due to an already aborted request, ignore it
|
|
352
|
+
// due to race condition we might get aborted event later and see a `Invalid InterceptionId`
|
|
353
|
+
// error before, in which case we should wait for a tick and check again
|
|
354
|
+
// Note: its not a necessity that we would get aborted callback in a tick, its just that if we
|
|
355
|
+
// already have it then we can safely ignore this error
|
|
356
|
+
// Its very hard to test it as this function should be called and request should get cancelled before
|
|
357
|
+
if (error.message === ABORTED_MESSAGE || error.message.includes('Invalid InterceptionId')) {
|
|
358
|
+
// defer this to the end of queue to make sure that any incoming aborted messages were
|
|
359
|
+
// handled and network.#aborted is updated
|
|
360
|
+
await new Promise((res, _) => process.nextTick(res));
|
|
361
|
+
/* istanbul ignore else: too hard to create race where abortion event is delayed */
|
|
362
|
+
if (network.isAborted(request.requestId)) {
|
|
363
|
+
log.debug(`Ignoring further steps for ${url} as request was aborted by the browser.`);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
312
367
|
log.debug(`Encountered an error handling request: ${url}`, meta);
|
|
313
368
|
log.debug(error);
|
|
314
369
|
|
|
315
370
|
/* istanbul ignore next: catch race condition */
|
|
316
|
-
await
|
|
371
|
+
await send('Fetch.failRequest', {
|
|
317
372
|
requestId: request.interceptId,
|
|
318
373
|
errorReason: 'Failed'
|
|
319
374
|
}).catch(e => log.debug(e, meta));
|
|
@@ -376,12 +431,16 @@ async function saveResponseResource(network, request) {
|
|
|
376
431
|
} else if (!enableJavaScript && !ALLOWED_RESOURCES.includes(request.type)) {
|
|
377
432
|
return log.debug(`- Skipping disallowed resource type [${request.type}]`, meta);
|
|
378
433
|
}
|
|
434
|
+
let detectedMime = mime.lookup(response.url);
|
|
379
435
|
let mimeType =
|
|
380
436
|
// ensure the mimetype is correct for text/plain responses
|
|
381
|
-
response.mimeType === 'text/plain' &&
|
|
437
|
+
response.mimeType === 'text/plain' && detectedMime || response.mimeType;
|
|
382
438
|
|
|
383
|
-
// font
|
|
384
|
-
|
|
439
|
+
// if we detect a font mime, we dont want to override it as different browsers may behave
|
|
440
|
+
// differently for incorrect mimetype in font response, but we want to treat it as a
|
|
441
|
+
// font anyway as font responses from the browser may not be properly encoded,
|
|
442
|
+
// so request them directly.
|
|
443
|
+
if (mimeType !== null && mimeType !== void 0 && mimeType.includes('font') || detectedMime && detectedMime.includes('font')) {
|
|
385
444
|
log.debug('- Requesting asset directly');
|
|
386
445
|
body = await makeDirectRequest(network, request);
|
|
387
446
|
}
|
package/dist/page.js
CHANGED
|
@@ -4,7 +4,7 @@ import Network from './network.js';
|
|
|
4
4
|
import { PERCY_DOM } from './api.js';
|
|
5
5
|
import { hostname, waitFor, waitForTimeout as sleep, serializeFunction } from './utils.js';
|
|
6
6
|
export class Page {
|
|
7
|
-
static TIMEOUT =
|
|
7
|
+
static TIMEOUT = undefined;
|
|
8
8
|
log = logger('core:page');
|
|
9
9
|
constructor(session, options) {
|
|
10
10
|
this.session = session;
|
|
@@ -12,6 +12,7 @@ export class Page {
|
|
|
12
12
|
this.enableJavaScript = options.enableJavaScript ?? true;
|
|
13
13
|
this.network = new Network(this, options);
|
|
14
14
|
this.meta = options.meta;
|
|
15
|
+
this._initializeLoadTimeout();
|
|
15
16
|
session.on('Runtime.executionContextCreated', this._handleExecutionContextCreated);
|
|
16
17
|
session.on('Runtime.executionContextDestroyed', this._handleExecutionContextDestroyed);
|
|
17
18
|
session.on('Runtime.executionContextsCleared', this._handleExecutionContextsCleared);
|
|
@@ -241,5 +242,12 @@ export class Page {
|
|
|
241
242
|
_handleExecutionContextsCleared = () => {
|
|
242
243
|
this.contextId = null;
|
|
243
244
|
};
|
|
245
|
+
_initializeLoadTimeout() {
|
|
246
|
+
if (Page.TIMEOUT) return;
|
|
247
|
+
Page.TIMEOUT = parseInt(process.env.PERCY_PAGE_LOAD_TIMEOUT) || 30000;
|
|
248
|
+
if (Page.TIMEOUT > 60000) {
|
|
249
|
+
this.log.warn('Setting PERCY_PAGE_LOAD_TIMEOUT over 60000ms is not recommended. ' + 'If your page needs more than 60000ms to load due to CPU/Network load, ' + 'its recommended to increase CI resources where this cli is running.');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
244
252
|
}
|
|
245
253
|
export default Page;
|
package/dist/snapshot.js
CHANGED
|
@@ -78,7 +78,7 @@ function mapSnapshotOptions(snapshots, context) {
|
|
|
78
78
|
// assign additional options to included snaphots
|
|
79
79
|
snapshotMatches(snap, include, exclude) ? Object.assign(snap, opts) : snap), snap => getSnapshotOptions(snap, context));
|
|
80
80
|
|
|
81
|
-
// reduce snapshots with
|
|
81
|
+
// reduce snapshots with options
|
|
82
82
|
return snapshots.reduce((acc, snapshot) => {
|
|
83
83
|
var _snapshot;
|
|
84
84
|
// transform snapshot URL shorthand into an object
|
|
@@ -417,7 +417,7 @@ export function createSnapshotsQueue(percy) {
|
|
|
417
417
|
})
|
|
418
418
|
// handle possible build errors returned by the API
|
|
419
419
|
.handle('error', (snapshot, error) => {
|
|
420
|
-
var _error$response;
|
|
420
|
+
var _error$response, _error$response2, _error$response2$body;
|
|
421
421
|
let result = {
|
|
422
422
|
...snapshot,
|
|
423
423
|
error
|
|
@@ -437,6 +437,14 @@ export function createSnapshotsQueue(percy) {
|
|
|
437
437
|
build.failed = true;
|
|
438
438
|
queue.close(true);
|
|
439
439
|
}
|
|
440
|
+
let errors = (_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : (_error$response2$body = _error$response2.body) === null || _error$response2$body === void 0 ? void 0 : _error$response2$body.errors;
|
|
441
|
+
let duplicate = (errors === null || errors === void 0 ? void 0 : errors.length) > 1 && errors[1].detail.includes('must be unique');
|
|
442
|
+
if (duplicate) {
|
|
443
|
+
if (process.env.PERCY_IGNORE_DUPLICATES !== 'true') {
|
|
444
|
+
percy.log.warn(`Ignored duplicate snapshot. ${errors[1].detail}`);
|
|
445
|
+
}
|
|
446
|
+
return result;
|
|
447
|
+
}
|
|
440
448
|
percy.log.error(`Encountered an error uploading snapshot: ${name}`, meta);
|
|
441
449
|
percy.log.error(error, meta);
|
|
442
450
|
return result;
|
package/dist/utils.js
CHANGED
|
@@ -20,7 +20,7 @@ export function normalizeURL(url) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
// Returns the body for automateScreenshot in structure
|
|
23
|
-
export function percyAutomateRequestHandler(req) {
|
|
23
|
+
export function percyAutomateRequestHandler(req, buildInfo) {
|
|
24
24
|
if (req.body.client_info) {
|
|
25
25
|
req.body.clientInfo = req.body.client_info;
|
|
26
26
|
}
|
|
@@ -30,6 +30,7 @@ export function percyAutomateRequestHandler(req) {
|
|
|
30
30
|
if (!req.body.options) {
|
|
31
31
|
req.body.options = {};
|
|
32
32
|
}
|
|
33
|
+
req.body.buildInfo = buildInfo;
|
|
33
34
|
return req;
|
|
34
35
|
}
|
|
35
36
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/core",
|
|
3
|
-
"version": "1.27.0-
|
|
3
|
+
"version": "1.27.0-beta.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public",
|
|
12
|
-
"tag": "
|
|
12
|
+
"tag": "beta"
|
|
13
13
|
},
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=14"
|
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
"types": "./types/index.d.ts",
|
|
25
25
|
"type": "module",
|
|
26
26
|
"exports": {
|
|
27
|
-
".":
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./types/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
},
|
|
28
31
|
"./utils": "./dist/utils.js",
|
|
29
32
|
"./config": "./dist/config.js",
|
|
30
33
|
"./install": "./dist/install.js",
|
|
@@ -40,10 +43,11 @@
|
|
|
40
43
|
"test:types": "tsd"
|
|
41
44
|
},
|
|
42
45
|
"dependencies": {
|
|
43
|
-
"@percy/client": "1.27.0-
|
|
44
|
-
"@percy/config": "1.27.0-
|
|
45
|
-
"@percy/dom": "1.27.0-
|
|
46
|
-
"@percy/logger": "1.27.0-
|
|
46
|
+
"@percy/client": "1.27.0-beta.1",
|
|
47
|
+
"@percy/config": "1.27.0-beta.1",
|
|
48
|
+
"@percy/dom": "1.27.0-beta.1",
|
|
49
|
+
"@percy/logger": "1.27.0-beta.1",
|
|
50
|
+
"@percy/webdriver-utils": "1.27.0-beta.1",
|
|
47
51
|
"content-disposition": "^0.5.4",
|
|
48
52
|
"cross-spawn": "^7.0.3",
|
|
49
53
|
"extract-zip": "^2.0.1",
|
|
@@ -54,5 +58,5 @@
|
|
|
54
58
|
"rimraf": "^3.0.2",
|
|
55
59
|
"ws": "^8.0.0"
|
|
56
60
|
},
|
|
57
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "40cdf9c38613ccaf5e3707cd2cd2d2778ffbd5dd"
|
|
58
62
|
}
|
package/dist/work.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const webdriver = require('selenium-webdriver');
|
|
2
|
-
const remote = require('selenium-webdriver/remote');
|
|
3
|
-
export default class PoaDriver {
|
|
4
|
-
sessionId = '';
|
|
5
|
-
commandExecutorUrl = '';
|
|
6
|
-
capabilities = {};
|
|
7
|
-
driver = null;
|
|
8
|
-
constructor(sessionId, commandExecutorUrl, capabilities) {
|
|
9
|
-
this.sessionId = sessionId;
|
|
10
|
-
this.commandExecutorUrl = commandExecutorUrl;
|
|
11
|
-
this.capabilities = capabilities;
|
|
12
|
-
this.createDriver();
|
|
13
|
-
this.localScreenshot();
|
|
14
|
-
}
|
|
15
|
-
createDriver() {
|
|
16
|
-
this.driver = new webdriver.Remote({
|
|
17
|
-
sessionId: this.sessionId,
|
|
18
|
-
commandExecutor: new remote.SeleniumWebDriverError(this.commandExecutorUrl),
|
|
19
|
-
desiredCapabilities: this.capabilities
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
localScreenshot() {
|
|
23
|
-
console.log(this.driver);
|
|
24
|
-
this.driver.takeScreenshot().then(function (image, err) {
|
|
25
|
-
require('fs').writeFile('./out1234.png', image, 'base64', function (err) {
|
|
26
|
-
console.log(err);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
}
|