bdy 1.18.8-dev → 1.18.9-dev-commands-changes-869c3r8yn
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/command/api/request.js +25 -3
- package/distTs/src/command/crawl/validation.js +151 -0
- package/distTs/src/command/crawl.js +144 -0
- package/distTs/src/command/login.js +1 -2
- package/distTs/src/command/scrape/validation.js +21 -15
- package/distTs/src/command/scrape.js +14 -15
- package/distTs/src/command/tests/capture/validation.js +59 -0
- package/distTs/src/command/tests/capture.js +100 -0
- package/distTs/src/command/tests/unit/upload.js +86 -0
- package/distTs/src/command/tests/unit.js +11 -0
- package/distTs/src/command/tests/visual/session/close.js +27 -0
- package/distTs/src/command/tests/visual/session/create.js +82 -0
- package/distTs/src/command/tests/visual/session.js +13 -0
- package/distTs/src/command/tests/visual/setup.js +20 -0
- package/distTs/src/command/tests/visual/shared/validation.js +118 -0
- package/distTs/src/command/tests/visual/upload.js +138 -0
- package/distTs/src/command/tests/visual.js +15 -0
- package/distTs/src/command/tests.js +15 -0
- package/distTs/src/command/ut/upload.js +48 -16
- package/distTs/src/command/vt/close.js +5 -5
- package/distTs/src/command/vt/compare.js +15 -18
- package/distTs/src/command/vt/exec.js +28 -28
- package/distTs/src/command/vt/installBrowser.js +2 -2
- package/distTs/src/command/vt/storybook.js +14 -14
- package/distTs/src/index.js +4 -6
- package/distTs/src/output.js +7 -2
- package/distTs/src/texts.js +39 -37
- package/distTs/src/types/crawl.js +2 -0
- package/distTs/src/visualTest/requests.js +1 -1
- package/package.json +1 -1
- package/distTs/src/command/project/get.js +0 -18
- package/distTs/src/command/project/set.js +0 -31
- package/distTs/src/command/sandbox/get/yaml.js +0 -30
- package/distTs/src/command/vt/scrape.js +0 -193
|
@@ -0,0 +1,86 @@
|
|
|
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 output_1 = __importDefault(require("../../../output"));
|
|
9
|
+
const commander_1 = require("commander");
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const token = process.env.BUDDY_UT_TOKEN || '';
|
|
12
|
+
const commandUtUpload = (0, utils_1.newCommand)('upload', texts_1.DESC_COMMAND_UT_UPLOAD);
|
|
13
|
+
commandUtUpload.argument('<glob>', texts_1.OPTION_UPLOAD_REPORT_GLOB);
|
|
14
|
+
commandUtUpload.addOption(new commander_1.Option('--format <format>', texts_1.OPTION_UPLOAD_REPORT_FORMAT)
|
|
15
|
+
.choices(['junit-xml'])
|
|
16
|
+
.makeOptionMandatory());
|
|
17
|
+
commandUtUpload.option('--dryRun', texts_1.OPTION_UPLOAD_DRY_RUN);
|
|
18
|
+
commandUtUpload.action(async (input, options) => {
|
|
19
|
+
const { getCiInfo } = require('../../../unitTest/ci');
|
|
20
|
+
const { sendUploadRequest } = require('../../../unitTest/requests');
|
|
21
|
+
if (!token) {
|
|
22
|
+
output_1.default.exitError(texts_1.ERR_MISSING_UT_TOKEN);
|
|
23
|
+
}
|
|
24
|
+
const { glob, dryRun } = validateInputAndOptions(input, options);
|
|
25
|
+
const ciInfo = await getCiInfo();
|
|
26
|
+
const { absolutePattern, files } = findFilesByGlob(glob);
|
|
27
|
+
if (files.length === 0) {
|
|
28
|
+
output_1.default.exitError(`No files matched the provided glob: ${absolutePattern}`);
|
|
29
|
+
}
|
|
30
|
+
if (dryRun) {
|
|
31
|
+
output_1.default.normal(`Found ${files.length} report file(s) using pattern: ${absolutePattern}`);
|
|
32
|
+
files.forEach((file) => {
|
|
33
|
+
output_1.default.normal(file);
|
|
34
|
+
});
|
|
35
|
+
output_1.default.exitSuccess('Dry run completed');
|
|
36
|
+
}
|
|
37
|
+
await sendUploadRequest(files, ciInfo);
|
|
38
|
+
output_1.default.exitSuccess('Upload completed');
|
|
39
|
+
});
|
|
40
|
+
exports.default = commandUtUpload;
|
|
41
|
+
function validateInputAndOptions(input, options) {
|
|
42
|
+
const z = require('zod');
|
|
43
|
+
const { ZodError } = require('zod');
|
|
44
|
+
const globSchema = z.string();
|
|
45
|
+
const optionsSchema = z.object({
|
|
46
|
+
format: z.enum(['junit-xml']),
|
|
47
|
+
dryRun: z.boolean().optional(),
|
|
48
|
+
});
|
|
49
|
+
try {
|
|
50
|
+
const glob = globSchema.parse(input);
|
|
51
|
+
const { format, dryRun } = optionsSchema.parse(options);
|
|
52
|
+
return {
|
|
53
|
+
glob,
|
|
54
|
+
format,
|
|
55
|
+
dryRun,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof ZodError) {
|
|
60
|
+
output_1.default.exitError(error.errors.map((e) => `${e.path}: ${e.message}`).join(', '));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function findFilesByGlob(pattern) {
|
|
68
|
+
const { fdir } = require('fdir');
|
|
69
|
+
const picomatch = require('picomatch');
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
const scan = picomatch.scan(pattern);
|
|
72
|
+
if (!scan.isGlob) {
|
|
73
|
+
return {
|
|
74
|
+
absolutePattern: pattern,
|
|
75
|
+
files: (0, utils_1.isFile)(pattern) ? [pattern] : [],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (node_path_1.default.isAbsolute(pattern)) {
|
|
79
|
+
const root = scan.base;
|
|
80
|
+
const files = new fdir().withFullPaths().glob(pattern).crawl(root).sync();
|
|
81
|
+
return { absolutePattern: pattern, files };
|
|
82
|
+
}
|
|
83
|
+
const preparedPattern = node_path_1.default.resolve(cwd, pattern);
|
|
84
|
+
const files = new fdir().withFullPaths().glob(preparedPattern).crawl().sync();
|
|
85
|
+
return { absolutePattern: preparedPattern, files };
|
|
86
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
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 upload_1 = __importDefault(require("./unit/upload"));
|
|
9
|
+
const commandUnit = (0, utils_1.newCommand)('unit', texts_1.DESC_COMMAND_UNIT);
|
|
10
|
+
commandUnit.addCommand(upload_1.default);
|
|
11
|
+
exports.default = commandUnit;
|
|
@@ -0,0 +1,27 @@
|
|
|
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 output_1 = __importDefault(require("../../../../output"));
|
|
9
|
+
const commandSessionClose = (0, utils_1.newCommand)('close', texts_1.DESC_COMMAND_SESSION_CLOSE);
|
|
10
|
+
commandSessionClose.action(async () => {
|
|
11
|
+
const { checkBuildId, checkToken } = require('../../../../visualTest/validation');
|
|
12
|
+
const { closeSession } = require('../../../../visualTest/requests');
|
|
13
|
+
if (!checkToken('vt')) {
|
|
14
|
+
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
15
|
+
}
|
|
16
|
+
if (!checkBuildId()) {
|
|
17
|
+
output_1.default.exitError(texts_1.ERR_MISSING_BUILD_ID);
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const { message } = await closeSession();
|
|
21
|
+
output_1.default.exitNormal(message);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
output_1.default.exitError(`${error}`);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
exports.default = commandSessionClose;
|
|
@@ -0,0 +1,82 @@
|
|
|
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 output_1 = __importDefault(require("../../../../output"));
|
|
9
|
+
const commandSessionCreate = (0, utils_1.newCommand)('create', texts_1.DESC_COMMAND_SESSION_CREATE);
|
|
10
|
+
commandSessionCreate.argument('<command>', texts_1.OPTION_EXEC_COMMAND);
|
|
11
|
+
commandSessionCreate.option('--skipDiscovery', texts_1.OPTION_EXEC_SKIP_DISCOVERY);
|
|
12
|
+
commandSessionCreate.option('--oneByOne', texts_1.OPTION_EXEC_ONE_BY_ONE);
|
|
13
|
+
commandSessionCreate.option('--parallel', texts_1.OPTION_EXEC_PARALLEL);
|
|
14
|
+
commandSessionCreate.action(async (command, options) => {
|
|
15
|
+
const which = require('which');
|
|
16
|
+
const { getCiAndGitInfo, formattedCiInfo } = require('@buddy-works/ci-info');
|
|
17
|
+
const { checkParallel, checkToken } = require('../../../../visualTest/validation');
|
|
18
|
+
const { getDefaultSettings } = require('../../../../visualTest/requests');
|
|
19
|
+
const { debug, setBrowserPath, setCiAndCommitInfo, setExecOptions } = require('../../../../visualTest/context');
|
|
20
|
+
const { createServer } = require('../../../../visualTest/server');
|
|
21
|
+
const { finishProcessingSnapshots, setDefaultSettings, showSessionLink } = require('../../../../visualTest/snapshots');
|
|
22
|
+
const { testExec } = require('../../../../visualTest/exec');
|
|
23
|
+
const { getBrowserPath } = require('../../../../visualTest/browser');
|
|
24
|
+
setExecOptions(options);
|
|
25
|
+
try {
|
|
26
|
+
const browserPath = await getBrowserPath();
|
|
27
|
+
setBrowserPath(browserPath);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
output_1.default.exitError(`${error}`);
|
|
31
|
+
}
|
|
32
|
+
if (!checkToken('vt')) {
|
|
33
|
+
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
34
|
+
}
|
|
35
|
+
if (!checkParallel()) {
|
|
36
|
+
output_1.default.exitError(texts_1.ERR_MISSING_BUILD_ID);
|
|
37
|
+
}
|
|
38
|
+
const app = await createServer();
|
|
39
|
+
const [mainCommand, ...mainCommandArguments] = command.split(' ');
|
|
40
|
+
output_1.default.normal((0, texts_1.LOG_RUNNING_EXEC_COMMAND)(`${mainCommand} ${[...mainCommandArguments].join(' ')}`));
|
|
41
|
+
const resolved = await which(mainCommand, { nothrow: true });
|
|
42
|
+
if (!resolved) {
|
|
43
|
+
output_1.default.exitError((0, texts_1.ERR_MISSING_EXEC_COMMAND)(`${mainCommand} ${[...mainCommandArguments].join(' ')}`));
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
let t1, t11;
|
|
47
|
+
if (debug) {
|
|
48
|
+
t1 = performance.now();
|
|
49
|
+
}
|
|
50
|
+
const defaultSettings = await getDefaultSettings();
|
|
51
|
+
setDefaultSettings(defaultSettings);
|
|
52
|
+
const ciAndGitInfo = await getCiAndGitInfo({
|
|
53
|
+
baseBranch: defaultSettings.baseBranch,
|
|
54
|
+
logger: output_1.default.warning,
|
|
55
|
+
});
|
|
56
|
+
setCiAndCommitInfo(ciAndGitInfo);
|
|
57
|
+
output_1.default.normal(formattedCiInfo(ciAndGitInfo));
|
|
58
|
+
if (debug) {
|
|
59
|
+
t11 = performance.now();
|
|
60
|
+
}
|
|
61
|
+
const spawnedProcessExitCode = await testExec(mainCommand, [
|
|
62
|
+
...mainCommandArguments,
|
|
63
|
+
]);
|
|
64
|
+
if (debug && t11) {
|
|
65
|
+
const t22 = performance.now();
|
|
66
|
+
output_1.default.normal((0, texts_1.DEBUG_EXEC_TEST_COMMAND)(t22 - t11));
|
|
67
|
+
}
|
|
68
|
+
await app.close();
|
|
69
|
+
await finishProcessingSnapshots(spawnedProcessExitCode);
|
|
70
|
+
showSessionLink();
|
|
71
|
+
if (debug && t1) {
|
|
72
|
+
const t2 = performance.now();
|
|
73
|
+
output_1.default.normal((0, texts_1.DEBUG_EXEC_COMMAND)(t2 - t1));
|
|
74
|
+
}
|
|
75
|
+
process.exit(spawnedProcessExitCode);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
await app.close();
|
|
79
|
+
output_1.default.exitError(`${error}`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
exports.default = commandSessionCreate;
|
|
@@ -0,0 +1,13 @@
|
|
|
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 create_1 = __importDefault(require("./session/create"));
|
|
9
|
+
const close_1 = __importDefault(require("./session/close"));
|
|
10
|
+
const commandSession = (0, utils_1.newCommand)('session', texts_1.DESC_COMMAND_SESSION);
|
|
11
|
+
commandSession.addCommand(create_1.default);
|
|
12
|
+
commandSession.addCommand(close_1.default);
|
|
13
|
+
exports.default = commandSession;
|
|
@@ -0,0 +1,20 @@
|
|
|
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 output_1 = __importDefault(require("../../../output"));
|
|
9
|
+
const commandVisualSetup = (0, utils_1.newCommand)('setup', texts_1.DESC_COMMAND_VISUAL_SETUP);
|
|
10
|
+
commandVisualSetup.action(async () => {
|
|
11
|
+
try {
|
|
12
|
+
const { installBrowser } = require('../../../visualTest/browser');
|
|
13
|
+
await installBrowser();
|
|
14
|
+
output_1.default.exitNormal('');
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
output_1.default.exitError(`${error}`);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
exports.default = commandVisualSetup;
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
exports.waitForSchema = exports.headerSchema = exports.cookieSchema = exports.DEFAULT_SCOPE = void 0;
|
|
7
|
+
exports.parseScopedSelector = parseScopedSelector;
|
|
8
|
+
exports.parseScopedKeyValue = parseScopedKeyValue;
|
|
9
|
+
const zod_1 = require("zod");
|
|
10
|
+
const output_1 = __importDefault(require("../../../../output"));
|
|
11
|
+
exports.DEFAULT_SCOPE = '**';
|
|
12
|
+
function parseScopedSelector(value) {
|
|
13
|
+
return value?.map((v) => {
|
|
14
|
+
let scope, type, selectorValue;
|
|
15
|
+
if (v.includes('::CSS=') || v.includes('::XPATH=')) {
|
|
16
|
+
const [scopePart, ...rest] = v.split('::');
|
|
17
|
+
const [typePart, ...valuePart] = rest.join('::').split('=');
|
|
18
|
+
type = typePart;
|
|
19
|
+
selectorValue = valuePart.join('=');
|
|
20
|
+
scope = scopePart;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const [typePart, ...valuePart] = v.split('=');
|
|
24
|
+
type = typePart;
|
|
25
|
+
selectorValue = valuePart.join('=');
|
|
26
|
+
scope = exports.DEFAULT_SCOPE;
|
|
27
|
+
}
|
|
28
|
+
return { scope, type, value: selectorValue };
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function parseScopedKeyValue(rawValue) {
|
|
32
|
+
let scope = exports.DEFAULT_SCOPE;
|
|
33
|
+
let keyValue = rawValue;
|
|
34
|
+
const scopeSeparatorIndex = rawValue.indexOf('::');
|
|
35
|
+
if (scopeSeparatorIndex >= 0) {
|
|
36
|
+
scope = rawValue.slice(0, scopeSeparatorIndex).trim();
|
|
37
|
+
keyValue = rawValue.slice(scopeSeparatorIndex + 2).trim();
|
|
38
|
+
}
|
|
39
|
+
const equalSignIndex = keyValue.indexOf('=');
|
|
40
|
+
if (equalSignIndex <= 0) {
|
|
41
|
+
output_1.default.exitError("Option value must follow pattern '[scope::]key=value' (scope is optional)");
|
|
42
|
+
}
|
|
43
|
+
const key = keyValue.slice(0, equalSignIndex).trim();
|
|
44
|
+
const value = keyValue.slice(equalSignIndex + 1).trim();
|
|
45
|
+
if (!key) {
|
|
46
|
+
output_1.default.exitError('Option key cannot be empty');
|
|
47
|
+
}
|
|
48
|
+
return { scope, key, value };
|
|
49
|
+
}
|
|
50
|
+
exports.cookieSchema = zod_1.z
|
|
51
|
+
.array(zod_1.z
|
|
52
|
+
.string()
|
|
53
|
+
.max(4096, {
|
|
54
|
+
message: 'Cookie must be less than 4096 characters',
|
|
55
|
+
})
|
|
56
|
+
.regex(/^(?:([^:]+)::)?([^=]+)=(.*)$/, {
|
|
57
|
+
message: "Cookie option must follow pattern '[scope::]key=value[;attribute]' (scope is optional)",
|
|
58
|
+
}))
|
|
59
|
+
.optional()
|
|
60
|
+
.transform((value) => value?.map((v) => {
|
|
61
|
+
let scope = exports.DEFAULT_SCOPE;
|
|
62
|
+
let cookieValue = v;
|
|
63
|
+
if (v.includes('::')) {
|
|
64
|
+
const [scopePart, valuePart] = v.split('::');
|
|
65
|
+
scope = scopePart.trim();
|
|
66
|
+
cookieValue = valuePart.trim();
|
|
67
|
+
}
|
|
68
|
+
const cookieParts = cookieValue.split(';').map((part) => part.trim());
|
|
69
|
+
const mainPart = cookieParts[0];
|
|
70
|
+
const firstEqualSignIndex = mainPart.indexOf('=');
|
|
71
|
+
const key = mainPart.slice(0, firstEqualSignIndex).trim();
|
|
72
|
+
const value = mainPart.slice(firstEqualSignIndex + 1).trim();
|
|
73
|
+
const cookie = {
|
|
74
|
+
scope,
|
|
75
|
+
key,
|
|
76
|
+
value,
|
|
77
|
+
httpOnly: false,
|
|
78
|
+
secure: false,
|
|
79
|
+
};
|
|
80
|
+
for (let i = 1; i < cookieParts.length; i++) {
|
|
81
|
+
const part = cookieParts[i].toLowerCase();
|
|
82
|
+
if (part === 'httponly') {
|
|
83
|
+
cookie.httpOnly = true;
|
|
84
|
+
}
|
|
85
|
+
else if (part === 'secure') {
|
|
86
|
+
cookie.secure = true;
|
|
87
|
+
}
|
|
88
|
+
else if (part.startsWith('domain=')) {
|
|
89
|
+
cookie.domain = part.substring(7);
|
|
90
|
+
}
|
|
91
|
+
else if (part.startsWith('path=')) {
|
|
92
|
+
cookie.path = part.substring(5);
|
|
93
|
+
}
|
|
94
|
+
else if (part.startsWith('samesite=')) {
|
|
95
|
+
const sameSiteValue = part.substring(9);
|
|
96
|
+
if (['strict', 'lax', 'none'].includes(sameSiteValue)) {
|
|
97
|
+
cookie.sameSite = (sameSiteValue.charAt(0).toUpperCase() +
|
|
98
|
+
sameSiteValue.slice(1));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return cookie;
|
|
103
|
+
}));
|
|
104
|
+
exports.headerSchema = zod_1.z
|
|
105
|
+
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?([^=]+)=(.*)$/, {
|
|
106
|
+
message: "Header option must follow pattern '[scope::]key=value' (scope is optional)",
|
|
107
|
+
}))
|
|
108
|
+
.optional()
|
|
109
|
+
.transform((value) => value?.map((v) => {
|
|
110
|
+
const { scope, key, value } = parseScopedKeyValue(v);
|
|
111
|
+
return { scope, key, value };
|
|
112
|
+
}));
|
|
113
|
+
exports.waitForSchema = zod_1.z
|
|
114
|
+
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?(?:(CSS|XPATH))=(.+)$/, {
|
|
115
|
+
message: "WaitFor option must follow pattern '[scope::]type=value' where type must be CSS or XPATH (scope is optional)",
|
|
116
|
+
}))
|
|
117
|
+
.optional()
|
|
118
|
+
.transform(parseScopedSelector);
|
|
@@ -0,0 +1,138 @@
|
|
|
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 output_1 = __importDefault(require("../../../output"));
|
|
9
|
+
const node_fs_1 = require("node:fs");
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const node_zlib_1 = require("node:zlib");
|
|
12
|
+
const commandVisualUpload = (0, utils_1.newCommand)('upload', texts_1.DESC_COMMAND_VISUAL_UPLOAD);
|
|
13
|
+
commandVisualUpload.action(async () => {
|
|
14
|
+
const { getCiAndGitInfo, formattedCiInfo } = require('@buddy-works/ci-info');
|
|
15
|
+
const { checkToken } = require('../../../visualTest/validation');
|
|
16
|
+
const { getDefaultSettings, sendStorybook } = require('../../../visualTest/requests');
|
|
17
|
+
const { setDefaultSettings } = require('../../../visualTest/snapshots');
|
|
18
|
+
const { setCiAndCommitInfo } = require('../../../visualTest/context');
|
|
19
|
+
if (!checkToken('vt')) {
|
|
20
|
+
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
21
|
+
}
|
|
22
|
+
const currentDirectoryFiles = getCurrentDirectoryFiles();
|
|
23
|
+
if (!isStorybookDirectory(currentDirectoryFiles)) {
|
|
24
|
+
output_1.default.exitError(texts_1.ERR_WRONG_STORYBOOK_DIRECTORY);
|
|
25
|
+
}
|
|
26
|
+
const storybookStoriesIndex = getStorybookStoriesIndex(currentDirectoryFiles);
|
|
27
|
+
const storiesList = getStoriesList(storybookStoriesIndex);
|
|
28
|
+
const storybookSnapshots = getStorybookSnapshots(storiesList);
|
|
29
|
+
const defaultSettings = await getDefaultSettings();
|
|
30
|
+
setDefaultSettings(defaultSettings);
|
|
31
|
+
const ciAndGitInfo = await getCiAndGitInfo({
|
|
32
|
+
baseBranch: defaultSettings.baseBranch,
|
|
33
|
+
logger: output_1.default.warning,
|
|
34
|
+
});
|
|
35
|
+
setCiAndCommitInfo(ciAndGitInfo);
|
|
36
|
+
output_1.default.normal(formattedCiInfo(ciAndGitInfo));
|
|
37
|
+
try {
|
|
38
|
+
const compressedStorybookDirectory = await createCompressedStorybookDirectory(currentDirectoryFiles);
|
|
39
|
+
const { message } = await sendStorybook(storybookSnapshots, compressedStorybookDirectory);
|
|
40
|
+
output_1.default.exitSuccess(message);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
output_1.default.exitError(`${error}`);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
function getCurrentDirectoryFiles() {
|
|
47
|
+
const cwd = process.cwd();
|
|
48
|
+
const filesAndDirectories = (0, node_fs_1.readdirSync)(cwd, {
|
|
49
|
+
encoding: 'utf8',
|
|
50
|
+
recursive: true,
|
|
51
|
+
});
|
|
52
|
+
return filesAndDirectories.filter((file) => {
|
|
53
|
+
const elementPath = node_path_1.default.join(cwd, file);
|
|
54
|
+
const stats = (0, node_fs_1.statSync)(elementPath);
|
|
55
|
+
return stats.isFile();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function createCompressedStorybookDirectory(files) {
|
|
59
|
+
const tar = require('tar-stream');
|
|
60
|
+
const cwd = process.cwd();
|
|
61
|
+
const chunks = [];
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const compressStream = (0, node_zlib_1.createBrotliCompress)({
|
|
64
|
+
params: {
|
|
65
|
+
[node_zlib_1.constants.BROTLI_PARAM_QUALITY]: 6,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
compressStream.on('data', (chunk) => {
|
|
69
|
+
chunks.push(chunk);
|
|
70
|
+
});
|
|
71
|
+
compressStream.on('end', () => {
|
|
72
|
+
resolve(Buffer.concat(chunks));
|
|
73
|
+
});
|
|
74
|
+
compressStream.on('error', reject);
|
|
75
|
+
const packStream = tar.pack();
|
|
76
|
+
packStream.pipe(compressStream);
|
|
77
|
+
let filesProcessed = 0;
|
|
78
|
+
for (const file of files) {
|
|
79
|
+
const filePath = node_path_1.default.join(cwd, file);
|
|
80
|
+
const stats = (0, node_fs_1.statSync)(filePath);
|
|
81
|
+
const entry = packStream.entry({
|
|
82
|
+
name: file,
|
|
83
|
+
size: stats.size,
|
|
84
|
+
}, (error) => {
|
|
85
|
+
if (error) {
|
|
86
|
+
reject(error);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
filesProcessed += 1;
|
|
90
|
+
if (filesProcessed === files.length) {
|
|
91
|
+
packStream.finalize();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
const fileStream = (0, node_fs_1.createReadStream)(filePath);
|
|
96
|
+
fileStream.pipe(entry);
|
|
97
|
+
fileStream.on('error', reject);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function isStorybookDirectory(files) {
|
|
102
|
+
return (files.length > 0 &&
|
|
103
|
+
files.includes('index.html') &&
|
|
104
|
+
files.includes('iframe.html'));
|
|
105
|
+
}
|
|
106
|
+
function getStorybookStoriesIndex(files) {
|
|
107
|
+
const indexFiles = files.find((file) => file === 'index.json');
|
|
108
|
+
if (indexFiles) {
|
|
109
|
+
return indexFiles;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return output_1.default.exitError(texts_1.ERR_MISSING_STORYBOOK_INDEX_FILE);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function getStoriesList(storybookStoriesIndex) {
|
|
116
|
+
const storiesListFile = (0, node_fs_1.readFileSync)(storybookStoriesIndex);
|
|
117
|
+
try {
|
|
118
|
+
const json = JSON.parse(storiesListFile.toString());
|
|
119
|
+
if (![4, 5].includes(json.v)) {
|
|
120
|
+
output_1.default.exitError(texts_1.ERR_UNSUPPORTED_STORYBOOK);
|
|
121
|
+
}
|
|
122
|
+
return json;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
output_1.default.exitError(texts_1.ERR_PARSING_STORIES);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function getStorybookSnapshots(storiesList) {
|
|
129
|
+
const stories = Object.entries(storiesList.entries)
|
|
130
|
+
.filter(([, value]) => value.type === 'story')
|
|
131
|
+
.map(([key, value]) => ({
|
|
132
|
+
id: key,
|
|
133
|
+
name: `${value.title}/${value.name}`,
|
|
134
|
+
}));
|
|
135
|
+
output_1.default.normal((0, texts_1.TXT_STORIES_AMOUNT)(stories.length));
|
|
136
|
+
return stories;
|
|
137
|
+
}
|
|
138
|
+
exports.default = commandVisualUpload;
|
|
@@ -0,0 +1,15 @@
|
|
|
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 setup_1 = __importDefault(require("./visual/setup"));
|
|
9
|
+
const upload_1 = __importDefault(require("./visual/upload"));
|
|
10
|
+
const session_1 = __importDefault(require("./visual/session"));
|
|
11
|
+
const commandVisual = (0, utils_1.newCommand)('visual', texts_1.DESC_COMMAND_VISUAL);
|
|
12
|
+
commandVisual.addCommand(setup_1.default);
|
|
13
|
+
commandVisual.addCommand(upload_1.default);
|
|
14
|
+
commandVisual.addCommand(session_1.default);
|
|
15
|
+
exports.default = commandVisual;
|
|
@@ -0,0 +1,15 @@
|
|
|
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 unit_1 = __importDefault(require("./tests/unit"));
|
|
9
|
+
const visual_1 = __importDefault(require("./tests/visual"));
|
|
10
|
+
const capture_1 = __importDefault(require("./tests/capture"));
|
|
11
|
+
const commandTests = (0, utils_1.newCommand)('tests', texts_1.DESC_COMMAND_TESTS);
|
|
12
|
+
commandTests.addCommand(unit_1.default);
|
|
13
|
+
commandTests.addCommand(visual_1.default);
|
|
14
|
+
commandTests.addCommand(capture_1.default);
|
|
15
|
+
exports.default = commandTests;
|
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -7,7 +40,12 @@ const utils_1 = require("../../utils");
|
|
|
7
40
|
const texts_1 = require("../../texts");
|
|
8
41
|
const output_1 = __importDefault(require("../../output"));
|
|
9
42
|
const commander_1 = require("commander");
|
|
43
|
+
const zod_1 = __importStar(require("zod"));
|
|
44
|
+
const fdir_1 = require("fdir");
|
|
45
|
+
const picomatch_1 = __importDefault(require("picomatch"));
|
|
10
46
|
const node_path_1 = __importDefault(require("node:path"));
|
|
47
|
+
const ci_1 = require("../../unitTest/ci");
|
|
48
|
+
const requests_1 = require("../../unitTest/requests");
|
|
11
49
|
const token = process.env.BUDDY_UT_TOKEN || '';
|
|
12
50
|
const commandUtUpload = (0, utils_1.newCommand)('upload', texts_1.DESC_COMMAND_UT_UPLOAD);
|
|
13
51
|
commandUtUpload.argument('<glob>', texts_1.OPTION_UPLOAD_REPORT_GLOB);
|
|
@@ -16,13 +54,11 @@ commandUtUpload.addOption(new commander_1.Option('--format <format>', texts_1.OP
|
|
|
16
54
|
.makeOptionMandatory());
|
|
17
55
|
commandUtUpload.option('--dryRun', texts_1.OPTION_UPLOAD_DRY_RUN);
|
|
18
56
|
commandUtUpload.action(async (input, options) => {
|
|
19
|
-
const { getCiInfo } = require('../../unitTest/ci');
|
|
20
|
-
const { sendUploadRequest } = require('../../unitTest/requests');
|
|
21
57
|
if (!token) {
|
|
22
58
|
output_1.default.exitError(texts_1.ERR_MISSING_UT_TOKEN);
|
|
23
59
|
}
|
|
24
60
|
const { glob, dryRun } = validateInputAndOptions(input, options);
|
|
25
|
-
const ciInfo = await getCiInfo();
|
|
61
|
+
const ciInfo = await (0, ci_1.getCiInfo)();
|
|
26
62
|
const { absolutePattern, files } = findFilesByGlob(glob);
|
|
27
63
|
if (files.length === 0) {
|
|
28
64
|
output_1.default.exitError(`No files matched the provided glob: ${absolutePattern}`);
|
|
@@ -34,17 +70,15 @@ commandUtUpload.action(async (input, options) => {
|
|
|
34
70
|
});
|
|
35
71
|
output_1.default.exitSuccess('Dry run completed');
|
|
36
72
|
}
|
|
37
|
-
await sendUploadRequest(files, ciInfo);
|
|
73
|
+
await (0, requests_1.sendUploadRequest)(files, ciInfo);
|
|
38
74
|
output_1.default.exitSuccess('Upload completed');
|
|
39
75
|
});
|
|
40
76
|
exports.default = commandUtUpload;
|
|
41
77
|
function validateInputAndOptions(input, options) {
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
format: z.enum(['junit-xml']),
|
|
47
|
-
dryRun: z.boolean().optional(),
|
|
78
|
+
const globSchema = zod_1.default.string();
|
|
79
|
+
const optionsSchema = zod_1.default.object({
|
|
80
|
+
format: zod_1.default.enum(['junit-xml']),
|
|
81
|
+
dryRun: zod_1.default.boolean().optional(),
|
|
48
82
|
});
|
|
49
83
|
try {
|
|
50
84
|
const glob = globSchema.parse(input);
|
|
@@ -56,7 +90,7 @@ function validateInputAndOptions(input, options) {
|
|
|
56
90
|
};
|
|
57
91
|
}
|
|
58
92
|
catch (error) {
|
|
59
|
-
if (error instanceof ZodError) {
|
|
93
|
+
if (error instanceof zod_1.ZodError) {
|
|
60
94
|
output_1.default.exitError(error.errors.map((e) => `${e.path}: ${e.message}`).join(', '));
|
|
61
95
|
}
|
|
62
96
|
else {
|
|
@@ -65,10 +99,8 @@ function validateInputAndOptions(input, options) {
|
|
|
65
99
|
}
|
|
66
100
|
}
|
|
67
101
|
function findFilesByGlob(pattern) {
|
|
68
|
-
const { fdir } = require('fdir');
|
|
69
|
-
const picomatch = require('picomatch');
|
|
70
102
|
const cwd = process.cwd();
|
|
71
|
-
const scan =
|
|
103
|
+
const scan = picomatch_1.default.scan(pattern);
|
|
72
104
|
if (!scan.isGlob) {
|
|
73
105
|
return {
|
|
74
106
|
absolutePattern: pattern,
|
|
@@ -77,10 +109,10 @@ function findFilesByGlob(pattern) {
|
|
|
77
109
|
}
|
|
78
110
|
if (node_path_1.default.isAbsolute(pattern)) {
|
|
79
111
|
const root = scan.base;
|
|
80
|
-
const files = new fdir().withFullPaths().glob(pattern).crawl(root).sync();
|
|
112
|
+
const files = new fdir_1.fdir().withFullPaths().glob(pattern).crawl(root).sync();
|
|
81
113
|
return { absolutePattern: pattern, files };
|
|
82
114
|
}
|
|
83
115
|
const preparedPattern = node_path_1.default.resolve(cwd, pattern);
|
|
84
|
-
const files = new fdir().withFullPaths().glob(preparedPattern).crawl().sync();
|
|
116
|
+
const files = new fdir_1.fdir().withFullPaths().glob(preparedPattern).crawl().sync();
|
|
85
117
|
return { absolutePattern: preparedPattern, files };
|
|
86
118
|
}
|