bdy 1.18.31-dev-commands-changes-869c3r8yn → 1.18.32-dev
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/distTs/package.json +1 -1
- package/distTs/src/agent/wait.js +17 -16
- package/distTs/src/agent/windows.js +8 -2
- package/distTs/src/api/client.js +0 -83
- package/distTs/src/command/project/get.js +18 -0
- package/distTs/src/command/project/set.js +31 -0
- package/distTs/src/command/sandbox/get/yaml.js +30 -0
- package/distTs/src/command/vt/scrape.js +193 -0
- package/distTs/src/command/whoami.js +0 -12
- package/distTs/src/index.js +6 -4
- package/distTs/src/input.js +0 -78
- package/distTs/src/output.js +1 -0
- package/distTs/src/project/cfg.js +0 -39
- package/distTs/src/texts.js +41 -68
- package/distTs/src/unitTest/requests.js +10 -23
- package/distTs/src/visualTest/context.js +31 -42
- package/distTs/src/visualTest/requests.js +139 -39
- package/distTs/src/visualTest/resources.js +38 -40
- package/distTs/src/visualTest/server.js +2 -2
- package/distTs/src/visualTest/snapshots.js +17 -18
- package/distTs/src/visualTest/validation.js +10 -2
- package/package.json +1 -1
- package/distTs/src/command/crawl/link.js +0 -61
- package/distTs/src/command/crawl/run.js +0 -147
- package/distTs/src/command/crawl/validation.js +0 -154
- package/distTs/src/command/crawl.js +0 -13
- package/distTs/src/command/pipeline/run/start.js +0 -101
- package/distTs/src/command/pipeline/run/status.js +0 -34
- package/distTs/src/command/tests/capture/validation.js +0 -46
- package/distTs/src/command/tests/capture.js +0 -103
- package/distTs/src/command/tests/unit/link.js +0 -61
- package/distTs/src/command/tests/unit/upload.js +0 -91
- package/distTs/src/command/tests/unit.js +0 -13
- package/distTs/src/command/tests/visual/link.js +0 -61
- package/distTs/src/command/tests/visual/session/close.js +0 -32
- package/distTs/src/command/tests/visual/session/create.js +0 -86
- package/distTs/src/command/tests/visual/session.js +0 -13
- package/distTs/src/command/tests/visual/setup.js +0 -20
- package/distTs/src/command/tests/visual/shared/validation.js +0 -145
- package/distTs/src/command/tests/visual/upload.js +0 -141
- package/distTs/src/command/tests/visual.js +0 -17
- package/distTs/src/command/tests.js +0 -15
- package/distTs/src/crawl/requests.js +0 -141
- package/distTs/src/output/pipeline.js +0 -915
- package/distTs/src/types/crawl.js +0 -2
- package/distTs/src/types/pipeline.js +0 -424
- package/distTs/src/unitTest/context.js +0 -26
package/distTs/package.json
CHANGED
package/distTs/src/agent/wait.js
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
4
|
const waitUntilAgentEnabled = async (api, timeout, onTimeout, onSuccess) => {
|
|
5
|
-
let
|
|
6
|
-
|
|
7
|
-
s
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
let remaining = timeout;
|
|
6
|
+
while (remaining >= 1000) {
|
|
7
|
+
let s;
|
|
8
|
+
try {
|
|
9
|
+
s = await api.fetchStatus();
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
s = {};
|
|
13
|
+
}
|
|
14
|
+
if (s.enabled) {
|
|
15
|
+
return onSuccess();
|
|
16
|
+
}
|
|
17
|
+
remaining -= 1000;
|
|
18
|
+
if (remaining >= 1000) {
|
|
19
|
+
await (0, utils_1.sleep)(1000);
|
|
20
|
+
}
|
|
21
21
|
}
|
|
22
|
+
return onTimeout();
|
|
22
23
|
};
|
|
23
24
|
exports.default = waitUntilAgentEnabled;
|
|
@@ -117,8 +117,14 @@ class AgentWindows extends system_1.default {
|
|
|
117
117
|
if (user && pass) {
|
|
118
118
|
await this.nssm(`set bdy ObjectName ${user} ${pass}`);
|
|
119
119
|
}
|
|
120
|
-
if (start)
|
|
121
|
-
|
|
120
|
+
if (start) {
|
|
121
|
+
try {
|
|
122
|
+
await this.start();
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// do nothing, it will throw operation pending
|
|
126
|
+
}
|
|
127
|
+
}
|
|
122
128
|
logger_1.default.info(texts_1.LOG_AGENT_ENABLED);
|
|
123
129
|
}
|
|
124
130
|
catch (err) {
|
package/distTs/src/api/client.js
CHANGED
|
@@ -241,72 +241,6 @@ class ApiClient {
|
|
|
241
241
|
parseResponseBody: true,
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
|
-
async getVtSuites(workspace, project) {
|
|
245
|
-
return await this.request({
|
|
246
|
-
method: 'GET',
|
|
247
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/visual-tests/suites`,
|
|
248
|
-
parseResponseBody: true,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
async getCrawlSuites(workspace, project) {
|
|
252
|
-
return await this.request({
|
|
253
|
-
method: 'GET',
|
|
254
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/crawl/suites`,
|
|
255
|
-
parseResponseBody: true,
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
async getUtSuites(workspace, project) {
|
|
259
|
-
return await this.request({
|
|
260
|
-
method: 'GET',
|
|
261
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/unit-tests/suites`,
|
|
262
|
-
parseResponseBody: true,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
async createVtSuite(workspace, project, body) {
|
|
266
|
-
return await this.request({
|
|
267
|
-
method: 'POST',
|
|
268
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/visual-tests/suites`,
|
|
269
|
-
body,
|
|
270
|
-
parseResponseBody: true,
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
async createCrawlSuite(workspace, project, body) {
|
|
274
|
-
return await this.request({
|
|
275
|
-
method: 'POST',
|
|
276
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/crawl/suites`,
|
|
277
|
-
body,
|
|
278
|
-
parseResponseBody: true,
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
async createUtSuite(workspace, project, body) {
|
|
282
|
-
return await this.request({
|
|
283
|
-
method: 'POST',
|
|
284
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/unit-tests/suites`,
|
|
285
|
-
body,
|
|
286
|
-
parseResponseBody: true,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
async getVtSuiteToken(workspace, project, suiteId) {
|
|
290
|
-
return await this.request({
|
|
291
|
-
method: 'GET',
|
|
292
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/visual-tests/suites/${encodeURIComponent(suiteId)}/token`,
|
|
293
|
-
parseResponseBody: true,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
async getCrawlSuiteToken(workspace, project, suiteId) {
|
|
297
|
-
return await this.request({
|
|
298
|
-
method: 'GET',
|
|
299
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/crawl/suites/${encodeURIComponent(suiteId)}/token`,
|
|
300
|
-
parseResponseBody: true,
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
async getUtSuiteToken(workspace, project, suiteId) {
|
|
304
|
-
return await this.request({
|
|
305
|
-
method: 'GET',
|
|
306
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/unit-tests/suites/${encodeURIComponent(suiteId)}/token`,
|
|
307
|
-
parseResponseBody: true,
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
244
|
async getInvokerEmails() {
|
|
311
245
|
return await this.request({
|
|
312
246
|
method: 'GET',
|
|
@@ -754,23 +688,6 @@ class ApiClient {
|
|
|
754
688
|
parseResponseBody: true,
|
|
755
689
|
});
|
|
756
690
|
}
|
|
757
|
-
async resolveIdentifiers(workspace, params) {
|
|
758
|
-
let query = '';
|
|
759
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
760
|
-
if (value === undefined)
|
|
761
|
-
return;
|
|
762
|
-
if (!query)
|
|
763
|
-
query += '?';
|
|
764
|
-
else
|
|
765
|
-
query += '&';
|
|
766
|
-
query += encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
|
767
|
-
});
|
|
768
|
-
return await this.request({
|
|
769
|
-
method: 'GET',
|
|
770
|
-
path: `/workspaces/${encodeURIComponent(workspace)}/identifiers${query}`,
|
|
771
|
-
parseResponseBody: true,
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
691
|
async getPipelineByIdentifier(workspace, project, identifier) {
|
|
775
692
|
return await this.getResourceByIdentifier(workspace, {
|
|
776
693
|
project,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const cfg_1 = __importDefault(require("../../tunnel/cfg"));
|
|
7
|
+
const output_1 = __importDefault(require("../../output"));
|
|
8
|
+
const texts_1 = require("../../texts");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
const commandProjectGet = (0, utils_1.newCommand)('get', texts_1.DESC_COMMAND_PROJECT_GET);
|
|
11
|
+
commandProjectGet.action(async () => {
|
|
12
|
+
const project = cfg_1.default.getProject();
|
|
13
|
+
if (!project) {
|
|
14
|
+
output_1.default.exitError(texts_1.TXT_PROJECT_NONE);
|
|
15
|
+
}
|
|
16
|
+
output_1.default.exitNormal(project);
|
|
17
|
+
});
|
|
18
|
+
exports.default = commandProjectGet;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const cfg_1 = __importDefault(require("../../tunnel/cfg"));
|
|
7
|
+
const output_1 = __importDefault(require("../../output"));
|
|
8
|
+
const texts_1 = require("../../texts");
|
|
9
|
+
const utils_1 = require("../../utils");
|
|
10
|
+
const input_1 = __importDefault(require("../../input"));
|
|
11
|
+
const commandProjectSet = (0, utils_1.newCommand)('set', texts_1.DESC_COMMAND_PROJECT_SET);
|
|
12
|
+
commandProjectSet.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
|
|
13
|
+
commandProjectSet.argument('[project]', texts_1.ARG_COMMAND_PROJECT_NAME);
|
|
14
|
+
commandProjectSet.action(async (project, options) => {
|
|
15
|
+
output_1.default.handleSignals();
|
|
16
|
+
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
17
|
+
const client = input_1.default.restApiTokenClient();
|
|
18
|
+
if (project) {
|
|
19
|
+
await client.getProject(workspace, project);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
const response = await client.getProjects(workspace);
|
|
23
|
+
project = await output_1.default.selectProject(response.projects);
|
|
24
|
+
}
|
|
25
|
+
cfg_1.default.setProject(project);
|
|
26
|
+
if (!project)
|
|
27
|
+
output_1.default.exitSuccess(texts_1.TXT_PROJECT_SET_CLEARED);
|
|
28
|
+
else
|
|
29
|
+
output_1.default.exitSuccess((0, texts_1.TXT_PROJECT_SET_SUCCESS)(project));
|
|
30
|
+
});
|
|
31
|
+
exports.default = commandProjectSet;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("../../../utils");
|
|
7
|
+
const texts_1 = require("../../../texts");
|
|
8
|
+
const input_1 = __importDefault(require("../../../input"));
|
|
9
|
+
const output_1 = __importDefault(require("../../../output"));
|
|
10
|
+
const commandSandboxGetYaml = (0, utils_1.newCommand)('yaml', texts_1.DESC_COMMAND_SANDBOX_GET_YAML);
|
|
11
|
+
commandSandboxGetYaml.hideVersionUpdate = true;
|
|
12
|
+
commandSandboxGetYaml.alias('yml');
|
|
13
|
+
commandSandboxGetYaml.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
|
|
14
|
+
commandSandboxGetYaml.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
|
|
15
|
+
commandSandboxGetYaml.argument('<identifier>', texts_1.OPTION_SANDBOX_IDENTIFIER);
|
|
16
|
+
commandSandboxGetYaml.action(async (identifier, options) => {
|
|
17
|
+
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
18
|
+
const project = input_1.default.restApiProject(options.project);
|
|
19
|
+
const client = input_1.default.restApiTokenClient();
|
|
20
|
+
let result = await client.listSandboxes(workspace, project);
|
|
21
|
+
const sandboxes = result.sandboxes || [];
|
|
22
|
+
const found = sandboxes.find((s) => s.identifier === identifier);
|
|
23
|
+
if (!found) {
|
|
24
|
+
output_1.default.exitError(texts_1.ERR_SANDBOX_NOT_FOUND);
|
|
25
|
+
}
|
|
26
|
+
const sandboxId = found.id;
|
|
27
|
+
result = await client.getSandboxYaml(workspace, sandboxId);
|
|
28
|
+
output_1.default.exitNormal(Buffer.from(result.yaml, 'base64').toString('utf8'));
|
|
29
|
+
});
|
|
30
|
+
exports.default = commandSandboxGetYaml;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("../../utils");
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const texts_1 = require("../../texts");
|
|
9
|
+
const validation_1 = require("../../visualTest/validation");
|
|
10
|
+
const output_1 = __importDefault(require("../../output"));
|
|
11
|
+
const requests_1 = require("../../visualTest/requests");
|
|
12
|
+
const zod_1 = require("zod");
|
|
13
|
+
const node_zlib_1 = require("node:zlib");
|
|
14
|
+
const tar_stream_1 = __importDefault(require("tar-stream"));
|
|
15
|
+
const promises_1 = require("node:stream/promises");
|
|
16
|
+
const node_fs_1 = require("node:fs");
|
|
17
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
18
|
+
const promises_2 = require("node:fs/promises");
|
|
19
|
+
const commandScrape = (0, utils_1.newCommand)('scrape', texts_1.DESC_COMMAND_VT_SCRAPE);
|
|
20
|
+
commandScrape.argument('<url>', texts_1.OPTION_SCRAPE_URL);
|
|
21
|
+
commandScrape.option('--follow', texts_1.OPTION_SCRAPE_FOLLOW, false);
|
|
22
|
+
commandScrape.addOption(new commander_1.Option('--outputType <type>', texts_1.OPTION_SCRAPE_OUTPUT_TYPE)
|
|
23
|
+
.choices(['jpeg', 'png', 'md', 'html'])
|
|
24
|
+
.makeOptionMandatory());
|
|
25
|
+
commandScrape.option('--quality <quality>', texts_1.OPTION_SCRAPE_QUALITY);
|
|
26
|
+
commandScrape.option('--fullPage', texts_1.OPTION_SCRAPE_FULL_PAGE, false);
|
|
27
|
+
commandScrape.option('--cssSelector <selector>', texts_1.OPTION_SCRAPE_CSS_SELECTOR);
|
|
28
|
+
commandScrape.option('--xpathSelector <selector>', texts_1.OPTION_SCRAPE_XPATH_SELECTOR);
|
|
29
|
+
commandScrape.addOption(new commander_1.Option('--browser <browser>', texts_1.OPTION_SCRAPE_BROWSER)
|
|
30
|
+
.choices(['chrome', 'firefox', 'safari'])
|
|
31
|
+
.default('chrome'));
|
|
32
|
+
commandScrape.option('--viewport <viewport>', texts_1.OPTION_SCRAPE_VIEWPORT, '1920x1080');
|
|
33
|
+
commandScrape.option('--devicePixelRatio <ratio>', texts_1.OPTION_SCRAPE_DEVICE_PIXEL_RATIO, '1');
|
|
34
|
+
commandScrape.option('--waitForElement <selector>', texts_1.OPTION_SCRAPE_WAIT_FOR_ELEMENT);
|
|
35
|
+
commandScrape.option('--darkMode', texts_1.OPTION_SCRAPE_DARK_MODE, false);
|
|
36
|
+
commandScrape.option('--delay <delay>', texts_1.OPTION_SCRAPE_DELAY, '0');
|
|
37
|
+
commandScrape.option('--outputDir <dir>', texts_1.OPTION_SCRAPE_OUTPUT_DIR, '.');
|
|
38
|
+
commandScrape.action(async (inputUrl, options) => {
|
|
39
|
+
if (!(0, validation_1.checkToken)()) {
|
|
40
|
+
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
41
|
+
}
|
|
42
|
+
const { url, follow, outputType, quality, outputDir, fullPage, cssSelector, xpathSelector, browser, viewport, devicePixelRatio, darkMode, delay, waitForElement, } = validateInputAndOptions(inputUrl, options);
|
|
43
|
+
try {
|
|
44
|
+
const { buildId } = await (0, requests_1.sendScrap)(url, outputType, follow, quality, fullPage, cssSelector, xpathSelector, browser, viewport, devicePixelRatio, darkMode, delay, waitForElement);
|
|
45
|
+
output_1.default.normal('Starting scrape session');
|
|
46
|
+
const status = await watchSessionStatus(buildId);
|
|
47
|
+
if (!status.ok) {
|
|
48
|
+
output_1.default.exitError(`Unexpected error while watching session status: ${status.error}`);
|
|
49
|
+
}
|
|
50
|
+
output_1.default.normal('Downloading scrape package');
|
|
51
|
+
const scrapPackageStream = await (0, requests_1.downloadScrapPackage)(buildId);
|
|
52
|
+
const brotliDecompressor = (0, node_zlib_1.createBrotliDecompress)();
|
|
53
|
+
const unpack = tar_stream_1.default.extract();
|
|
54
|
+
unpack.on('entry', async (header, stream, next) => {
|
|
55
|
+
const currentDir = process.cwd();
|
|
56
|
+
const preparedOutputDir = outputDir.startsWith('.')
|
|
57
|
+
? node_path_1.default.join(currentDir, outputDir)
|
|
58
|
+
: outputDir;
|
|
59
|
+
const newFilePath = node_path_1.default.join(preparedOutputDir, header.name);
|
|
60
|
+
try {
|
|
61
|
+
if (header.type === 'file') {
|
|
62
|
+
await (0, promises_2.mkdir)(node_path_1.default.dirname(newFilePath), { recursive: true });
|
|
63
|
+
const fileWriteStream = (0, node_fs_1.createWriteStream)(newFilePath);
|
|
64
|
+
await (0, promises_1.pipeline)(stream, fileWriteStream);
|
|
65
|
+
next();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
stream.resume();
|
|
69
|
+
next();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (entryError) {
|
|
73
|
+
output_1.default.error(`Error processing entry ${header.name}: ${entryError}`);
|
|
74
|
+
next(entryError);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await (0, promises_1.pipeline)(scrapPackageStream, brotliDecompressor, unpack);
|
|
78
|
+
output_1.default.exitSuccess('Downloading scrape package finished');
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
output_1.default.exitError(`${error}`);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
function validateInputAndOptions(input, options) {
|
|
85
|
+
const urlSchema = zod_1.z.string().url();
|
|
86
|
+
const optionsSchema = zod_1.z.object({
|
|
87
|
+
follow: zod_1.z.boolean(),
|
|
88
|
+
outputType: zod_1.z.enum(['jpeg', 'png', 'md', 'html']),
|
|
89
|
+
quality: zod_1.z.coerce.number().min(1).max(100).optional(),
|
|
90
|
+
outputDir: zod_1.z.string().default('.'),
|
|
91
|
+
fullPage: zod_1.z.boolean().optional(),
|
|
92
|
+
cssSelector: zod_1.z.string().optional(),
|
|
93
|
+
xpathSelector: zod_1.z.string().optional(),
|
|
94
|
+
browser: zod_1.z.enum(['chrome', 'firefox', 'safari']),
|
|
95
|
+
viewport: zod_1.z
|
|
96
|
+
.string()
|
|
97
|
+
.refine((value) => {
|
|
98
|
+
const [width, height] = value.split('x');
|
|
99
|
+
return (width &&
|
|
100
|
+
height &&
|
|
101
|
+
!isNaN(Number(width)) &&
|
|
102
|
+
!isNaN(Number(height)) &&
|
|
103
|
+
Number(width) > 0 &&
|
|
104
|
+
Number(height) > 0);
|
|
105
|
+
}, 'Invalid viewport format, example: 1920x1080')
|
|
106
|
+
.transform((value) => {
|
|
107
|
+
const [width, height] = value.split('x');
|
|
108
|
+
return {
|
|
109
|
+
width: Number(width),
|
|
110
|
+
height: Number(height),
|
|
111
|
+
};
|
|
112
|
+
}),
|
|
113
|
+
devicePixelRatio: zod_1.z.coerce.number().min(1).max(4),
|
|
114
|
+
darkMode: zod_1.z.boolean(),
|
|
115
|
+
delay: zod_1.z.coerce.number().min(0).max(10000),
|
|
116
|
+
waitForElement: zod_1.z.string().optional(),
|
|
117
|
+
});
|
|
118
|
+
try {
|
|
119
|
+
const url = urlSchema.parse(input);
|
|
120
|
+
const { follow, outputType, quality, outputDir, fullPage, cssSelector, xpathSelector, browser, viewport, devicePixelRatio, darkMode, delay, waitForElement, } = optionsSchema.parse(options);
|
|
121
|
+
if (typeof quality === 'number' && outputType !== 'jpeg') {
|
|
122
|
+
output_1.default.exitError('Quality is only supported for jpeg output type, use --outputType jpeg');
|
|
123
|
+
}
|
|
124
|
+
if (cssSelector && xpathSelector) {
|
|
125
|
+
output_1.default.exitError('Only one of --cssSelector or --xpathSelector can be used');
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
url,
|
|
129
|
+
follow,
|
|
130
|
+
outputType,
|
|
131
|
+
quality,
|
|
132
|
+
outputDir,
|
|
133
|
+
fullPage,
|
|
134
|
+
cssSelector,
|
|
135
|
+
xpathSelector,
|
|
136
|
+
browser,
|
|
137
|
+
viewport,
|
|
138
|
+
devicePixelRatio,
|
|
139
|
+
darkMode,
|
|
140
|
+
delay,
|
|
141
|
+
waitForElement,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (error instanceof zod_1.ZodError) {
|
|
146
|
+
output_1.default.exitError(error.errors.map((e) => `${e.path}: ${e.message}`).join(', '));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async function watchSessionStatus(buildId) {
|
|
154
|
+
return new Promise((resolve) => {
|
|
155
|
+
const eventSource = (0, requests_1.connectToScrapSession)(buildId);
|
|
156
|
+
eventSource.addEventListener('SESSION_STATUS', (event) => {
|
|
157
|
+
const data = JSON.parse(event.data);
|
|
158
|
+
if (data.status === 'GATHER_URLS_COMPLETED') {
|
|
159
|
+
output_1.default.normal(`Gathering URLs completed, found ${data.text} URLs`);
|
|
160
|
+
}
|
|
161
|
+
else if (data.status === 'GATHER_URLS_FAILED') {
|
|
162
|
+
output_1.default.error('Gathering URLs failed');
|
|
163
|
+
}
|
|
164
|
+
else if (data.status === 'SCRAPE_URL_COMPLETED') {
|
|
165
|
+
output_1.default.normal(`Scraping ${data.text} completed`);
|
|
166
|
+
}
|
|
167
|
+
else if (data.status === 'SCRAPE_URL_FAILED') {
|
|
168
|
+
output_1.default.error(`Scraping ${data.text} failed`);
|
|
169
|
+
}
|
|
170
|
+
else if (data.status === 'CREATE_PACKAGE_COMPLETED') {
|
|
171
|
+
output_1.default.normal('Package created');
|
|
172
|
+
}
|
|
173
|
+
else if (data.status === 'CREATE_PACKAGE_FAILED') {
|
|
174
|
+
output_1.default.error('Package creation failed');
|
|
175
|
+
}
|
|
176
|
+
else if (data.status === 'FINISHED') {
|
|
177
|
+
eventSource.close();
|
|
178
|
+
output_1.default.normal('Scrape session finished');
|
|
179
|
+
resolve({ ok: true });
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
eventSource.addEventListener('error', (event) => {
|
|
183
|
+
if (event.code) {
|
|
184
|
+
eventSource.close();
|
|
185
|
+
if (event.code === 410) {
|
|
186
|
+
output_1.default.normal('Scrape session finished');
|
|
187
|
+
}
|
|
188
|
+
resolve({ ok: event.code === 410, error: event.code });
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
exports.default = commandScrape;
|
|
@@ -30,18 +30,6 @@ commandWhoami.action(async () => {
|
|
|
30
30
|
if (localProject) {
|
|
31
31
|
output_1.default.normal(`Project: ${localProject}`);
|
|
32
32
|
}
|
|
33
|
-
const vtSuite = cfg_2.default.getVtSuite();
|
|
34
|
-
const utSuite = cfg_2.default.getUtSuite();
|
|
35
|
-
const crawlSuite = cfg_2.default.getCrawlSuite();
|
|
36
|
-
if (vtSuite) {
|
|
37
|
-
output_1.default.normal(`Visual test suite: ${vtSuite}`);
|
|
38
|
-
}
|
|
39
|
-
if (utSuite) {
|
|
40
|
-
output_1.default.normal(`Unit test suite: ${utSuite}`);
|
|
41
|
-
}
|
|
42
|
-
if (crawlSuite) {
|
|
43
|
-
output_1.default.normal(`Crawl suite: ${crawlSuite}`);
|
|
44
|
-
}
|
|
45
33
|
output_1.default.exitNormal();
|
|
46
34
|
});
|
|
47
35
|
exports.default = commandWhoami;
|
package/distTs/src/index.js
CHANGED
|
@@ -11,8 +11,9 @@ const pre_1 = __importDefault(require("./command/pre"));
|
|
|
11
11
|
const stream_1 = __importDefault(require("stream"));
|
|
12
12
|
const utils_1 = require("./utils");
|
|
13
13
|
const texts_1 = require("./texts");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const vt_1 = __importDefault(require("./command/vt"));
|
|
15
|
+
const scrape_1 = __importDefault(require("./command/scrape"));
|
|
16
|
+
const ut_1 = __importDefault(require("./command/ut"));
|
|
16
17
|
const tunnel_1 = __importDefault(require("./command/tunnel"));
|
|
17
18
|
const pipeline_1 = __importDefault(require("./command/pipeline"));
|
|
18
19
|
const sandbox_1 = __importDefault(require("./command/sandbox"));
|
|
@@ -40,8 +41,9 @@ program.addCommand(tunnel_1.default);
|
|
|
40
41
|
if (!(0, utils_1.isDocker)())
|
|
41
42
|
program.addCommand(agent_1.default);
|
|
42
43
|
program.addCommand(version_1.default);
|
|
43
|
-
program.addCommand(
|
|
44
|
-
program.addCommand(
|
|
44
|
+
program.addCommand(vt_1.default);
|
|
45
|
+
program.addCommand(scrape_1.default);
|
|
46
|
+
program.addCommand(ut_1.default);
|
|
45
47
|
program.addCommand(pipeline_1.default);
|
|
46
48
|
program.addCommand(package_1.default);
|
|
47
49
|
program.addCommand(sandbox_1.default);
|
package/distTs/src/input.js
CHANGED
|
@@ -743,84 +743,6 @@ class Input {
|
|
|
743
743
|
host: d.host,
|
|
744
744
|
};
|
|
745
745
|
}
|
|
746
|
-
static async resolveSuiteId(client, workspace, project, identifier, type) {
|
|
747
|
-
const paramKey = type === 'vt' ? 'visual_test_suite'
|
|
748
|
-
: type === 'crawl' ? 'crawl_suite'
|
|
749
|
-
: 'unit_test_suite';
|
|
750
|
-
const responseKey = type === 'vt' ? 'visual_test_suite_id'
|
|
751
|
-
: type === 'crawl' ? 'crawl_suite_id'
|
|
752
|
-
: 'unit_test_suite_id';
|
|
753
|
-
try {
|
|
754
|
-
const result = await client.resolveIdentifiers(workspace, {
|
|
755
|
-
project,
|
|
756
|
-
[paramKey]: identifier,
|
|
757
|
-
});
|
|
758
|
-
return result?.[responseKey] ? String(result[responseKey]) : null;
|
|
759
|
-
}
|
|
760
|
-
catch {
|
|
761
|
-
return null;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
static async vtSuiteToken() {
|
|
765
|
-
const envToken = process.env.BUDDY_VT_TOKEN;
|
|
766
|
-
if (envToken)
|
|
767
|
-
return envToken;
|
|
768
|
-
const ProjectCfg = require('./project/cfg').default;
|
|
769
|
-
const suiteIdentifier = ProjectCfg.getVtSuite();
|
|
770
|
-
if (suiteIdentifier && (cfg_1.default.getApiToken() || process.env.BUDDY_TOKEN)) {
|
|
771
|
-
const workspace = Input.restApiWorkspace('', true);
|
|
772
|
-
const project = Input.restApiProject('', true);
|
|
773
|
-
if (workspace && project) {
|
|
774
|
-
const client = Input.restApiTokenClient();
|
|
775
|
-
const suiteId = await Input.resolveSuiteId(client, workspace, project, suiteIdentifier, 'vt');
|
|
776
|
-
if (!suiteId)
|
|
777
|
-
return '';
|
|
778
|
-
const result = await client.getVtSuiteToken(workspace, project, suiteId);
|
|
779
|
-
return String(result?.token || '');
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
return '';
|
|
783
|
-
}
|
|
784
|
-
static async crawlSuiteToken() {
|
|
785
|
-
const envToken = process.env.BUDDY_CRAWL_TOKEN;
|
|
786
|
-
if (envToken)
|
|
787
|
-
return envToken;
|
|
788
|
-
const ProjectCfg = require('./project/cfg').default;
|
|
789
|
-
const suiteIdentifier = ProjectCfg.getCrawlSuite();
|
|
790
|
-
if (suiteIdentifier && (cfg_1.default.getApiToken() || process.env.BUDDY_TOKEN)) {
|
|
791
|
-
const workspace = Input.restApiWorkspace('', true);
|
|
792
|
-
const project = Input.restApiProject('', true);
|
|
793
|
-
if (workspace && project) {
|
|
794
|
-
const client = Input.restApiTokenClient();
|
|
795
|
-
const suiteId = await Input.resolveSuiteId(client, workspace, project, suiteIdentifier, 'crawl');
|
|
796
|
-
if (!suiteId)
|
|
797
|
-
return '';
|
|
798
|
-
const result = await client.getCrawlSuiteToken(workspace, project, suiteId);
|
|
799
|
-
return String(result?.token || '');
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
return '';
|
|
803
|
-
}
|
|
804
|
-
static async utSuiteToken() {
|
|
805
|
-
const envToken = process.env.BUDDY_UT_TOKEN;
|
|
806
|
-
if (envToken)
|
|
807
|
-
return envToken;
|
|
808
|
-
const ProjectCfg = require('./project/cfg').default;
|
|
809
|
-
const suiteIdentifier = ProjectCfg.getUtSuite();
|
|
810
|
-
if (suiteIdentifier && (cfg_1.default.getApiToken() || process.env.BUDDY_TOKEN)) {
|
|
811
|
-
const workspace = Input.restApiWorkspace('', true);
|
|
812
|
-
const project = Input.restApiProject('', true);
|
|
813
|
-
if (workspace && project) {
|
|
814
|
-
const client = Input.restApiTokenClient();
|
|
815
|
-
const suiteId = await Input.resolveSuiteId(client, workspace, project, suiteIdentifier, 'ut');
|
|
816
|
-
if (!suiteId)
|
|
817
|
-
return '';
|
|
818
|
-
const result = await client.getUtSuiteToken(workspace, project, suiteId);
|
|
819
|
-
return String(result?.token || '');
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
return '';
|
|
823
|
-
}
|
|
824
746
|
static keyCert(keyPath, certPath) {
|
|
825
747
|
let key;
|
|
826
748
|
let cert;
|
package/distTs/src/output.js
CHANGED
|
@@ -24,9 +24,6 @@ class ProjectCfg {
|
|
|
24
24
|
get(path) {
|
|
25
25
|
let workspace = '';
|
|
26
26
|
let project = '';
|
|
27
|
-
let vtSuite = '';
|
|
28
|
-
let crawlSuite = '';
|
|
29
|
-
let utSuite = '';
|
|
30
27
|
try {
|
|
31
28
|
const str = node_fs_1.default.readFileSync(getFullPath(path), 'utf8');
|
|
32
29
|
const json = JSON.parse(str);
|
|
@@ -34,12 +31,6 @@ class ProjectCfg {
|
|
|
34
31
|
workspace = json.workspace;
|
|
35
32
|
if (json.project)
|
|
36
33
|
project = json.project;
|
|
37
|
-
if (json.vtSuite)
|
|
38
|
-
vtSuite = json.vtSuite;
|
|
39
|
-
if (json.crawlSuite)
|
|
40
|
-
crawlSuite = json.crawlSuite;
|
|
41
|
-
if (json.utSuite)
|
|
42
|
-
utSuite = json.utSuite;
|
|
43
34
|
}
|
|
44
35
|
catch {
|
|
45
36
|
// do nothing
|
|
@@ -47,26 +38,8 @@ class ProjectCfg {
|
|
|
47
38
|
return {
|
|
48
39
|
workspace,
|
|
49
40
|
project,
|
|
50
|
-
vtSuite,
|
|
51
|
-
crawlSuite,
|
|
52
|
-
utSuite,
|
|
53
41
|
};
|
|
54
42
|
}
|
|
55
|
-
setSuite(path, type, suiteIdentifier) {
|
|
56
|
-
const fullPath = getFullPath(path);
|
|
57
|
-
let json = {};
|
|
58
|
-
try {
|
|
59
|
-
const str = node_fs_1.default.readFileSync(fullPath, 'utf8');
|
|
60
|
-
json = JSON.parse(str);
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
// do nothing
|
|
64
|
-
}
|
|
65
|
-
const key = type === 'vt' ? 'vtSuite' : type === 'crawl' ? 'crawlSuite' : 'utSuite';
|
|
66
|
-
json[key] = suiteIdentifier;
|
|
67
|
-
node_fs_1.default.mkdirSync((0, node_path_1.dirname)(fullPath), { recursive: true });
|
|
68
|
-
node_fs_1.default.writeFileSync(fullPath, JSON.stringify(json), 'utf8');
|
|
69
|
-
}
|
|
70
43
|
getWorkspace() {
|
|
71
44
|
const c = this.get((0, utils_1.getWorkingDir)());
|
|
72
45
|
return c.workspace;
|
|
@@ -75,17 +48,5 @@ class ProjectCfg {
|
|
|
75
48
|
const c = this.get((0, utils_1.getWorkingDir)());
|
|
76
49
|
return c.project;
|
|
77
50
|
}
|
|
78
|
-
getVtSuite() {
|
|
79
|
-
const c = this.get((0, utils_1.getWorkingDir)());
|
|
80
|
-
return c.vtSuite;
|
|
81
|
-
}
|
|
82
|
-
getCrawlSuite() {
|
|
83
|
-
const c = this.get((0, utils_1.getWorkingDir)());
|
|
84
|
-
return c.crawlSuite;
|
|
85
|
-
}
|
|
86
|
-
getUtSuite() {
|
|
87
|
-
const c = this.get((0, utils_1.getWorkingDir)());
|
|
88
|
-
return c.utSuite;
|
|
89
|
-
}
|
|
90
51
|
}
|
|
91
52
|
exports.default = new ProjectCfg();
|