@verdaccio/e2e-cli 2.1.0 → 2.2.0
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/build/adapters/adapter.d.ts +1 -0
- package/build/adapters/index.d.ts +4 -0
- package/build/adapters/npm.d.ts +2 -0
- package/build/adapters/pnpm.d.ts +2 -0
- package/build/adapters/yarn-classic.d.ts +2 -0
- package/build/adapters/yarn-modern.d.ts +2 -0
- package/build/cjs/_virtual/_rolldown/runtime.cjs +23 -0
- package/build/cjs/adapters/index.cjs +4 -0
- package/build/cjs/adapters/npm.cjs +78 -0
- package/build/cjs/adapters/npm.cjs.map +1 -0
- package/build/cjs/adapters/pnpm.cjs +78 -0
- package/build/cjs/adapters/pnpm.cjs.map +1 -0
- package/build/cjs/adapters/yarn-classic.cjs +96 -0
- package/build/cjs/adapters/yarn-classic.cjs.map +1 -0
- package/build/cjs/adapters/yarn-modern.cjs +133 -0
- package/build/cjs/adapters/yarn-modern.cjs.map +1 -0
- package/build/cjs/index.cjs +152 -0
- package/build/cjs/index.cjs.map +1 -0
- package/build/cjs/reporter.cjs +60 -0
- package/build/cjs/reporter.cjs.map +1 -0
- package/build/cjs/runner.cjs +102 -0
- package/build/cjs/runner.cjs.map +1 -0
- package/build/cjs/tests/audit.cjs +27 -0
- package/build/cjs/tests/audit.cjs.map +1 -0
- package/build/cjs/tests/deprecate.cjs +67 -0
- package/build/cjs/tests/deprecate.cjs.map +1 -0
- package/build/cjs/tests/dist-tags.cjs +43 -0
- package/build/cjs/tests/dist-tags.cjs.map +1 -0
- package/build/cjs/tests/index.cjs +27 -0
- package/build/cjs/tests/index.cjs.map +1 -0
- package/build/cjs/tests/info.cjs +38 -0
- package/build/cjs/tests/info.cjs.map +1 -0
- package/build/cjs/tests/install.cjs +28 -0
- package/build/cjs/tests/install.cjs.map +1 -0
- package/build/cjs/tests/ping.cjs +18 -0
- package/build/cjs/tests/ping.cjs.map +1 -0
- package/build/cjs/tests/publish.cjs +34 -0
- package/build/cjs/tests/publish.cjs.map +1 -0
- package/build/cjs/tests/search.cjs +19 -0
- package/build/cjs/tests/search.cjs.map +1 -0
- package/build/cjs/tests/star.cjs +27 -0
- package/build/cjs/tests/star.cjs.map +1 -0
- package/build/cjs/tests/unpublish.cjs +40 -0
- package/build/cjs/tests/unpublish.cjs.map +1 -0
- package/build/cjs/utils/process.cjs +85 -0
- package/build/cjs/utils/process.cjs.map +1 -0
- package/build/cjs/utils/project.cjs +55 -0
- package/build/cjs/utils/project.cjs.map +1 -0
- package/build/cjs/utils/registry-client.cjs +61 -0
- package/build/cjs/utils/registry-client.cjs.map +1 -0
- package/build/esm/adapters/index.js +5 -0
- package/build/esm/adapters/npm.js +76 -0
- package/build/esm/adapters/npm.js.map +1 -0
- package/build/esm/adapters/pnpm.js +76 -0
- package/build/esm/adapters/pnpm.js.map +1 -0
- package/build/esm/adapters/yarn-classic.js +94 -0
- package/build/esm/adapters/yarn-classic.js.map +1 -0
- package/build/esm/adapters/yarn-modern.js +130 -0
- package/build/esm/adapters/yarn-modern.js.map +1 -0
- package/build/esm/index.js +142 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/reporter.js +56 -0
- package/build/esm/reporter.js.map +1 -0
- package/build/esm/runner.js +99 -0
- package/build/esm/runner.js.map +1 -0
- package/build/esm/tests/audit.js +25 -0
- package/build/esm/tests/audit.js.map +1 -0
- package/build/esm/tests/deprecate.js +65 -0
- package/build/esm/tests/deprecate.js.map +1 -0
- package/build/esm/tests/dist-tags.js +41 -0
- package/build/esm/tests/dist-tags.js.map +1 -0
- package/build/esm/tests/index.js +27 -0
- package/build/esm/tests/index.js.map +1 -0
- package/build/esm/tests/info.js +36 -0
- package/build/esm/tests/info.js.map +1 -0
- package/build/esm/tests/install.js +26 -0
- package/build/esm/tests/install.js.map +1 -0
- package/build/esm/tests/ping.js +16 -0
- package/build/esm/tests/ping.js.map +1 -0
- package/build/esm/tests/publish.js +32 -0
- package/build/esm/tests/publish.js.map +1 -0
- package/build/esm/tests/search.js +17 -0
- package/build/esm/tests/search.js.map +1 -0
- package/build/esm/tests/star.js +25 -0
- package/build/esm/tests/star.js.map +1 -0
- package/build/esm/tests/unpublish.js +38 -0
- package/build/esm/tests/unpublish.js.map +1 -0
- package/build/esm/utils/process.js +82 -0
- package/build/esm/utils/process.js.map +1 -0
- package/build/esm/utils/project.js +50 -0
- package/build/esm/utils/project.js.map +1 -0
- package/build/esm/utils/registry-client.js +57 -0
- package/build/esm/utils/registry-client.js.map +1 -0
- package/build/index.d.ts +5 -0
- package/build/reporter.d.ts +6 -0
- package/build/runner.d.ts +13 -0
- package/build/tests/audit.d.ts +2 -0
- package/build/tests/deprecate.d.ts +2 -0
- package/build/tests/dist-tags.d.ts +2 -0
- package/build/tests/index.d.ts +13 -0
- package/build/tests/info.d.ts +2 -0
- package/build/tests/install.d.ts +2 -0
- package/build/tests/ping.d.ts +2 -0
- package/build/tests/publish.d.ts +2 -0
- package/build/tests/search.d.ts +2 -0
- package/build/tests/star.d.ts +2 -0
- package/build/tests/unpublish.d.ts +2 -0
- package/build/types.d.ts +65 -0
- package/build/utils/index.d.ts +3 -0
- package/build/utils/process.d.ts +5 -0
- package/build/utils/project.d.ts +6 -0
- package/build/utils/registry-client.d.ts +14 -0
- package/package.json +1 -1
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { exec } from "../utils/process.js";
|
|
2
|
+
import { createTempFolder, getPackageJSON, getREADME } from "../utils/project.js";
|
|
3
|
+
import buildDebug from "debug";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { writeFile } from "fs/promises";
|
|
7
|
+
import YAML from "js-yaml";
|
|
8
|
+
import { URL } from "url";
|
|
9
|
+
//#region src/adapters/yarn-modern.ts
|
|
10
|
+
var debug = buildDebug("verdaccio:e2e-cli:yarn-modern");
|
|
11
|
+
var YARN_MODERN_SUPPORTED_COMMANDS = new Set([
|
|
12
|
+
"publish",
|
|
13
|
+
"install",
|
|
14
|
+
"info"
|
|
15
|
+
]);
|
|
16
|
+
function detectVersion(bin) {
|
|
17
|
+
try {
|
|
18
|
+
return execSync(`${bin} --version`, {
|
|
19
|
+
env: {
|
|
20
|
+
...process.env,
|
|
21
|
+
COREPACK_ENABLE_STRICT: "0"
|
|
22
|
+
},
|
|
23
|
+
encoding: "utf8",
|
|
24
|
+
timeout: 5e3
|
|
25
|
+
}).trim();
|
|
26
|
+
} catch {
|
|
27
|
+
return "unknown";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function installYarnModern(version = "4") {
|
|
31
|
+
const pkg = `@yarnpkg/cli-dist@${version}`;
|
|
32
|
+
debug("installing %s into temp dir", pkg);
|
|
33
|
+
const tmpDir = execSync("mktemp -d", { encoding: "utf8" }).trim();
|
|
34
|
+
execSync(`npm install --prefix "${tmpDir}" ${pkg} --loglevel=error`, {
|
|
35
|
+
encoding: "utf8",
|
|
36
|
+
timeout: 3e4
|
|
37
|
+
});
|
|
38
|
+
const bin = `${tmpDir}/node_modules/@yarnpkg/cli-dist/bin/yarn.js`;
|
|
39
|
+
const installed = detectVersion(bin);
|
|
40
|
+
debug("installed yarn modern %s at %s", installed, bin);
|
|
41
|
+
console.log(` Auto-installed yarn modern ${installed}`);
|
|
42
|
+
return bin;
|
|
43
|
+
}
|
|
44
|
+
function resolveYarnBin(binPath, version) {
|
|
45
|
+
if (binPath) return binPath;
|
|
46
|
+
if (version) return installYarnModern(version);
|
|
47
|
+
try {
|
|
48
|
+
const systemYarn = execSync("which yarn", {
|
|
49
|
+
encoding: "utf8",
|
|
50
|
+
timeout: 5e3
|
|
51
|
+
}).trim();
|
|
52
|
+
const sysVersion = detectVersion(systemYarn);
|
|
53
|
+
if (parseInt(sysVersion.split(".")[0], 10) >= 2) {
|
|
54
|
+
debug("using system yarn Berry %s", sysVersion);
|
|
55
|
+
return systemYarn;
|
|
56
|
+
}
|
|
57
|
+
debug("system yarn is Classic %s, auto-installing Berry", sysVersion);
|
|
58
|
+
} catch {
|
|
59
|
+
debug("no system yarn found, auto-installing Berry");
|
|
60
|
+
}
|
|
61
|
+
return installYarnModern();
|
|
62
|
+
}
|
|
63
|
+
function createYamlConfig(registry, token) {
|
|
64
|
+
const defaultYaml = {
|
|
65
|
+
npmRegistryServer: registry,
|
|
66
|
+
enableImmutableInstalls: false,
|
|
67
|
+
unsafeHttpWhitelist: ["localhost"]
|
|
68
|
+
};
|
|
69
|
+
if (typeof token === "string") {
|
|
70
|
+
const url = new URL(registry);
|
|
71
|
+
defaultYaml.npmRegistries = { [`//${url.hostname}:${url.port}`]: {
|
|
72
|
+
npmAlwaysAuth: true,
|
|
73
|
+
npmAuthToken: token
|
|
74
|
+
} };
|
|
75
|
+
}
|
|
76
|
+
return YAML.dump(defaultYaml);
|
|
77
|
+
}
|
|
78
|
+
function createYarnModernAdapter(binPath, version) {
|
|
79
|
+
const bin = resolveYarnBin(binPath, version);
|
|
80
|
+
const resolved = detectVersion(bin);
|
|
81
|
+
debug("creating yarn modern adapter with bin: %s (%s)", bin, resolved);
|
|
82
|
+
return {
|
|
83
|
+
name: `yarn-modern@${resolved}`,
|
|
84
|
+
type: "yarn-modern",
|
|
85
|
+
bin,
|
|
86
|
+
supports: YARN_MODERN_SUPPORTED_COMMANDS,
|
|
87
|
+
registryArg(_url) {
|
|
88
|
+
return [];
|
|
89
|
+
},
|
|
90
|
+
prefixArg(_folder) {
|
|
91
|
+
return [];
|
|
92
|
+
},
|
|
93
|
+
exec(options, ...args) {
|
|
94
|
+
const env = {
|
|
95
|
+
...process.env,
|
|
96
|
+
...options.env,
|
|
97
|
+
COREPACK_ENABLE_STRICT: "0"
|
|
98
|
+
};
|
|
99
|
+
const cmd = args[0];
|
|
100
|
+
let yarnArgs;
|
|
101
|
+
if (cmd === "publish") yarnArgs = [
|
|
102
|
+
"npm",
|
|
103
|
+
"publish",
|
|
104
|
+
...args.slice(1).filter((a) => a !== "--json" && !a.startsWith("--registry"))
|
|
105
|
+
];
|
|
106
|
+
else if (cmd === "info") yarnArgs = [
|
|
107
|
+
"npm",
|
|
108
|
+
"info",
|
|
109
|
+
...args.slice(1).filter((a) => !a.startsWith("--registry"))
|
|
110
|
+
];
|
|
111
|
+
else yarnArgs = args.filter((a) => !a.startsWith("--registry"));
|
|
112
|
+
return exec({
|
|
113
|
+
...options,
|
|
114
|
+
env
|
|
115
|
+
}, bin, yarnArgs);
|
|
116
|
+
},
|
|
117
|
+
async prepareProject(packageName, version, registryUrl, _port, token, dependencies = {}, devDependencies = {}) {
|
|
118
|
+
const tempFolder = await createTempFolder(packageName);
|
|
119
|
+
const yamlContent = createYamlConfig(registryUrl, token);
|
|
120
|
+
await writeFile(join(tempFolder, ".yarnrc.yml"), yamlContent);
|
|
121
|
+
await writeFile(join(tempFolder, "package.json"), getPackageJSON(packageName, version, dependencies, devDependencies));
|
|
122
|
+
await writeFile(join(tempFolder, "README.md"), getREADME(packageName));
|
|
123
|
+
return { tempFolder };
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
export { createYarnModernAdapter };
|
|
129
|
+
|
|
130
|
+
//# sourceMappingURL=yarn-modern.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yarn-modern.js","names":[],"sources":["../../../src/adapters/yarn-modern.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\nimport { writeFile } from 'fs/promises';\nimport YAML from 'js-yaml';\nimport { join } from 'path';\nimport { URL } from 'url';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { createTempFolder, getPackageJSON, getREADME } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:yarn-modern');\n\nconst YARN_MODERN_SUPPORTED_COMMANDS = new Set(['publish', 'install', 'info']);\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, {\n env: { ...process.env, COREPACK_ENABLE_STRICT: '0' },\n encoding: 'utf8',\n timeout: 5000,\n }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction installYarnModern(version = '4'): string {\n const pkg = `@yarnpkg/cli-dist@${version}`;\n debug('installing %s into temp dir', pkg);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n execSync(`npm install --prefix \"${tmpDir}\" ${pkg} --loglevel=error`, {\n encoding: 'utf8',\n timeout: 30000,\n });\n const bin = `${tmpDir}/node_modules/@yarnpkg/cli-dist/bin/yarn.js`;\n const installed = detectVersion(bin);\n debug('installed yarn modern %s at %s', installed, bin);\n console.log(` Auto-installed yarn modern ${installed}`);\n return bin;\n}\n\nfunction resolveYarnBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n\n // Always install the requested version to ensure reproducibility\n if (version) {\n return installYarnModern(version);\n }\n\n // Check if system yarn is Berry (2+)\n try {\n const systemYarn = execSync('which yarn', { encoding: 'utf8', timeout: 5000 }).trim();\n const sysVersion = detectVersion(systemYarn);\n const major = parseInt(sysVersion.split('.')[0], 10);\n if (major >= 2) {\n debug('using system yarn Berry %s', sysVersion);\n return systemYarn;\n }\n debug('system yarn is Classic %s, auto-installing Berry', sysVersion);\n } catch {\n debug('no system yarn found, auto-installing Berry');\n }\n\n return installYarnModern();\n}\n\nfunction createYamlConfig(registry: string, token?: string) {\n const defaultYaml: any = {\n npmRegistryServer: registry,\n enableImmutableInstalls: false,\n unsafeHttpWhitelist: ['localhost'],\n };\n\n if (typeof token === 'string') {\n const url = new URL(registry);\n defaultYaml.npmRegistries = {\n [`//${url.hostname}:${url.port}`]: {\n npmAlwaysAuth: true,\n npmAuthToken: token,\n },\n };\n }\n\n return YAML.dump(defaultYaml);\n}\n\nexport function createYarnModernAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolveYarnBin(binPath, version);\n const resolved = detectVersion(bin);\n debug('creating yarn modern adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `yarn-modern@${resolved}`,\n type: 'yarn-modern',\n bin,\n supports: YARN_MODERN_SUPPORTED_COMMANDS,\n\n registryArg(_url: string): string[] {\n return [];\n },\n\n prefixArg(_folder: string): string[] {\n return [];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n const env = { ...process.env, ...options.env, COREPACK_ENABLE_STRICT: '0' };\n\n const cmd = args[0];\n let yarnArgs: string[];\n if (cmd === 'publish') {\n const filtered = args.slice(1).filter(\n (a) => a !== '--json' && !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'publish', ...filtered];\n } else if (cmd === 'info') {\n const filtered = args.slice(1).filter((a) => !a.startsWith('--registry'));\n yarnArgs = ['npm', 'info', ...filtered];\n } else {\n yarnArgs = args.filter((a) => !a.startsWith('--registry'));\n }\n\n return exec({ ...options, env }, bin, yarnArgs);\n },\n\n async prepareProject(\n packageName: string,\n version: string,\n registryUrl: string,\n _port: number,\n token: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n ): Promise<{ tempFolder: string }> {\n const tempFolder = await createTempFolder(packageName);\n const yamlContent = createYamlConfig(registryUrl, token);\n await writeFile(join(tempFolder, '.yarnrc.yml'), yamlContent);\n await writeFile(\n join(tempFolder, 'package.json'),\n getPackageJSON(packageName, version, dependencies, devDependencies)\n );\n await writeFile(join(tempFolder, 'README.md'), getREADME(packageName));\n return { tempFolder };\n },\n };\n\n return adapter;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { createNpmAdapter } from "./adapters/npm.js";
|
|
2
|
+
import { createPnpmAdapter } from "./adapters/pnpm.js";
|
|
3
|
+
import { createYarnClassicAdapter } from "./adapters/yarn-classic.js";
|
|
4
|
+
import { createYarnModernAdapter } from "./adapters/yarn-modern.js";
|
|
5
|
+
import "./adapters/index.js";
|
|
6
|
+
import { allTests } from "./tests/index.js";
|
|
7
|
+
import { createUser, pingRegistry } from "./utils/registry-client.js";
|
|
8
|
+
import { runAll, runSuite } from "./runner.js";
|
|
9
|
+
import buildDebug from "debug";
|
|
10
|
+
//#region src/index.ts
|
|
11
|
+
buildDebug("verdaccio:e2e-cli");
|
|
12
|
+
function parsePmSpec(filter) {
|
|
13
|
+
const eqIdx = filter.indexOf("=");
|
|
14
|
+
if (eqIdx !== -1) return {
|
|
15
|
+
name: filter.slice(0, eqIdx).toLowerCase(),
|
|
16
|
+
binPath: filter.slice(eqIdx + 1)
|
|
17
|
+
};
|
|
18
|
+
const atIdx = filter.indexOf("@");
|
|
19
|
+
if (atIdx !== -1) return {
|
|
20
|
+
name: filter.slice(0, atIdx).toLowerCase(),
|
|
21
|
+
version: filter.slice(atIdx + 1)
|
|
22
|
+
};
|
|
23
|
+
return { name: filter.toLowerCase() };
|
|
24
|
+
}
|
|
25
|
+
function parseAdapters(pmFilters) {
|
|
26
|
+
if (!pmFilters || pmFilters.length === 0) return [createNpmAdapter()];
|
|
27
|
+
const adapters = [];
|
|
28
|
+
for (const filter of pmFilters) {
|
|
29
|
+
const { name, version, binPath } = parsePmSpec(filter);
|
|
30
|
+
if (name === "npm") adapters.push(createNpmAdapter(binPath, version));
|
|
31
|
+
else if (name === "pnpm") adapters.push(createPnpmAdapter(binPath, version));
|
|
32
|
+
else if (name === "yarn-classic" || name === "yarn1") adapters.push(createYarnClassicAdapter(binPath, version));
|
|
33
|
+
else if (name === "yarn-modern" || name === "yarn") adapters.push(createYarnModernAdapter(binPath, version));
|
|
34
|
+
else throw new Error(`Unknown package manager: "${name}". Supported: npm, pnpm, yarn-classic, yarn-modern[@version]`);
|
|
35
|
+
}
|
|
36
|
+
return adapters;
|
|
37
|
+
}
|
|
38
|
+
function parseArgs(argv) {
|
|
39
|
+
const options = {
|
|
40
|
+
registry: "",
|
|
41
|
+
pm: [],
|
|
42
|
+
test: [],
|
|
43
|
+
concurrency: 1,
|
|
44
|
+
timeout: 5e4,
|
|
45
|
+
verbose: false
|
|
46
|
+
};
|
|
47
|
+
for (let i = 2; i < argv.length; i++) {
|
|
48
|
+
const arg = argv[i];
|
|
49
|
+
if (arg === "--registry" || arg === "-r") options.registry = argv[++i];
|
|
50
|
+
else if (arg === "--pm") options.pm.push(argv[++i]);
|
|
51
|
+
else if (arg === "--test" || arg === "-t") options.test.push(argv[++i]);
|
|
52
|
+
else if (arg === "--concurrency" || arg === "-c") options.concurrency = parseInt(argv[++i], 10);
|
|
53
|
+
else if (arg === "--timeout") options.timeout = parseInt(argv[++i], 10);
|
|
54
|
+
else if (arg === "--token") options.token = argv[++i];
|
|
55
|
+
else if (arg === "--verbose" || arg === "-v") options.verbose = true;
|
|
56
|
+
else if (arg === "--help" || arg === "-h") {
|
|
57
|
+
printHelp();
|
|
58
|
+
process.exit(0);
|
|
59
|
+
} else if (arg.startsWith("--registry=")) options.registry = arg.split("=")[1];
|
|
60
|
+
else if (arg.startsWith("--pm=")) options.pm.push(arg.split("=")[1]);
|
|
61
|
+
else if (arg.startsWith("--test=")) options.test.push(arg.split("=")[1]);
|
|
62
|
+
else if (arg.startsWith("--token=")) options.token = arg.split("=")[1];
|
|
63
|
+
else if (arg.startsWith("--timeout=")) options.timeout = parseInt(arg.split("=")[1], 10);
|
|
64
|
+
else {
|
|
65
|
+
console.error(`Unknown argument: ${arg}`);
|
|
66
|
+
printHelp();
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return options;
|
|
71
|
+
}
|
|
72
|
+
function printHelp() {
|
|
73
|
+
console.log(`
|
|
74
|
+
@verdaccio/e2e-cli - Run Verdaccio e2e tests against any running registry
|
|
75
|
+
|
|
76
|
+
Usage:
|
|
77
|
+
verdaccio-e2e --registry <url> [options]
|
|
78
|
+
|
|
79
|
+
Required:
|
|
80
|
+
-r, --registry <url> Verdaccio registry URL (e.g. http://localhost:4873)
|
|
81
|
+
|
|
82
|
+
Options:
|
|
83
|
+
--pm <name[@version]> Package manager to test (can be repeated)
|
|
84
|
+
Supported: npm, pnpm, yarn-classic, yarn-modern (or yarn)
|
|
85
|
+
Examples: --pm npm@10 --pm pnpm@9
|
|
86
|
+
--pm yarn-modern@4
|
|
87
|
+
--pm yarn-modern@3
|
|
88
|
+
--pm yarn-classic
|
|
89
|
+
--pm npm --pm pnpm (uses system version)
|
|
90
|
+
Auto-installs the requested yarn version if needed
|
|
91
|
+
Default: npm
|
|
92
|
+
|
|
93
|
+
-t, --test <name> Filter tests by name (can be repeated)
|
|
94
|
+
Available: publish, install, audit, info, deprecate,
|
|
95
|
+
dist-tags, ping, search, star, unpublish
|
|
96
|
+
Default: all supported by the PM
|
|
97
|
+
|
|
98
|
+
--token <token> Auth token (skips user creation)
|
|
99
|
+
--timeout <ms> Per-test timeout (default: 50000)
|
|
100
|
+
-v, --verbose Enable debug output
|
|
101
|
+
-h, --help Show this help
|
|
102
|
+
`);
|
|
103
|
+
}
|
|
104
|
+
async function main(argv = process.argv) {
|
|
105
|
+
const options = parseArgs(argv);
|
|
106
|
+
if (!options.registry) {
|
|
107
|
+
console.error("Error: --registry is required\n");
|
|
108
|
+
printHelp();
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
if (options.verbose) {
|
|
112
|
+
const { setVerbose } = await import("./utils/process.js");
|
|
113
|
+
setVerbose(true);
|
|
114
|
+
}
|
|
115
|
+
console.log(`Checking registry at ${options.registry}...`);
|
|
116
|
+
if (!await pingRegistry(options.registry)) {
|
|
117
|
+
console.error(`Error: Registry at ${options.registry} is not reachable`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
console.log(`Registry is alive.`);
|
|
121
|
+
let token = options.token;
|
|
122
|
+
if (!token) {
|
|
123
|
+
console.log("Creating test user...");
|
|
124
|
+
const auth = await createUser(options.registry);
|
|
125
|
+
token = auth.token;
|
|
126
|
+
console.log(`User "${auth.user}" created.`);
|
|
127
|
+
}
|
|
128
|
+
const adapters = parseAdapters(options.pm);
|
|
129
|
+
console.log(`Adapters: ${adapters.map((a) => a.name).join(", ")}`);
|
|
130
|
+
const tests = options.test && options.test.length > 0 ? allTests.filter((t) => options.test.includes(t.name)) : allTests;
|
|
131
|
+
console.log(`Tests: ${tests.map((t) => t.name).join(", ")}`);
|
|
132
|
+
const { exitCode } = await runAll(adapters, tests, options.registry, token, {
|
|
133
|
+
timeout: options.timeout,
|
|
134
|
+
concurrency: options.concurrency,
|
|
135
|
+
testFilter: options.test
|
|
136
|
+
});
|
|
137
|
+
process.exit(exitCode);
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
export { allTests, createNpmAdapter, createPnpmAdapter, createYarnClassicAdapter, createYarnModernAdapter, main, runAll, runSuite };
|
|
141
|
+
|
|
142
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport {\n createNpmAdapter,\n createPnpmAdapter,\n createYarnClassicAdapter,\n createYarnModernAdapter,\n} from './adapters';\nimport { allTests } from './tests';\nimport { CliOptions, PackageManagerAdapter } from './types';\nimport { createUser, pingRegistry } from './utils/registry-client';\nimport { runAll } from './runner';\n\nconst debug = buildDebug('verdaccio:e2e-cli');\n\nfunction parsePmSpec(filter: string): { name: string; version?: string; binPath?: string } {\n // --pm yarn-modern@3, --pm yarn-classic@1.22.22, --pm npm=/path/to/bin\n const eqIdx = filter.indexOf('=');\n if (eqIdx !== -1) {\n return { name: filter.slice(0, eqIdx).toLowerCase(), binPath: filter.slice(eqIdx + 1) };\n }\n const atIdx = filter.indexOf('@');\n if (atIdx !== -1) {\n return { name: filter.slice(0, atIdx).toLowerCase(), version: filter.slice(atIdx + 1) };\n }\n return { name: filter.toLowerCase() };\n}\n\nfunction parseAdapters(pmFilters?: string[]): PackageManagerAdapter[] {\n if (!pmFilters || pmFilters.length === 0) {\n return [createNpmAdapter()];\n }\n\n const adapters: PackageManagerAdapter[] = [];\n\n for (const filter of pmFilters) {\n const { name, version, binPath } = parsePmSpec(filter);\n\n if (name === 'npm') {\n adapters.push(createNpmAdapter(binPath, version));\n } else if (name === 'pnpm') {\n adapters.push(createPnpmAdapter(binPath, version));\n } else if (name === 'yarn-classic' || name === 'yarn1') {\n adapters.push(createYarnClassicAdapter(binPath, version));\n } else if (name === 'yarn-modern' || name === 'yarn') {\n adapters.push(createYarnModernAdapter(binPath, version));\n } else {\n throw new Error(\n `Unknown package manager: \"${name}\". Supported: npm, pnpm, yarn-classic, yarn-modern[@version]`\n );\n }\n }\n\n return adapters;\n}\n\nfunction parseArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n registry: '',\n pm: [],\n test: [],\n concurrency: 1,\n timeout: 50000,\n verbose: false,\n };\n\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i];\n\n if (arg === '--registry' || arg === '-r') {\n options.registry = argv[++i];\n } else if (arg === '--pm') {\n options.pm!.push(argv[++i]);\n } else if (arg === '--test' || arg === '-t') {\n options.test!.push(argv[++i]);\n } else if (arg === '--concurrency' || arg === '-c') {\n options.concurrency = parseInt(argv[++i], 10);\n } else if (arg === '--timeout') {\n options.timeout = parseInt(argv[++i], 10);\n } else if (arg === '--token') {\n options.token = argv[++i];\n } else if (arg === '--verbose' || arg === '-v') {\n options.verbose = true;\n } else if (arg === '--help' || arg === '-h') {\n printHelp();\n process.exit(0);\n } else if (arg.startsWith('--registry=')) {\n options.registry = arg.split('=')[1];\n } else if (arg.startsWith('--pm=')) {\n options.pm!.push(arg.split('=')[1]);\n } else if (arg.startsWith('--test=')) {\n options.test!.push(arg.split('=')[1]);\n } else if (arg.startsWith('--token=')) {\n options.token = arg.split('=')[1];\n } else if (arg.startsWith('--timeout=')) {\n options.timeout = parseInt(arg.split('=')[1], 10);\n } else {\n console.error(`Unknown argument: ${arg}`);\n printHelp();\n process.exit(1);\n }\n }\n\n return options;\n}\n\nfunction printHelp(): void {\n console.log(`\n @verdaccio/e2e-cli - Run Verdaccio e2e tests against any running registry\n\n Usage:\n verdaccio-e2e --registry <url> [options]\n\n Required:\n -r, --registry <url> Verdaccio registry URL (e.g. http://localhost:4873)\n\n Options:\n --pm <name[@version]> Package manager to test (can be repeated)\n Supported: npm, pnpm, yarn-classic, yarn-modern (or yarn)\n Examples: --pm npm@10 --pm pnpm@9\n --pm yarn-modern@4\n --pm yarn-modern@3\n --pm yarn-classic\n --pm npm --pm pnpm (uses system version)\n Auto-installs the requested yarn version if needed\n Default: npm\n\n -t, --test <name> Filter tests by name (can be repeated)\n Available: publish, install, audit, info, deprecate,\n dist-tags, ping, search, star, unpublish\n Default: all supported by the PM\n\n --token <token> Auth token (skips user creation)\n --timeout <ms> Per-test timeout (default: 50000)\n -v, --verbose Enable debug output\n -h, --help Show this help\n `);\n}\n\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const options = parseArgs(argv);\n\n if (!options.registry) {\n console.error('Error: --registry is required\\n');\n printHelp();\n process.exit(1);\n }\n\n if (options.verbose) {\n const { setVerbose } = await import('./utils/process');\n setVerbose(true);\n }\n\n // Ensure registry is reachable\n console.log(`Checking registry at ${options.registry}...`);\n const alive = await pingRegistry(options.registry);\n if (!alive) {\n console.error(`Error: Registry at ${options.registry} is not reachable`);\n process.exit(1);\n }\n console.log(`Registry is alive.`);\n\n // Get auth token\n let token = options.token;\n if (!token) {\n console.log('Creating test user...');\n const auth = await createUser(options.registry);\n token = auth.token;\n console.log(`User \"${auth.user}\" created.`);\n }\n\n // Build adapter list\n const adapters = parseAdapters(options.pm);\n console.log(`Adapters: ${adapters.map((a) => a.name).join(', ')}`);\n\n // Filter tests\n const tests = options.test && options.test.length > 0\n ? allTests.filter((t) => options.test!.includes(t.name))\n : allTests;\n\n console.log(`Tests: ${tests.map((t) => t.name).join(', ')}`);\n\n // Run\n const { exitCode } = await runAll(adapters, tests, options.registry, token, {\n timeout: options.timeout,\n concurrency: options.concurrency,\n testFilter: options.test,\n });\n\n process.exit(exitCode);\n}\n\n// Re-export for programmatic usage\nexport { allTests } from './tests';\nexport { createNpmAdapter, createPnpmAdapter, createYarnClassicAdapter, createYarnModernAdapter } from './adapters';\nexport { runAll, runSuite } from './runner';\nexport type { PackageManagerAdapter, TestDefinition, TestContext, CliOptions } from './types';\n"],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//#region src/reporter.ts
|
|
2
|
+
var COLORS = {
|
|
3
|
+
reset: "\x1B[0m",
|
|
4
|
+
red: "\x1B[31m",
|
|
5
|
+
green: "\x1B[32m",
|
|
6
|
+
yellow: "\x1B[33m",
|
|
7
|
+
cyan: "\x1B[36m",
|
|
8
|
+
dim: "\x1B[2m",
|
|
9
|
+
bold: "\x1B[1m"
|
|
10
|
+
};
|
|
11
|
+
function formatDuration(ms) {
|
|
12
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
13
|
+
return `${(ms / 1e3).toFixed(1)}s`;
|
|
14
|
+
}
|
|
15
|
+
function reportTestStart(adapterName, testName) {
|
|
16
|
+
process.stdout.write(` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}...`);
|
|
17
|
+
}
|
|
18
|
+
function reportTestResult(result) {
|
|
19
|
+
if (result.passed) process.stdout.write(`\r ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\n`);
|
|
20
|
+
else {
|
|
21
|
+
process.stdout.write(`\r ${COLORS.red}FAIL${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\n`);
|
|
22
|
+
if (result.error) {
|
|
23
|
+
const lines = result.error.split("\n");
|
|
24
|
+
for (const line of lines) console.log(` ${COLORS.red}${line}${COLORS.reset}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function reportSuiteStart(adapterName) {
|
|
29
|
+
console.log(`\n${COLORS.bold}${COLORS.cyan}${adapterName}${COLORS.reset}`);
|
|
30
|
+
}
|
|
31
|
+
function reportSkipped(testName) {
|
|
32
|
+
console.log(` ${COLORS.yellow}SKIP${COLORS.reset} ${testName}`);
|
|
33
|
+
}
|
|
34
|
+
function reportSummary(results) {
|
|
35
|
+
console.log(`\n${COLORS.bold}${"=".repeat(50)}${COLORS.reset}`);
|
|
36
|
+
console.log(`${COLORS.bold}Summary${COLORS.reset}\n`);
|
|
37
|
+
let totalPassed = 0;
|
|
38
|
+
let totalFailed = 0;
|
|
39
|
+
let totalSkipped = 0;
|
|
40
|
+
let totalDuration = 0;
|
|
41
|
+
for (const suite of results) {
|
|
42
|
+
const status = suite.failed > 0 ? COLORS.red : COLORS.green;
|
|
43
|
+
const icon = suite.failed > 0 ? "x" : "v";
|
|
44
|
+
console.log(` ${status}${icon}${COLORS.reset} ${suite.adapter}: ${COLORS.green}${suite.passed} passed${COLORS.reset}, ${COLORS.red}${suite.failed} failed${COLORS.reset}, ${COLORS.yellow}${suite.skipped} skipped${COLORS.reset} ${COLORS.dim}(${formatDuration(suite.duration)})${COLORS.reset}`);
|
|
45
|
+
totalPassed += suite.passed;
|
|
46
|
+
totalFailed += suite.failed;
|
|
47
|
+
totalSkipped += suite.skipped;
|
|
48
|
+
totalDuration += suite.duration;
|
|
49
|
+
}
|
|
50
|
+
console.log(`\n Total: ${COLORS.green}${totalPassed} passed${COLORS.reset}, ${COLORS.red}${totalFailed} failed${COLORS.reset}, ${COLORS.yellow}${totalSkipped} skipped${COLORS.reset} ${COLORS.dim}(${formatDuration(totalDuration)})${COLORS.reset}`);
|
|
51
|
+
console.log(`${COLORS.bold}${"=".repeat(50)}${COLORS.reset}\n`);
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { reportSkipped, reportSuiteStart, reportSummary, reportTestResult, reportTestStart };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.js","names":[],"sources":["../../src/reporter.ts"],"sourcesContent":["import { SuiteResult, TestResult } from './types';\n\nconst COLORS = {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n};\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nexport function reportTestStart(adapterName: string, testName: string): void {\n process.stdout.write(\n ` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}...`\n );\n}\n\nexport function reportTestResult(result: TestResult): void {\n if (result.passed) {\n process.stdout.write(\n `\\r ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\\n`\n );\n } else {\n process.stdout.write(\n `\\r ${COLORS.red}FAIL${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\\n`\n );\n if (result.error) {\n const lines = result.error.split('\\n');\n for (const line of lines) {\n console.log(` ${COLORS.red}${line}${COLORS.reset}`);\n }\n }\n }\n}\n\nexport function reportSuiteStart(adapterName: string): void {\n console.log(`\\n${COLORS.bold}${COLORS.cyan}${adapterName}${COLORS.reset}`);\n}\n\nexport function reportSkipped(testName: string): void {\n console.log(` ${COLORS.yellow}SKIP${COLORS.reset} ${testName}`);\n}\n\nexport function reportSummary(results: SuiteResult[]): void {\n console.log(`\\n${COLORS.bold}${'='.repeat(50)}${COLORS.reset}`);\n console.log(`${COLORS.bold}Summary${COLORS.reset}\\n`);\n\n let totalPassed = 0;\n let totalFailed = 0;\n let totalSkipped = 0;\n let totalDuration = 0;\n\n for (const suite of results) {\n const status = suite.failed > 0 ? COLORS.red : COLORS.green;\n const icon = suite.failed > 0 ? 'x' : 'v';\n console.log(\n ` ${status}${icon}${COLORS.reset} ${suite.adapter}: ` +\n `${COLORS.green}${suite.passed} passed${COLORS.reset}, ` +\n `${COLORS.red}${suite.failed} failed${COLORS.reset}, ` +\n `${COLORS.yellow}${suite.skipped} skipped${COLORS.reset} ` +\n `${COLORS.dim}(${formatDuration(suite.duration)})${COLORS.reset}`\n );\n totalPassed += suite.passed;\n totalFailed += suite.failed;\n totalSkipped += suite.skipped;\n totalDuration += suite.duration;\n }\n\n console.log(`\\n Total: ${COLORS.green}${totalPassed} passed${COLORS.reset}, ` +\n `${COLORS.red}${totalFailed} failed${COLORS.reset}, ` +\n `${COLORS.yellow}${totalSkipped} skipped${COLORS.reset} ` +\n `${COLORS.dim}(${formatDuration(totalDuration)})${COLORS.reset}`);\n console.log(`${COLORS.bold}${'='.repeat(50)}${COLORS.reset}\\n`);\n}\n"],"mappings":";AAEA,IAAM,SAAS;CACb,OAAO;CACP,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,KAAK;CACL,MAAM;CACP;AAED,SAAS,eAAe,IAAoB;AAC1C,KAAI,KAAK,IAAM,QAAO,GAAG,GAAG;AAC5B,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;;AAGnC,SAAgB,gBAAgB,aAAqB,UAAwB;AAC3E,SAAQ,OAAO,MACb,KAAK,OAAO,IAAI,SAAS,OAAO,MAAM,GAAG,YAAY,KAAK,SAAS,KACpE;;AAGH,SAAgB,iBAAiB,QAA0B;AACzD,KAAI,OAAO,OACT,SAAQ,OAAO,MACb,OAAO,OAAO,MAAM,MAAM,OAAO,MAAM,GAAG,OAAO,KAAK,GAAG,OAAO,IAAI,GAAG,eAAe,OAAO,SAAS,CAAC,GAAG,OAAO,MAAM,IACxH;MACI;AACL,UAAQ,OAAO,MACb,OAAO,OAAO,IAAI,MAAM,OAAO,MAAM,GAAG,OAAO,KAAK,GAAG,OAAO,IAAI,GAAG,eAAe,OAAO,SAAS,CAAC,GAAG,OAAO,MAAM,IACtH;AACD,MAAI,OAAO,OAAO;GAChB,MAAM,QAAQ,OAAO,MAAM,MAAM,KAAK;AACtC,QAAK,MAAM,QAAQ,MACjB,SAAQ,IAAI,OAAO,OAAO,MAAM,OAAO,OAAO,QAAQ;;;;AAM9D,SAAgB,iBAAiB,aAA2B;AAC1D,SAAQ,IAAI,KAAK,OAAO,OAAO,OAAO,OAAO,cAAc,OAAO,QAAQ;;AAG5E,SAAgB,cAAc,UAAwB;AACpD,SAAQ,IAAI,KAAK,OAAO,OAAO,MAAM,OAAO,MAAM,GAAG,WAAW;;AAGlE,SAAgB,cAAc,SAA8B;AAC1D,SAAQ,IAAI,KAAK,OAAO,OAAO,IAAI,OAAO,GAAG,GAAG,OAAO,QAAQ;AAC/D,SAAQ,IAAI,GAAG,OAAO,KAAK,SAAS,OAAO,MAAM,IAAI;CAErD,IAAI,cAAc;CAClB,IAAI,cAAc;CAClB,IAAI,eAAe;CACnB,IAAI,gBAAgB;AAEpB,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,SAAS,MAAM,SAAS,IAAI,OAAO,MAAM,OAAO;EACtD,MAAM,OAAO,MAAM,SAAS,IAAI,MAAM;AACtC,UAAQ,IACN,KAAK,SAAS,OAAO,OAAO,MAAM,GAAG,MAAM,QAAQ,IAC9C,OAAO,QAAQ,MAAM,OAAO,SAAS,OAAO,MAAM,IAClD,OAAO,MAAM,MAAM,OAAO,SAAS,OAAO,MAAM,IAChD,OAAO,SAAS,MAAM,QAAQ,UAAU,OAAO,MAAM,GACrD,OAAO,IAAI,GAAG,eAAe,MAAM,SAAS,CAAC,GAAG,OAAO,QAC7D;AACD,iBAAe,MAAM;AACrB,iBAAe,MAAM;AACrB,kBAAgB,MAAM;AACtB,mBAAiB,MAAM;;AAGzB,SAAQ,IAAI,cAAc,OAAO,QAAQ,YAAY,SAAS,OAAO,MAAM,IACtE,OAAO,MAAM,YAAY,SAAS,OAAO,MAAM,IAC/C,OAAO,SAAS,aAAa,UAAU,OAAO,MAAM,GACpD,OAAO,IAAI,GAAG,eAAe,cAAc,CAAC,GAAG,OAAO,QAAQ;AACnE,SAAQ,IAAI,GAAG,OAAO,OAAO,IAAI,OAAO,GAAG,GAAG,OAAO,MAAM,IAAI"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { reportSkipped, reportSuiteStart, reportSummary, reportTestResult, reportTestStart } from "./reporter.js";
|
|
2
|
+
import buildDebug from "debug";
|
|
3
|
+
import { URL } from "url";
|
|
4
|
+
//#region src/runner.ts
|
|
5
|
+
var debug = buildDebug("verdaccio:e2e-cli:runner");
|
|
6
|
+
function getPort(registryUrl) {
|
|
7
|
+
try {
|
|
8
|
+
const url = new URL(registryUrl);
|
|
9
|
+
return parseInt(url.port, 10) || (url.protocol === "https:" ? 443 : 80);
|
|
10
|
+
} catch {
|
|
11
|
+
return 4873;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function runSingleTest(adapter, test, registryUrl, token, timeout) {
|
|
15
|
+
const ctx = {
|
|
16
|
+
registryUrl,
|
|
17
|
+
token,
|
|
18
|
+
port: getPort(registryUrl),
|
|
19
|
+
exec: adapter.exec.bind(adapter),
|
|
20
|
+
adapter,
|
|
21
|
+
runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`
|
|
22
|
+
};
|
|
23
|
+
const start = Date.now();
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
const timer = setTimeout(() => {
|
|
26
|
+
resolve({
|
|
27
|
+
name: test.name,
|
|
28
|
+
passed: false,
|
|
29
|
+
duration: Date.now() - start,
|
|
30
|
+
error: `Test timed out after ${timeout}ms`
|
|
31
|
+
});
|
|
32
|
+
}, timeout);
|
|
33
|
+
test.run(ctx).then(() => {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
resolve({
|
|
36
|
+
name: test.name,
|
|
37
|
+
passed: true,
|
|
38
|
+
duration: Date.now() - start
|
|
39
|
+
});
|
|
40
|
+
}).catch((err) => {
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
resolve({
|
|
43
|
+
name: test.name,
|
|
44
|
+
passed: false,
|
|
45
|
+
duration: Date.now() - start,
|
|
46
|
+
error: err instanceof Error ? err.message : String(err)
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function runSuite(adapter, tests, registryUrl, token, options) {
|
|
52
|
+
const suiteStart = Date.now();
|
|
53
|
+
const results = [];
|
|
54
|
+
let skipped = 0;
|
|
55
|
+
reportSuiteStart(adapter.name);
|
|
56
|
+
for (const test of tests) {
|
|
57
|
+
if (options.testFilter && options.testFilter.length > 0) {
|
|
58
|
+
if (!options.testFilter.includes(test.name)) continue;
|
|
59
|
+
}
|
|
60
|
+
if (test.requires) {
|
|
61
|
+
if (test.requires.filter((cmd) => !adapter.supports.has(cmd)).length > 0) {
|
|
62
|
+
reportSkipped(test.name);
|
|
63
|
+
skipped++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
reportTestStart(adapter.name, test.name);
|
|
68
|
+
const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);
|
|
69
|
+
results.push(result);
|
|
70
|
+
reportTestResult(result);
|
|
71
|
+
}
|
|
72
|
+
const passed = results.filter((r) => r.passed).length;
|
|
73
|
+
const failed = results.filter((r) => !r.passed).length;
|
|
74
|
+
return {
|
|
75
|
+
adapter: adapter.name,
|
|
76
|
+
tests: results,
|
|
77
|
+
passed,
|
|
78
|
+
failed,
|
|
79
|
+
skipped,
|
|
80
|
+
duration: Date.now() - suiteStart
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async function runAll(adapters, tests, registryUrl, token, options) {
|
|
84
|
+
debug("running %d adapters with %d tests", adapters.length, tests.length);
|
|
85
|
+
const results = [];
|
|
86
|
+
for (const adapter of adapters) {
|
|
87
|
+
const result = await runSuite(adapter, tests, registryUrl, token, options);
|
|
88
|
+
results.push(result);
|
|
89
|
+
}
|
|
90
|
+
reportSummary(results);
|
|
91
|
+
return {
|
|
92
|
+
results,
|
|
93
|
+
exitCode: results.reduce((sum, r) => sum + r.failed, 0) > 0 ? 1 : 0
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { runAll, runSuite };
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","names":[],"sources":["../../src/runner.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { URL } from 'url';\n\nimport { PackageManagerAdapter, SuiteResult, TestContext, TestDefinition, TestResult } from './types';\nimport { reportSkipped, reportSuiteStart, reportSummary, reportTestResult, reportTestStart } from './reporter';\n\nconst debug = buildDebug('verdaccio:e2e-cli:runner');\n\nfunction getPort(registryUrl: string): number {\n try {\n const url = new URL(registryUrl);\n return parseInt(url.port, 10) || (url.protocol === 'https:' ? 443 : 80);\n } catch {\n return 4873;\n }\n}\n\nasync function runSingleTest(\n adapter: PackageManagerAdapter,\n test: TestDefinition,\n registryUrl: string,\n token: string,\n timeout: number\n): Promise<TestResult> {\n const port = getPort(registryUrl);\n const ctx: TestContext = {\n registryUrl,\n token,\n port,\n exec: adapter.exec.bind(adapter),\n adapter,\n runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,\n };\n\n const start = Date.now();\n\n return new Promise<TestResult>((resolve) => {\n const timer = setTimeout(() => {\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: `Test timed out after ${timeout}ms`,\n });\n }, timeout);\n\n test\n .run(ctx)\n .then(() => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: true,\n duration: Date.now() - start,\n });\n })\n .catch((err) => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n });\n}\n\nexport async function runSuite(\n adapter: PackageManagerAdapter,\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; testFilter?: string[] }\n): Promise<SuiteResult> {\n const suiteStart = Date.now();\n const results: TestResult[] = [];\n let skipped = 0;\n\n reportSuiteStart(adapter.name);\n\n for (const test of tests) {\n // Filter by test name if specified\n if (options.testFilter && options.testFilter.length > 0) {\n if (!options.testFilter.includes(test.name)) {\n continue;\n }\n }\n\n // Check if adapter supports required commands\n if (test.requires) {\n const unsupported = test.requires.filter((cmd) => !adapter.supports.has(cmd));\n if (unsupported.length > 0) {\n reportSkipped(test.name);\n skipped++;\n continue;\n }\n }\n\n reportTestStart(adapter.name, test.name);\n const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);\n results.push(result);\n reportTestResult(result);\n }\n\n const passed = results.filter((r) => r.passed).length;\n const failed = results.filter((r) => !r.passed).length;\n\n return {\n adapter: adapter.name,\n tests: results,\n passed,\n failed,\n skipped,\n duration: Date.now() - suiteStart,\n };\n}\n\nexport async function runAll(\n adapters: PackageManagerAdapter[],\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; concurrency: number; testFilter?: string[] }\n): Promise<{ results: SuiteResult[]; exitCode: number }> {\n debug('running %d adapters with %d tests', adapters.length, tests.length);\n const results: SuiteResult[] = [];\n\n // Run adapters sequentially (each suite is already complex enough)\n for (const adapter of adapters) {\n const result = await runSuite(adapter, tests, registryUrl, token, options);\n results.push(result);\n }\n\n reportSummary(results);\n\n const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);\n return { results, exitCode: totalFailed > 0 ? 1 : 0 };\n}\n"],"mappings":";;;;AAMA,IAAM,QAAQ,WAAW,2BAA2B;AAEpD,SAAS,QAAQ,aAA6B;AAC5C,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,YAAY;AAChC,SAAO,SAAS,IAAI,MAAM,GAAG,KAAK,IAAI,aAAa,WAAW,MAAM;SAC9D;AACN,SAAO;;;AAIX,eAAe,cACb,SACA,MACA,aACA,OACA,SACqB;CAErB,MAAM,MAAmB;EACvB;EACA;EACA,MAJW,QAAQ,YAAY;EAK/B,MAAM,QAAQ,KAAK,KAAK,QAAQ;EAChC;EACA,OAAO,GAAG,KAAK,KAAK,CAAC,SAAS,GAAG,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;EAC3E;CAED,MAAM,QAAQ,KAAK,KAAK;AAExB,QAAO,IAAI,SAAqB,YAAY;EAC1C,MAAM,QAAQ,iBAAiB;AAC7B,WAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,KAAK,GAAG;IACvB,OAAO,wBAAwB,QAAQ;IACxC,CAAC;KACD,QAAQ;AAEX,OACG,IAAI,IAAI,CACR,WAAW;AACV,gBAAa,MAAM;AACnB,WAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,KAAK,GAAG;IACxB,CAAC;IACF,CACD,OAAO,QAAQ;AACd,gBAAa,MAAM;AACnB,WAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,KAAK,GAAG;IACvB,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IACxD,CAAC;IACF;GACJ;;AAGJ,eAAsB,SACpB,SACA,OACA,aACA,OACA,SACsB;CACtB,MAAM,aAAa,KAAK,KAAK;CAC7B,MAAM,UAAwB,EAAE;CAChC,IAAI,UAAU;AAEd,kBAAiB,QAAQ,KAAK;AAE9B,MAAK,MAAM,QAAQ,OAAO;AAExB,MAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS;OAChD,CAAC,QAAQ,WAAW,SAAS,KAAK,KAAK,CACzC;;AAKJ,MAAI,KAAK;OACa,KAAK,SAAS,QAAQ,QAAQ,CAAC,QAAQ,SAAS,IAAI,IAAI,CAAC,CAC7D,SAAS,GAAG;AAC1B,kBAAc,KAAK,KAAK;AACxB;AACA;;;AAIJ,kBAAgB,QAAQ,MAAM,KAAK,KAAK;EACxC,MAAM,SAAS,MAAM,cAAc,SAAS,MAAM,aAAa,OAAO,QAAQ,QAAQ;AACtF,UAAQ,KAAK,OAAO;AACpB,mBAAiB,OAAO;;CAG1B,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,OAAO,CAAC;CAC/C,MAAM,SAAS,QAAQ,QAAQ,MAAM,CAAC,EAAE,OAAO,CAAC;AAEhD,QAAO;EACL,SAAS,QAAQ;EACjB,OAAO;EACP;EACA;EACA;EACA,UAAU,KAAK,KAAK,GAAG;EACxB;;AAGH,eAAsB,OACpB,UACA,OACA,aACA,OACA,SACuD;AACvD,OAAM,qCAAqC,SAAS,QAAQ,MAAM,OAAO;CACzE,MAAM,UAAyB,EAAE;AAGjC,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,SAAS,MAAM,SAAS,SAAS,OAAO,aAAa,OAAO,QAAQ;AAC1E,UAAQ,KAAK,OAAO;;AAGtB,eAAc,QAAQ;AAGtB,QAAO;EAAE;EAAS,UADE,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,QAAQ,EAAE,GACvB,IAAI,IAAI;EAAG"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
//#region src/tests/audit.ts
|
|
3
|
+
async function testAudit(ctx) {
|
|
4
|
+
const packages = [`verdaccio-audit-${ctx.runId}`, `@verdaccio/audit-${ctx.runId}`];
|
|
5
|
+
for (const pkgName of packages) {
|
|
6
|
+
const { tempFolder } = await ctx.adapter.prepareProject(pkgName, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, { jquery: "3.6.1" });
|
|
7
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "install", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
8
|
+
const resp = await ctx.adapter.exec({ cwd: tempFolder }, "audit", "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
9
|
+
const parsedBody = JSON.parse(resp.stdout);
|
|
10
|
+
if (ctx.adapter.type === "npm") {
|
|
11
|
+
assert.ok(parsedBody.metadata !== void 0, "Expected \"metadata\" in audit response");
|
|
12
|
+
assert.ok(parsedBody.auditReportVersion !== void 0, "Expected \"auditReportVersion\" in audit response");
|
|
13
|
+
assert.ok(parsedBody.vulnerabilities !== void 0, "Expected \"vulnerabilities\" in audit response");
|
|
14
|
+
} else assert.ok(parsedBody !== void 0, "Expected audit JSON response");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
var auditTest = {
|
|
18
|
+
name: "audit",
|
|
19
|
+
requires: ["audit"],
|
|
20
|
+
run: testAudit
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { auditTest };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","names":[],"sources":["../../../src/tests/audit.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testAudit(ctx: TestContext): Promise<void> {\n const packages = [`verdaccio-audit-${ctx.runId}`, `@verdaccio/audit-${ctx.runId}`];\n\n for (const pkgName of packages) {\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n { jquery: '3.6.1' }\n );\n\n // install is required to create package lock file\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'install',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'audit',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n const parsedBody = JSON.parse(resp.stdout);\n\n if (ctx.adapter.type === 'npm') {\n assert.ok(parsedBody.metadata !== undefined, 'Expected \"metadata\" in audit response');\n assert.ok(\n parsedBody.auditReportVersion !== undefined,\n 'Expected \"auditReportVersion\" in audit response'\n );\n assert.ok(\n parsedBody.vulnerabilities !== undefined,\n 'Expected \"vulnerabilities\" in audit response'\n );\n } else {\n // pnpm audit --json returns advisories-based format\n assert.ok(parsedBody !== undefined, 'Expected audit JSON response');\n }\n }\n}\n\nexport const auditTest: TestDefinition = {\n name: 'audit',\n requires: ['audit'],\n run: testAudit,\n};\n"],"mappings":";;AAIA,eAAe,UAAU,KAAiC;CACxD,MAAM,WAAW,CAAC,mBAAmB,IAAI,SAAS,oBAAoB,IAAI,QAAQ;AAElF,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,EAAE,QAAQ,SAAS,CACpB;AAGD,QAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;EAED,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,SACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;EAED,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;AAE1C,MAAI,IAAI,QAAQ,SAAS,OAAO;AAC9B,UAAO,GAAG,WAAW,aAAa,KAAA,GAAW,0CAAwC;AACrF,UAAO,GACL,WAAW,uBAAuB,KAAA,GAClC,oDACD;AACD,UAAO,GACL,WAAW,oBAAoB,KAAA,GAC/B,iDACD;QAGD,QAAO,GAAG,eAAe,KAAA,GAAW,+BAA+B;;;AAKzE,IAAa,YAA4B;CACvC,MAAM;CACN,UAAU,CAAC,QAAQ;CACnB,KAAK;CACN"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
//#region src/tests/deprecate.ts
|
|
3
|
+
async function publishPkg(ctx, tempFolder, pkgName) {
|
|
4
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
5
|
+
}
|
|
6
|
+
async function deprecate(ctx, tempFolder, packageVersion, message) {
|
|
7
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "deprecate", packageVersion, message, "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
8
|
+
}
|
|
9
|
+
async function getInfo(ctx, pkgName) {
|
|
10
|
+
const resp = await ctx.adapter.exec({}, "info", pkgName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
11
|
+
return JSON.parse(resp.stdout);
|
|
12
|
+
}
|
|
13
|
+
async function bumpVersion(ctx, tempFolder) {
|
|
14
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "version", "minor", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
15
|
+
}
|
|
16
|
+
async function testDeprecate(ctx) {
|
|
17
|
+
const id = ctx.runId;
|
|
18
|
+
const pkgName1 = `@verdaccio/dep1-${id}`;
|
|
19
|
+
const message = "some message";
|
|
20
|
+
const { tempFolder: tf1 } = await ctx.adapter.prepareProject(pkgName1, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
|
|
21
|
+
await publishPkg(ctx, tf1, pkgName1);
|
|
22
|
+
await deprecate(ctx, tf1, `${pkgName1}@1.0.0`, message);
|
|
23
|
+
const info1 = await getInfo(ctx, pkgName1);
|
|
24
|
+
assert.strictEqual(info1.name, pkgName1);
|
|
25
|
+
assert.strictEqual(info1.deprecated, message, "Package should be deprecated");
|
|
26
|
+
const pkgName2 = `@verdaccio/dep2-${id}`;
|
|
27
|
+
const { tempFolder: tf2 } = await ctx.adapter.prepareProject(pkgName2, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
|
|
28
|
+
await publishPkg(ctx, tf2, pkgName2);
|
|
29
|
+
await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, message);
|
|
30
|
+
const info2a = await getInfo(ctx, pkgName2);
|
|
31
|
+
assert.strictEqual(info2a.deprecated, message);
|
|
32
|
+
await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, "");
|
|
33
|
+
const info2b = await getInfo(ctx, pkgName2);
|
|
34
|
+
assert.strictEqual(info2b.deprecated, void 0, "Package should be un-deprecated");
|
|
35
|
+
const pkgName3 = `@verdaccio/dep3-${id}`;
|
|
36
|
+
const { tempFolder: tf3 } = await ctx.adapter.prepareProject(pkgName3, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
|
|
37
|
+
await publishPkg(ctx, tf3, pkgName3);
|
|
38
|
+
for (let i = 0; i < 3; i++) {
|
|
39
|
+
await bumpVersion(ctx, tf3);
|
|
40
|
+
await publishPkg(ctx, tf3, pkgName3);
|
|
41
|
+
}
|
|
42
|
+
await deprecate(ctx, tf3, pkgName3, message);
|
|
43
|
+
for (const v of [
|
|
44
|
+
"1.0.0",
|
|
45
|
+
"1.1.0",
|
|
46
|
+
"1.2.0",
|
|
47
|
+
"1.3.0"
|
|
48
|
+
]) {
|
|
49
|
+
const info = await getInfo(ctx, `${pkgName3}@${v}`);
|
|
50
|
+
assert.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);
|
|
51
|
+
}
|
|
52
|
+
await bumpVersion(ctx, tf3);
|
|
53
|
+
await publishPkg(ctx, tf3, pkgName3);
|
|
54
|
+
const info3 = await getInfo(ctx, `${pkgName3}@1.4.0`);
|
|
55
|
+
assert.strictEqual(info3.deprecated, void 0, "New version should not be deprecated");
|
|
56
|
+
}
|
|
57
|
+
var deprecateTest = {
|
|
58
|
+
name: "deprecate",
|
|
59
|
+
requires: ["deprecate"],
|
|
60
|
+
run: testDeprecate
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
export { deprecateTest };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=deprecate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deprecate.js","names":[],"sources":["../../../src/tests/deprecate.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function publishPkg(ctx: TestContext, tempFolder: string, pkgName: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function deprecate(\n ctx: TestContext,\n tempFolder: string,\n packageVersion: string,\n message: string\n) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'deprecate',\n packageVersion,\n message,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function getInfo(ctx: TestContext, pkgName: string) {\n const resp = await ctx.adapter.exec(\n {},\n 'info',\n pkgName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n return JSON.parse(resp.stdout);\n}\n\nasync function bumpVersion(ctx: TestContext, tempFolder: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'version',\n 'minor',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function testDeprecate(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Test 1: deprecate a single version\n const pkgName1 = `@verdaccio/dep1-${id}`;\n const message = 'some message';\n const { tempFolder: tf1 } = await ctx.adapter.prepareProject(\n pkgName1,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tf1, pkgName1);\n await deprecate(ctx, tf1, `${pkgName1}@1.0.0`, message);\n const info1 = await getInfo(ctx, pkgName1);\n assert.strictEqual(info1.name, pkgName1);\n assert.strictEqual(info1.deprecated, message, 'Package should be deprecated');\n\n // Test 2: un-deprecate\n const pkgName2 = `@verdaccio/dep2-${id}`;\n const { tempFolder: tf2 } = await ctx.adapter.prepareProject(\n pkgName2,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tf2, pkgName2);\n await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, message);\n const info2a = await getInfo(ctx, pkgName2);\n assert.strictEqual(info2a.deprecated, message);\n // empty string = undeprecate\n await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, '');\n const info2b = await getInfo(ctx, pkgName2);\n assert.strictEqual(info2b.deprecated, undefined, 'Package should be un-deprecated');\n\n // Test 3: deprecate multiple versions\n const pkgName3 = `@verdaccio/dep3-${id}`;\n const { tempFolder: tf3 } = await ctx.adapter.prepareProject(\n pkgName3,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tf3, pkgName3);\n for (let i = 0; i < 3; i++) {\n await bumpVersion(ctx, tf3);\n await publishPkg(ctx, tf3, pkgName3);\n }\n await deprecate(ctx, tf3, pkgName3, message);\n for (const v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) {\n const info = await getInfo(ctx, `${pkgName3}@${v}`);\n assert.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);\n }\n // publish a new version after deprecation — should NOT be deprecated\n await bumpVersion(ctx, tf3);\n await publishPkg(ctx, tf3, pkgName3);\n const info3 = await getInfo(ctx, `${pkgName3}@1.4.0`);\n assert.strictEqual(info3.deprecated, undefined, 'New version should not be deprecated');\n}\n\nexport const deprecateTest: TestDefinition = {\n name: 'deprecate',\n requires: ['deprecate'],\n run: testDeprecate,\n};\n"],"mappings":";;AAIA,eAAe,WAAW,KAAkB,YAAoB,SAAiB;AAC/E,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,UACb,KACA,YACA,gBACA,SACA;AACA,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,aACA,gBACA,SACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,QAAQ,KAAkB,SAAiB;CACxD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,EACF,QACA,SACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AACD,QAAO,KAAK,MAAM,KAAK,OAAO;;AAGhC,eAAe,YAAY,KAAkB,YAAoB;AAC/D,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,SACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,cAAc,KAAiC;CAC5D,MAAM,KAAK,IAAI;CAGf,MAAM,WAAW,mBAAmB;CACpC,MAAM,UAAU;CAChB,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,KAAK,SAAS;AACpC,OAAM,UAAU,KAAK,KAAK,GAAG,SAAS,SAAS,QAAQ;CACvD,MAAM,QAAQ,MAAM,QAAQ,KAAK,SAAS;AAC1C,QAAO,YAAY,MAAM,MAAM,SAAS;AACxC,QAAO,YAAY,MAAM,YAAY,SAAS,+BAA+B;CAG7E,MAAM,WAAW,mBAAmB;CACpC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,KAAK,SAAS;AACpC,OAAM,UAAU,KAAK,KAAK,GAAG,SAAS,SAAS,QAAQ;CACvD,MAAM,SAAS,MAAM,QAAQ,KAAK,SAAS;AAC3C,QAAO,YAAY,OAAO,YAAY,QAAQ;AAE9C,OAAM,UAAU,KAAK,KAAK,GAAG,SAAS,SAAS,GAAG;CAClD,MAAM,SAAS,MAAM,QAAQ,KAAK,SAAS;AAC3C,QAAO,YAAY,OAAO,YAAY,KAAA,GAAW,kCAAkC;CAGnF,MAAM,WAAW,mBAAmB;CACpC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,KAAK,SAAS;AACpC,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,WAAW,KAAK,KAAK,SAAS;;AAEtC,OAAM,UAAU,KAAK,KAAK,UAAU,QAAQ;AAC5C,MAAK,MAAM,KAAK;EAAC;EAAS;EAAS;EAAS;EAAQ,EAAE;EACpD,MAAM,OAAO,MAAM,QAAQ,KAAK,GAAG,SAAS,GAAG,IAAI;AACnD,SAAO,YAAY,KAAK,YAAY,SAAS,WAAW,EAAE,uBAAuB;;AAGnF,OAAM,YAAY,KAAK,IAAI;AAC3B,OAAM,WAAW,KAAK,KAAK,SAAS;CACpC,MAAM,QAAQ,MAAM,QAAQ,KAAK,GAAG,SAAS,QAAQ;AACrD,QAAO,YAAY,MAAM,YAAY,KAAA,GAAW,uCAAuC;;AAGzF,IAAa,gBAAgC;CAC3C,MAAM;CACN,UAAU,CAAC,YAAY;CACvB,KAAK;CACN"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import assert from "assert";
|
|
2
|
+
//#region src/tests/dist-tags.ts
|
|
3
|
+
async function publishPkg(ctx, tempFolder, extraArgs = []) {
|
|
4
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...extraArgs, ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
5
|
+
}
|
|
6
|
+
async function bumpVersion(ctx, tempFolder) {
|
|
7
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "version", "minor", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
8
|
+
}
|
|
9
|
+
async function testDistTags(ctx) {
|
|
10
|
+
const id = ctx.runId;
|
|
11
|
+
const pkgName1 = `@foo/dt1-${id}`;
|
|
12
|
+
const { tempFolder: tf1 } = await ctx.adapter.prepareProject(pkgName1, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
|
|
13
|
+
await publishPkg(ctx, tf1);
|
|
14
|
+
await bumpVersion(ctx, tf1);
|
|
15
|
+
await publishPkg(ctx, tf1, ["--tag", "beta"]);
|
|
16
|
+
const resp1 = await ctx.adapter.exec({ cwd: tf1 }, "dist-tag", "ls", "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
17
|
+
assert.strictEqual(resp1.stdout, "beta: 1.1.0latest: 1.0.0");
|
|
18
|
+
const pkgName2 = `@verdaccio/dt2-${id}`;
|
|
19
|
+
const { tempFolder: tf2 } = await ctx.adapter.prepareProject(pkgName2, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
|
|
20
|
+
await publishPkg(ctx, tf2);
|
|
21
|
+
await bumpVersion(ctx, tf2);
|
|
22
|
+
await publishPkg(ctx, tf2, ["--tag", "beta"]);
|
|
23
|
+
const resp2 = await ctx.adapter.exec({ cwd: tf2 }, "dist-tag", "rm", `${pkgName2}@1.1.0`, "beta", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
24
|
+
assert.strictEqual(resp2.stdout, `-beta: ${pkgName2}@1.1.0`);
|
|
25
|
+
const pkgName3 = `@verdaccio/dt3-${id}`;
|
|
26
|
+
const { tempFolder: tf3 } = await ctx.adapter.prepareProject(pkgName3, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
|
|
27
|
+
await publishPkg(ctx, tf3);
|
|
28
|
+
await bumpVersion(ctx, tf3);
|
|
29
|
+
await publishPkg(ctx, tf3);
|
|
30
|
+
const resp3 = await ctx.adapter.exec({ cwd: tf3 }, "dist-tag", "add", `${pkgName3}@1.1.0`, "alfa", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
31
|
+
assert.strictEqual(resp3.stdout, `+alfa: ${pkgName3}@1.1.0`);
|
|
32
|
+
}
|
|
33
|
+
var distTagsTest = {
|
|
34
|
+
name: "dist-tags",
|
|
35
|
+
requires: ["dist-tag"],
|
|
36
|
+
run: testDistTags
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { distTagsTest };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=dist-tags.js.map
|