@verdaccio/e2e-cli 2.4.0 → 2.6.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/cjs/adapters/pnpm.cjs +31 -2
- package/build/cjs/adapters/pnpm.cjs.map +1 -1
- package/build/cjs/adapters/yarn-modern.cjs +52 -3
- package/build/cjs/adapters/yarn-modern.cjs.map +1 -1
- package/build/cjs/reporter.cjs +57 -4
- package/build/cjs/reporter.cjs.map +1 -1
- package/build/cjs/runner.cjs +40 -6
- package/build/cjs/runner.cjs.map +1 -1
- package/build/cjs/tests/deprecate.cjs +82 -42
- package/build/cjs/tests/deprecate.cjs.map +1 -1
- package/build/cjs/tests/index.cjs +2 -0
- package/build/cjs/tests/index.cjs.map +1 -1
- package/build/cjs/tests/login.cjs +117 -0
- package/build/cjs/tests/login.cjs.map +1 -0
- package/build/cjs/tests/ping.cjs +15 -3
- package/build/cjs/tests/ping.cjs.map +1 -1
- package/build/cjs/tests/publish.cjs +3 -1
- package/build/cjs/tests/publish.cjs.map +1 -1
- package/build/cjs/tests/unpublish.cjs +1 -1
- package/build/cjs/tests/unpublish.cjs.map +1 -1
- package/build/cjs/utils/registry-client.cjs +3 -5
- package/build/cjs/utils/registry-client.cjs.map +1 -1
- package/build/esm/adapters/pnpm.js +31 -2
- package/build/esm/adapters/pnpm.js.map +1 -1
- package/build/esm/adapters/yarn-modern.js +52 -3
- package/build/esm/adapters/yarn-modern.js.map +1 -1
- package/build/esm/reporter.js +56 -5
- package/build/esm/reporter.js.map +1 -1
- package/build/esm/runner.js +41 -7
- package/build/esm/runner.js.map +1 -1
- package/build/esm/tests/deprecate.js +81 -42
- package/build/esm/tests/deprecate.js.map +1 -1
- package/build/esm/tests/index.js +2 -0
- package/build/esm/tests/index.js.map +1 -1
- package/build/esm/tests/login.js +113 -0
- package/build/esm/tests/login.js.map +1 -0
- package/build/esm/tests/ping.js +15 -3
- package/build/esm/tests/ping.js.map +1 -1
- package/build/esm/tests/publish.js +3 -1
- package/build/esm/tests/publish.js.map +1 -1
- package/build/esm/tests/unpublish.js +1 -1
- package/build/esm/tests/unpublish.js.map +1 -1
- package/build/esm/utils/registry-client.js +3 -5
- package/build/esm/utils/registry-client.js.map +1 -1
- package/build/reporter.d.ts +2 -1
- package/build/tests/index.d.ts +2 -1
- package/build/tests/login.d.ts +2 -0
- package/build/types.d.ts +11 -0
- package/build/utils/registry-client.d.ts +1 -0
- package/package.json +2 -1
|
@@ -6,7 +6,7 @@ debug = require_runtime.__toESM(debug);
|
|
|
6
6
|
let child_process = require("child_process");
|
|
7
7
|
//#region src/adapters/pnpm.ts
|
|
8
8
|
var debug$1 = (0, debug.default)("verdaccio:e2e-cli:pnpm");
|
|
9
|
-
var
|
|
9
|
+
var PNPM_V10_COMMANDS = new Set([
|
|
10
10
|
"publish",
|
|
11
11
|
"unpublish",
|
|
12
12
|
"install",
|
|
@@ -20,6 +20,22 @@ var PNPM_SUPPORTED_COMMANDS = new Set([
|
|
|
20
20
|
"stars",
|
|
21
21
|
"unstar"
|
|
22
22
|
]);
|
|
23
|
+
var PNPM_V11_COMMANDS = new Set([
|
|
24
|
+
"publish",
|
|
25
|
+
"unpublish",
|
|
26
|
+
"install",
|
|
27
|
+
"info",
|
|
28
|
+
"audit",
|
|
29
|
+
"deprecate"
|
|
30
|
+
]);
|
|
31
|
+
function getSupportedCommands(version) {
|
|
32
|
+
const major = parseInt(version.split(".")[0], 10);
|
|
33
|
+
if (major >= 11) {
|
|
34
|
+
debug$1("pnpm v%d detected, using v11 command set", major);
|
|
35
|
+
return PNPM_V11_COMMANDS;
|
|
36
|
+
}
|
|
37
|
+
return PNPM_V10_COMMANDS;
|
|
38
|
+
}
|
|
23
39
|
function detectVersion(bin) {
|
|
24
40
|
try {
|
|
25
41
|
return (0, child_process.execSync)(`${bin} --version`, {
|
|
@@ -57,7 +73,7 @@ function createPnpmAdapter(binPath, version) {
|
|
|
57
73
|
name: `pnpm@${resolved}`,
|
|
58
74
|
type: "pnpm",
|
|
59
75
|
bin,
|
|
60
|
-
supports:
|
|
76
|
+
supports: getSupportedCommands(resolved),
|
|
61
77
|
registryArg(url) {
|
|
62
78
|
return ["--registry", url];
|
|
63
79
|
},
|
|
@@ -65,6 +81,19 @@ function createPnpmAdapter(binPath, version) {
|
|
|
65
81
|
return ["--prefix", folder];
|
|
66
82
|
},
|
|
67
83
|
exec(options, ...args) {
|
|
84
|
+
if (parseInt(resolved.split(".")[0], 10) >= 11) {
|
|
85
|
+
const cmd = args[0];
|
|
86
|
+
if (cmd === "deprecate" || cmd === "unpublish" || cmd === "publish" || cmd === "dist-tag") args = args.filter((a) => a !== "--json" && !a.startsWith("--loglevel"));
|
|
87
|
+
if (cmd === "deprecate") {
|
|
88
|
+
const msgIdx = 2;
|
|
89
|
+
if (args.length > msgIdx && args[msgIdx] === "") args = [
|
|
90
|
+
"undeprecate",
|
|
91
|
+
args[1],
|
|
92
|
+
...args.slice(3)
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
if (cmd === "version") args = args.filter((a) => !a.startsWith("--registry") && !a.startsWith("--loglevel") && !a.startsWith("--no--git-tag-version"));
|
|
96
|
+
}
|
|
68
97
|
return require_process.exec(options, bin, args);
|
|
69
98
|
},
|
|
70
99
|
async prepareProject(packageName, version, registryUrl, port, token, dependencies = {}, devDependencies = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pnpm.cjs","names":[],"sources":["../../../src/adapters/pnpm.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { prepareGenericEmptyProject } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:pnpm');\n\nconst
|
|
1
|
+
{"version":3,"file":"pnpm.cjs","names":[],"sources":["../../../src/adapters/pnpm.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { prepareGenericEmptyProject } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:pnpm');\n\nconst PNPM_V10_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n 'dist-tag',\n 'ping',\n 'search',\n 'star',\n 'stars',\n 'unstar',\n]);\n\n// pnpm v11 removed ping, search, star/stars/unstar\n// dist-tag output format changed (no --json), needs adapted assertions\nconst PNPM_V11_COMMANDS = new Set([\n 'publish',\n 'unpublish',\n 'install',\n 'info',\n 'audit',\n 'deprecate',\n]);\n\nfunction getSupportedCommands(version: string): Set<string> {\n const major = parseInt(version.split('.')[0], 10);\n if (major >= 11) {\n debug('pnpm v%d detected, using v11 command set', major);\n return PNPM_V11_COMMANDS;\n }\n return PNPM_V10_COMMANDS;\n}\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, { encoding: 'utf8', timeout: 5000 }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction installPnpm(version: string): string {\n const pkg = `pnpm@${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/.bin/pnpm`;\n const installed = detectVersion(bin);\n debug('installed pnpm %s at %s', installed, bin);\n console.log(` Auto-installed pnpm ${installed}`);\n return bin;\n}\n\nfunction resolvePnpmBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n if (version) return installPnpm(version);\n return 'pnpm';\n}\n\nexport function createPnpmAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolvePnpmBin(binPath, version);\n const resolved = detectVersion(bin);\n debug('creating pnpm adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `pnpm@${resolved}`,\n type: 'pnpm',\n bin,\n supports: getSupportedCommands(resolved),\n\n registryArg(url: string): string[] {\n return ['--registry', url];\n },\n\n prefixArg(folder: string): string[] {\n return ['--prefix', folder];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n const major = parseInt(resolved.split('.')[0], 10);\n if (major >= 11) {\n // pnpm v11: native deprecate/unpublish don't support --json\n const cmd = args[0];\n if (cmd === 'deprecate' || cmd === 'unpublish' || cmd === 'publish' || cmd === 'dist-tag') {\n args = args.filter((a) => a !== '--json' && !a.startsWith('--loglevel'));\n }\n // pnpm v11: un-deprecate uses `undeprecate` command instead of `deprecate pkg \"\"`\n if (cmd === 'deprecate') {\n // Check if message arg is empty string (un-deprecate)\n // args: ['deprecate', 'pkg@version', '', ...flags]\n const msgIdx = 2; // message is the third arg\n if (args.length > msgIdx && args[msgIdx] === '') {\n args = ['undeprecate', args[1], ...args.slice(3)];\n }\n }\n // pnpm v11: native version command doesn't accept --registry, --loglevel, or --no--git-tag-version\n if (cmd === 'version') {\n args = args.filter(\n (a) =>\n !a.startsWith('--registry') &&\n !a.startsWith('--loglevel') &&\n !a.startsWith('--no--git-tag-version')\n );\n }\n }\n return exec(options, bin, args);\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 return prepareGenericEmptyProject(\n packageName,\n version,\n port,\n token,\n registryUrl,\n dependencies,\n devDependencies\n );\n },\n };\n\n return adapter;\n}\n"],"mappings":";;;;;;;AAOA,IAAM,WAAA,GAAA,MAAA,SAAmB,yBAAyB;AAElD,IAAM,oBAAoB,IAAI,IAAI;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAIF,IAAM,oBAAoB,IAAI,IAAI;CAChC;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,qBAAqB,SAA8B;CAC1D,MAAM,QAAQ,SAAS,QAAQ,MAAM,IAAI,CAAC,IAAI,GAAG;AACjD,KAAI,SAAS,IAAI;AACf,UAAM,4CAA4C,MAAM;AACxD,SAAO;;AAET,QAAO;;AAGT,SAAS,cAAc,KAAqB;AAC1C,KAAI;AACF,UAAA,GAAA,cAAA,UAAgB,GAAG,IAAI,aAAa;GAAE,UAAU;GAAQ,SAAS;GAAM,CAAC,CAAC,MAAM;SACzE;AACN,SAAO;;;AAIX,SAAS,YAAY,SAAyB;CAC5C,MAAM,MAAM,QAAQ;AACpB,SAAM,+BAA+B,IAAI;CACzC,MAAM,UAAA,GAAA,cAAA,UAAkB,aAAa,EAAE,UAAU,QAAQ,CAAC,CAAC,MAAM;AACjE,EAAA,GAAA,cAAA,UAAS,yBAAyB,OAAO,IAAI,IAAI,oBAAoB;EACnE,UAAU;EACV,SAAS;EACV,CAAC;CACF,MAAM,MAAM,GAAG,OAAO;CACtB,MAAM,YAAY,cAAc,IAAI;AACpC,SAAM,2BAA2B,WAAW,IAAI;AAChD,SAAQ,IAAI,yBAAyB,YAAY;AACjD,QAAO;;AAGT,SAAS,eAAe,SAAkB,SAA0B;AAClE,KAAI,QAAS,QAAO;AACpB,KAAI,QAAS,QAAO,YAAY,QAAQ;AACxC,QAAO;;AAGT,SAAgB,kBAAkB,SAAkB,SAAyC;CAC3F,MAAM,MAAM,eAAe,SAAS,QAAQ;CAC5C,MAAM,WAAW,cAAc,IAAI;AACnC,SAAM,2CAA2C,KAAK,SAAS;AAmE/D,QAjEuC;EACrC,MAAM,QAAQ;EACd,MAAM;EACN;EACA,UAAU,qBAAqB,SAAS;EAExC,YAAY,KAAuB;AACjC,UAAO,CAAC,cAAc,IAAI;;EAG5B,UAAU,QAA0B;AAClC,UAAO,CAAC,YAAY,OAAO;;EAG7B,KAAK,SAAuB,GAAG,MAAqC;AAElE,OADc,SAAS,SAAS,MAAM,IAAI,CAAC,IAAI,GAAG,IACrC,IAAI;IAEf,MAAM,MAAM,KAAK;AACjB,QAAI,QAAQ,eAAe,QAAQ,eAAe,QAAQ,aAAa,QAAQ,WAC7E,QAAO,KAAK,QAAQ,MAAM,MAAM,YAAY,CAAC,EAAE,WAAW,aAAa,CAAC;AAG1E,QAAI,QAAQ,aAAa;KAGvB,MAAM,SAAS;AACf,SAAI,KAAK,SAAS,UAAU,KAAK,YAAY,GAC3C,QAAO;MAAC;MAAe,KAAK;MAAI,GAAG,KAAK,MAAM,EAAE;MAAC;;AAIrD,QAAI,QAAQ,UACV,QAAO,KAAK,QACT,MACC,CAAC,EAAE,WAAW,aAAa,IAC3B,CAAC,EAAE,WAAW,aAAa,IAC3B,CAAC,EAAE,WAAW,wBAAwB,CACzC;;AAGL,UAAO,gBAAA,KAAK,SAAS,KAAK,KAAK;;EAGjC,MAAM,eACJ,aACA,SACA,aACA,MACA,OACA,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACX;AACjC,UAAO,gBAAA,2BACL,aACA,SACA,MACA,OACA,aACA,cACA,gBACD;;EAEJ"}
|
|
@@ -14,7 +14,10 @@ var debug$1 = (0, debug.default)("verdaccio:e2e-cli:yarn-modern");
|
|
|
14
14
|
var YARN_MODERN_SUPPORTED_COMMANDS = new Set([
|
|
15
15
|
"publish",
|
|
16
16
|
"install",
|
|
17
|
-
"info"
|
|
17
|
+
"info",
|
|
18
|
+
"ping",
|
|
19
|
+
"deprecate",
|
|
20
|
+
"login"
|
|
18
21
|
]);
|
|
19
22
|
var YARN_ENV = {
|
|
20
23
|
COREPACK_ENABLE_STRICT: "0",
|
|
@@ -74,8 +77,8 @@ function createYamlConfig(registry, token) {
|
|
|
74
77
|
unsafeHttpWhitelist: ["localhost"]
|
|
75
78
|
};
|
|
76
79
|
if (typeof token === "string") {
|
|
77
|
-
|
|
78
|
-
defaultYaml.npmRegistries = { [
|
|
80
|
+
new url.URL(registry);
|
|
81
|
+
defaultYaml.npmRegistries = { [registry]: {
|
|
79
82
|
npmAlwaysAuth: true,
|
|
80
83
|
npmAuthToken: token
|
|
81
84
|
} };
|
|
@@ -115,6 +118,26 @@ function createYarnModernAdapter(binPath, version) {
|
|
|
115
118
|
"info",
|
|
116
119
|
...args.slice(1).filter((a) => !a.startsWith("--registry"))
|
|
117
120
|
];
|
|
121
|
+
else if (cmd === "ping") yarnArgs = [
|
|
122
|
+
"npm",
|
|
123
|
+
"ping",
|
|
124
|
+
...args.slice(1).filter((a) => !a.startsWith("--registry"))
|
|
125
|
+
];
|
|
126
|
+
else if (cmd === "deprecate") yarnArgs = [
|
|
127
|
+
"npm",
|
|
128
|
+
"deprecate",
|
|
129
|
+
...args.slice(1).filter((a) => !a.startsWith("--registry"))
|
|
130
|
+
];
|
|
131
|
+
else if (cmd === "login") yarnArgs = [
|
|
132
|
+
"npm",
|
|
133
|
+
"login",
|
|
134
|
+
...args.slice(1).filter((a) => !a.startsWith("--registry"))
|
|
135
|
+
];
|
|
136
|
+
else if (cmd === "whoami") yarnArgs = [
|
|
137
|
+
"npm",
|
|
138
|
+
"whoami",
|
|
139
|
+
...args.slice(1).filter((a) => !a.startsWith("--registry"))
|
|
140
|
+
];
|
|
118
141
|
else yarnArgs = args.filter((a) => !a.startsWith("--registry"));
|
|
119
142
|
return require_process.exec({
|
|
120
143
|
...options,
|
|
@@ -128,6 +151,32 @@ function createYarnModernAdapter(binPath, version) {
|
|
|
128
151
|
await (0, fs_promises.writeFile)((0, path.join)(tempFolder, "package.json"), require_project.getPackageJSON(packageName, version, dependencies, devDependencies));
|
|
129
152
|
await (0, fs_promises.writeFile)((0, path.join)(tempFolder, "README.md"), require_project.getREADME(packageName));
|
|
130
153
|
return { tempFolder };
|
|
154
|
+
},
|
|
155
|
+
async importPlugin(cwd, pluginName) {
|
|
156
|
+
debug$1("downloading %s plugin bundle", pluginName);
|
|
157
|
+
const tmpDir = (0, child_process.execSync)("mktemp -d", { encoding: "utf8" }).trim();
|
|
158
|
+
(0, child_process.execSync)(`npm pack ${`@verdaccio/yarn-plugin-${pluginName}`} --pack-destination "${tmpDir}"`, {
|
|
159
|
+
encoding: "utf8",
|
|
160
|
+
timeout: 3e4,
|
|
161
|
+
stdio: "pipe"
|
|
162
|
+
});
|
|
163
|
+
(0, child_process.execSync)(`tar xzf "${tmpDir}"/*.tgz -C "${tmpDir}"`, {
|
|
164
|
+
encoding: "utf8",
|
|
165
|
+
stdio: "pipe"
|
|
166
|
+
});
|
|
167
|
+
const bundlePath = (0, path.join)(tmpDir, `package/bundles/@yarnpkg/plugin-${pluginName}.js`);
|
|
168
|
+
debug$1("importing plugin from %s into %s", bundlePath, cwd);
|
|
169
|
+
await require_process.exec({
|
|
170
|
+
cwd,
|
|
171
|
+
env: {
|
|
172
|
+
...process.env,
|
|
173
|
+
...YARN_ENV
|
|
174
|
+
}
|
|
175
|
+
}, bin, [
|
|
176
|
+
"plugin",
|
|
177
|
+
"import",
|
|
178
|
+
bundlePath
|
|
179
|
+
]);
|
|
131
180
|
}
|
|
132
181
|
};
|
|
133
182
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yarn-modern.cjs","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\nconst YARN_ENV = {\n COREPACK_ENABLE_STRICT: '0',\n YARN_IGNORE_PATH: '1',\n};\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, {\n env: { ...process.env, ...YARN_ENV },\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 if (version) {\n return installYarnModern(version);\n }\n\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 [
|
|
1
|
+
{"version":3,"file":"yarn-modern.cjs","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', 'ping', 'deprecate', 'login']);\n\nconst YARN_ENV = {\n COREPACK_ENABLE_STRICT: '0',\n YARN_IGNORE_PATH: '1',\n};\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, {\n env: { ...process.env, ...YARN_ENV },\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 if (version) {\n return installYarnModern(version);\n }\n\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 [registry]: {\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, ...YARN_ENV };\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 if (cmd === 'ping') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'ping', ...filtered];\n } else if (cmd === 'deprecate') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'deprecate', ...filtered];\n } else if (cmd === 'login') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'login', ...filtered];\n } else if (cmd === 'whoami') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'whoami', ...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 async importPlugin(cwd: string, pluginName: string): Promise<void> {\n debug('downloading %s plugin bundle', pluginName);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n const pkg = `@verdaccio/yarn-plugin-${pluginName}`;\n execSync(`npm pack ${pkg} --pack-destination \"${tmpDir}\"`, {\n encoding: 'utf8',\n timeout: 30000,\n stdio: 'pipe',\n });\n execSync(`tar xzf \"${tmpDir}\"/*.tgz -C \"${tmpDir}\"`, {\n encoding: 'utf8',\n stdio: 'pipe',\n });\n const bundlePath = join(tmpDir, `package/bundles/@yarnpkg/plugin-${pluginName}.js`);\n debug('importing plugin from %s into %s', bundlePath, cwd);\n await exec({ cwd, env: { ...process.env, ...YARN_ENV } }, bin, [\n 'plugin',\n 'import',\n bundlePath,\n ]);\n },\n };\n\n return adapter;\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAM,WAAA,GAAA,MAAA,SAAmB,gCAAgC;AAEzD,IAAM,iCAAiC,IAAI,IAAI;CAAC;CAAW;CAAW;CAAQ;CAAQ;CAAa;CAAQ,CAAC;AAE5G,IAAM,WAAW;CACf,wBAAwB;CACxB,kBAAkB;CACnB;AAED,SAAS,cAAc,KAAqB;AAC1C,KAAI;AACF,UAAA,GAAA,cAAA,UAAgB,GAAG,IAAI,aAAa;GAClC,KAAK;IAAE,GAAG,QAAQ;IAAK,GAAG;IAAU;GACpC,UAAU;GACV,SAAS;GACV,CAAC,CAAC,MAAM;SACH;AACN,SAAO;;;AAIX,SAAS,kBAAkB,UAAU,KAAa;CAChD,MAAM,MAAM,qBAAqB;AACjC,SAAM,+BAA+B,IAAI;CACzC,MAAM,UAAA,GAAA,cAAA,UAAkB,aAAa,EAAE,UAAU,QAAQ,CAAC,CAAC,MAAM;AACjE,EAAA,GAAA,cAAA,UAAS,yBAAyB,OAAO,IAAI,IAAI,oBAAoB;EACnE,UAAU;EACV,SAAS;EACV,CAAC;CACF,MAAM,MAAM,GAAG,OAAO;CACtB,MAAM,YAAY,cAAc,IAAI;AACpC,SAAM,kCAAkC,WAAW,IAAI;AACvD,SAAQ,IAAI,gCAAgC,YAAY;AACxD,QAAO;;AAGT,SAAS,eAAe,SAAkB,SAA0B;AAClE,KAAI,QAAS,QAAO;AAEpB,KAAI,QACF,QAAO,kBAAkB,QAAQ;AAGnC,KAAI;EACF,MAAM,cAAA,GAAA,cAAA,UAAsB,cAAc;GAAE,UAAU;GAAQ,SAAS;GAAM,CAAC,CAAC,MAAM;EACrF,MAAM,aAAa,cAAc,WAAW;AAE5C,MADc,SAAS,WAAW,MAAM,IAAI,CAAC,IAAI,GAAG,IACvC,GAAG;AACd,WAAM,8BAA8B,WAAW;AAC/C,UAAO;;AAET,UAAM,oDAAoD,WAAW;SAC/D;AACN,UAAM,8CAA8C;;AAGtD,QAAO,mBAAmB;;AAG5B,SAAS,iBAAiB,UAAkB,OAAgB;CAC1D,MAAM,cAAmB;EACvB,mBAAmB;EACnB,yBAAyB;EACzB,qBAAqB,CAAC,YAAY;EACnC;AAED,KAAI,OAAO,UAAU,UAAU;AACjB,MAAI,IAAA,IAAI,SAAS;AAC7B,cAAY,gBAAgB,GACzB,WAAW;GACV,eAAe;GACf,cAAc;GACf,EACF;;AAGH,QAAO,QAAA,QAAK,KAAK,YAAY;;AAG/B,SAAgB,wBAAwB,SAAkB,SAAyC;CACjG,MAAM,MAAM,eAAe,SAAS,QAAQ;CAC5C,MAAM,WAAW,cAAc,IAAI;AACnC,SAAM,kDAAkD,KAAK,SAAS;AAmGtE,QAjGuC;EACrC,MAAM,eAAe;EACrB,MAAM;EACN;EACA,UAAU;EAEV,YAAY,MAAwB;AAClC,UAAO,EAAE;;EAGX,UAAU,SAA2B;AACnC,UAAO,EAAE;;EAGX,KAAK,SAAuB,GAAG,MAAqC;GAClE,MAAM,MAAM;IAAE,GAAG,QAAQ;IAAK,GAAG,QAAQ;IAAK,GAAG;IAAU;GAE3D,MAAM,MAAM,KAAK;GACjB,IAAI;AACJ,OAAI,QAAQ,UAIV,YAAW;IAAC;IAAO;IAAW,GAHb,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,MAAM,YAAY,CAAC,EAAE,WAAW,aAAa,CACrD;IACyC;YACjC,QAAQ,OAEjB,YAAW;IAAC;IAAO;IAAQ,GADV,KAAK,MAAM,EAAE,CAAC,QAAQ,MAAM,CAAC,EAAE,WAAW,aAAa,CAAC;IAClC;YAC9B,QAAQ,OAIjB,YAAW;IAAC;IAAO;IAAQ,GAHV,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IACsC;YAC9B,QAAQ,YAIjB,YAAW;IAAC;IAAO;IAAa,GAHf,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IAC2C;YACnC,QAAQ,QAIjB,YAAW;IAAC;IAAO;IAAS,GAHX,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IACuC;YAC/B,QAAQ,SAIjB,YAAW;IAAC;IAAO;IAAU,GAHZ,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IACwC;OAEzC,YAAW,KAAK,QAAQ,MAAM,CAAC,EAAE,WAAW,aAAa,CAAC;AAG5D,UAAO,gBAAA,KAAK;IAAE,GAAG;IAAS;IAAK,EAAE,KAAK,SAAS;;EAGjD,MAAM,eACJ,aACA,SACA,aACA,OACA,OACA,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACX;GACjC,MAAM,aAAa,MAAM,gBAAA,iBAAiB,YAAY;GACtD,MAAM,cAAc,iBAAiB,aAAa,MAAM;AACxD,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MAAqB,YAAY,cAAc,EAAE,YAAY;AAC7D,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MACO,YAAY,eAAe,EAChC,gBAAA,eAAe,aAAa,SAAS,cAAc,gBAAgB,CACpE;AACD,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MAAqB,YAAY,YAAY,EAAE,gBAAA,UAAU,YAAY,CAAC;AACtE,UAAO,EAAE,YAAY;;EAGvB,MAAM,aAAa,KAAa,YAAmC;AACjE,WAAM,gCAAgC,WAAW;GACjD,MAAM,UAAA,GAAA,cAAA,UAAkB,aAAa,EAAE,UAAU,QAAQ,CAAC,CAAC,MAAM;AAEjE,IAAA,GAAA,cAAA,UAAS,YADG,0BAA0B,aACb,uBAAuB,OAAO,IAAI;IACzD,UAAU;IACV,SAAS;IACT,OAAO;IACR,CAAC;AACF,IAAA,GAAA,cAAA,UAAS,YAAY,OAAO,cAAc,OAAO,IAAI;IACnD,UAAU;IACV,OAAO;IACR,CAAC;GACF,MAAM,cAAA,GAAA,KAAA,MAAkB,QAAQ,mCAAmC,WAAW,KAAK;AACnF,WAAM,oCAAoC,YAAY,IAAI;AAC1D,SAAM,gBAAA,KAAK;IAAE;IAAK,KAAK;KAAE,GAAG,QAAQ;KAAK,GAAG;KAAU;IAAE,EAAE,KAAK;IAC7D;IACA;IACA;IACD,CAAC;;EAEL"}
|
package/build/cjs/reporter.cjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let fs = require("fs");
|
|
1
3
|
//#region src/reporter.ts
|
|
2
4
|
var COLORS = {
|
|
3
5
|
reset: "\x1B[0m",
|
|
@@ -13,21 +15,31 @@ function formatDuration(ms) {
|
|
|
13
15
|
return `${(ms / 1e3).toFixed(1)}s`;
|
|
14
16
|
}
|
|
15
17
|
function reportTestStart(adapterName, testName) {
|
|
16
|
-
process.stdout.write(` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}
|
|
18
|
+
process.stdout.write(` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}...\n`);
|
|
17
19
|
}
|
|
18
|
-
function reportTestResult(result) {
|
|
19
|
-
if (result.passed) process.stdout.write(
|
|
20
|
+
function reportTestResult(result, hasSubTests = false) {
|
|
21
|
+
if (result.passed) if (!hasSubTests) process.stdout.write(` ${COLORS.green}✓${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\n`);
|
|
22
|
+
else process.stdout.write(` ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\n`);
|
|
20
23
|
else {
|
|
21
|
-
process.stdout.write(
|
|
24
|
+
process.stdout.write(` ${COLORS.red}FAIL${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\n`);
|
|
22
25
|
if (result.error) {
|
|
23
26
|
const lines = result.error.split("\n");
|
|
24
27
|
for (const line of lines) console.log(` ${COLORS.red}${line}${COLORS.reset}`);
|
|
28
|
+
if (process.env.GITHUB_ACTIONS) {
|
|
29
|
+
const msg = result.error.split("\n")[0];
|
|
30
|
+
console.log(`::error title=E2E ${result.name}::${msg}`);
|
|
31
|
+
}
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
}
|
|
28
35
|
function reportSuiteStart(adapterName) {
|
|
29
36
|
console.log(`\n${COLORS.bold}${COLORS.cyan}${adapterName}${COLORS.reset}`);
|
|
30
37
|
}
|
|
38
|
+
function reportSubTestResult(label, passed, duration) {
|
|
39
|
+
const icon = passed ? `${COLORS.bold}${COLORS.green}✓${COLORS.reset}` : `${COLORS.bold}${COLORS.red}✗${COLORS.reset}`;
|
|
40
|
+
const dur = duration !== void 0 ? ` ${COLORS.dim}${formatDuration(duration)}${COLORS.reset}` : "";
|
|
41
|
+
process.stdout.write(`\n ${icon} ${COLORS.bold}${label}${COLORS.reset}${dur}\n\n`);
|
|
42
|
+
}
|
|
31
43
|
function reportSkipped(testName) {
|
|
32
44
|
console.log(` ${COLORS.yellow}SKIP${COLORS.reset} ${testName}`);
|
|
33
45
|
}
|
|
@@ -49,9 +61,50 @@ function reportSummary(results) {
|
|
|
49
61
|
}
|
|
50
62
|
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
63
|
console.log(`${COLORS.bold}${"=".repeat(50)}${COLORS.reset}\n`);
|
|
64
|
+
const summaryFile = process.env.GITHUB_STEP_SUMMARY;
|
|
65
|
+
if (summaryFile) writeGitHubSummary(summaryFile, results);
|
|
66
|
+
}
|
|
67
|
+
function writeGitHubSummary(summaryFile, results) {
|
|
68
|
+
const lines = [];
|
|
69
|
+
lines.push("## E2E Test Results\n");
|
|
70
|
+
for (const suite of results) {
|
|
71
|
+
const status = suite.failed > 0 ? "❌" : "✅";
|
|
72
|
+
lines.push(`### ${status} ${suite.adapter}\n`);
|
|
73
|
+
lines.push("| Test | Status | Duration |");
|
|
74
|
+
lines.push("|------|--------|----------|");
|
|
75
|
+
for (const test of suite.tests) {
|
|
76
|
+
const icon = test.passed ? "✅" : "❌";
|
|
77
|
+
const dur = formatDuration(test.duration);
|
|
78
|
+
if (test.subTests && test.subTests.length > 0) {
|
|
79
|
+
lines.push(`| **${test.name}** | ${icon} | ${dur} |`);
|
|
80
|
+
for (const sub of test.subTests) {
|
|
81
|
+
const subIcon = sub.passed ? "✅" : "❌";
|
|
82
|
+
const subDur = formatDuration(sub.duration);
|
|
83
|
+
const label = sub.passed ? sub.label : `${sub.label}: ${sub.error?.split("\n")[0] ?? ""}`;
|
|
84
|
+
lines.push(`| ${label} | ${subIcon} | ${subDur} |`);
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
const label = test.passed ? test.name : `${test.name}: ${test.error?.split("\n")[0] ?? ""}`;
|
|
88
|
+
lines.push(`| ${label} | ${icon} | ${dur} |`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
lines.push("");
|
|
92
|
+
}
|
|
93
|
+
let totalPassed = 0;
|
|
94
|
+
let totalFailed = 0;
|
|
95
|
+
let totalSkipped = 0;
|
|
96
|
+
for (const suite of results) {
|
|
97
|
+
totalPassed += suite.passed;
|
|
98
|
+
totalFailed += suite.failed;
|
|
99
|
+
totalSkipped += suite.skipped;
|
|
100
|
+
}
|
|
101
|
+
const emoji = totalFailed > 0 ? "❌" : "✅";
|
|
102
|
+
lines.push(`${emoji} **${totalPassed} passed**, **${totalFailed} failed**, **${totalSkipped} skipped**\n`);
|
|
103
|
+
(0, fs.appendFileSync)(summaryFile, lines.join("\n"));
|
|
52
104
|
}
|
|
53
105
|
//#endregion
|
|
54
106
|
exports.reportSkipped = reportSkipped;
|
|
107
|
+
exports.reportSubTestResult = reportSubTestResult;
|
|
55
108
|
exports.reportSuiteStart = reportSuiteStart;
|
|
56
109
|
exports.reportSummary = reportSummary;
|
|
57
110
|
exports.reportTestResult = reportTestResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reporter.cjs","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}
|
|
1
|
+
{"version":3,"file":"reporter.cjs","names":[],"sources":["../../src/reporter.ts"],"sourcesContent":["import { appendFileSync } from 'fs';\n\nimport { 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}\n\nexport function reportTestResult(result: TestResult, hasSubTests = false): void {\n if (result.passed) {\n if (!hasSubTests) {\n process.stdout.write(\n ` ${COLORS.green}✓${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\\n`\n );\n } else {\n process.stdout.write(\n ` ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\\n`\n );\n }\n } else {\n process.stdout.write(\n ` ${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 // GitHub Actions annotation\n if (process.env.GITHUB_ACTIONS) {\n const msg = result.error.split('\\n')[0];\n console.log(`::error title=E2E ${result.name}::${msg}`);\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 reportSubTestResult(label: string, passed: boolean, duration?: number): void {\n const icon = passed\n ? `${COLORS.bold}${COLORS.green}✓${COLORS.reset}`\n : `${COLORS.bold}${COLORS.red}✗${COLORS.reset}`;\n const dur = duration !== undefined ? ` ${COLORS.dim}${formatDuration(duration)}${COLORS.reset}` : '';\n process.stdout.write(`\\n ${icon} ${COLORS.bold}${label}${COLORS.reset}${dur}\\n\\n`);\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 // GitHub Actions Job Summary\n const summaryFile = process.env.GITHUB_STEP_SUMMARY;\n if (summaryFile) {\n writeGitHubSummary(summaryFile, results);\n }\n}\n\nfunction writeGitHubSummary(summaryFile: string, results: SuiteResult[]): void {\n const lines: string[] = [];\n\n lines.push('## E2E Test Results\\n');\n\n for (const suite of results) {\n const status = suite.failed > 0 ? '❌' : '✅';\n lines.push(`### ${status} ${suite.adapter}\\n`);\n lines.push('| Test | Status | Duration |');\n lines.push('|------|--------|----------|');\n\n for (const test of suite.tests) {\n const icon = test.passed ? '✅' : '❌';\n const dur = formatDuration(test.duration);\n\n if (test.subTests && test.subTests.length > 0) {\n // Parent row\n lines.push(`| **${test.name}** | ${icon} | ${dur} |`);\n // Sub-test rows\n for (const sub of test.subTests) {\n const subIcon = sub.passed ? '✅' : '❌';\n const subDur = formatDuration(sub.duration);\n const label = sub.passed ? sub.label : `${sub.label}: ${sub.error?.split('\\n')[0] ?? ''}`;\n lines.push(`| ${label} | ${subIcon} | ${subDur} |`);\n }\n } else {\n const label = test.passed ? test.name : `${test.name}: ${test.error?.split('\\n')[0] ?? ''}`;\n lines.push(`| ${label} | ${icon} | ${dur} |`);\n }\n }\n\n lines.push('');\n }\n\n let totalPassed = 0;\n let totalFailed = 0;\n let totalSkipped = 0;\n for (const suite of results) {\n totalPassed += suite.passed;\n totalFailed += suite.failed;\n totalSkipped += suite.skipped;\n }\n\n const emoji = totalFailed > 0 ? '❌' : '✅';\n lines.push(`${emoji} **${totalPassed} passed**, **${totalFailed} failed**, **${totalSkipped} skipped**\\n`);\n\n appendFileSync(summaryFile, lines.join('\\n'));\n}\n"],"mappings":"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"}
|
package/build/cjs/runner.cjs
CHANGED
|
@@ -14,13 +14,41 @@ function getPort(registryUrl) {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
async function runSingleTest(adapter, test, registryUrl, token, timeout) {
|
|
17
|
+
const port = getPort(registryUrl);
|
|
18
|
+
let hasSubTests = false;
|
|
19
|
+
const subResults = [];
|
|
17
20
|
const ctx = {
|
|
18
21
|
registryUrl,
|
|
19
22
|
token,
|
|
20
|
-
port
|
|
23
|
+
port,
|
|
21
24
|
exec: adapter.exec.bind(adapter),
|
|
22
25
|
adapter,
|
|
23
|
-
runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}
|
|
26
|
+
runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,
|
|
27
|
+
async subTest(label, fn) {
|
|
28
|
+
hasSubTests = true;
|
|
29
|
+
const subStart = Date.now();
|
|
30
|
+
try {
|
|
31
|
+
await fn();
|
|
32
|
+
const duration = Date.now() - subStart;
|
|
33
|
+
subResults.push({
|
|
34
|
+
label,
|
|
35
|
+
passed: true,
|
|
36
|
+
duration
|
|
37
|
+
});
|
|
38
|
+
require_reporter.reportSubTestResult(label, true, duration);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
const duration = Date.now() - subStart;
|
|
41
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
42
|
+
subResults.push({
|
|
43
|
+
label,
|
|
44
|
+
passed: false,
|
|
45
|
+
duration,
|
|
46
|
+
error
|
|
47
|
+
});
|
|
48
|
+
require_reporter.reportSubTestResult(label, false, duration);
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
24
52
|
};
|
|
25
53
|
const start = Date.now();
|
|
26
54
|
return new Promise((resolve) => {
|
|
@@ -29,7 +57,9 @@ async function runSingleTest(adapter, test, registryUrl, token, timeout) {
|
|
|
29
57
|
name: test.name,
|
|
30
58
|
passed: false,
|
|
31
59
|
duration: Date.now() - start,
|
|
32
|
-
error: `Test timed out after ${timeout}ms
|
|
60
|
+
error: `Test timed out after ${timeout}ms`,
|
|
61
|
+
hasSubTests,
|
|
62
|
+
subTests: subResults.length > 0 ? subResults : void 0
|
|
33
63
|
});
|
|
34
64
|
}, timeout);
|
|
35
65
|
test.run(ctx).then(() => {
|
|
@@ -37,7 +67,9 @@ async function runSingleTest(adapter, test, registryUrl, token, timeout) {
|
|
|
37
67
|
resolve({
|
|
38
68
|
name: test.name,
|
|
39
69
|
passed: true,
|
|
40
|
-
duration: Date.now() - start
|
|
70
|
+
duration: Date.now() - start,
|
|
71
|
+
hasSubTests,
|
|
72
|
+
subTests: subResults.length > 0 ? subResults : void 0
|
|
41
73
|
});
|
|
42
74
|
}).catch((err) => {
|
|
43
75
|
clearTimeout(timer);
|
|
@@ -45,7 +77,9 @@ async function runSingleTest(adapter, test, registryUrl, token, timeout) {
|
|
|
45
77
|
name: test.name,
|
|
46
78
|
passed: false,
|
|
47
79
|
duration: Date.now() - start,
|
|
48
|
-
error: err instanceof Error ? err.message : String(err)
|
|
80
|
+
error: err instanceof Error ? err.message : String(err),
|
|
81
|
+
hasSubTests,
|
|
82
|
+
subTests: subResults.length > 0 ? subResults : void 0
|
|
49
83
|
});
|
|
50
84
|
});
|
|
51
85
|
});
|
|
@@ -69,7 +103,7 @@ async function runSuite(adapter, tests, registryUrl, token, options) {
|
|
|
69
103
|
require_reporter.reportTestStart(adapter.name, test.name);
|
|
70
104
|
const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);
|
|
71
105
|
results.push(result);
|
|
72
|
-
require_reporter.reportTestResult(result);
|
|
106
|
+
require_reporter.reportTestResult(result, result.hasSubTests);
|
|
73
107
|
}
|
|
74
108
|
const passed = results.filter((r) => r.passed).length;
|
|
75
109
|
const failed = results.filter((r) => !r.passed).length;
|
package/build/cjs/runner.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.cjs","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,WAAA,GAAA,MAAA,SAAmB,2BAA2B;AAEpD,SAAS,QAAQ,aAA6B;AAC5C,KAAI;EACF,MAAM,QAAM,IAAI,IAAA,IAAI,YAAY;AAChC,SAAO,SAAS,MAAI,MAAM,GAAG,KAAK,MAAI,aAAa,WAAW,MAAM;SAC9D;AACN,SAAO;;;AAIX,eAAe,cACb,SACA,MACA,aACA,OACA,
|
|
1
|
+
{"version":3,"file":"runner.cjs","names":[],"sources":["../../src/runner.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { URL } from 'url';\n\nimport { PackageManagerAdapter, SubTestResult, SuiteResult, TestContext, TestDefinition, TestResult } from './types';\nimport { reportSkipped, reportSubTestResult, 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 & { hasSubTests: boolean }> {\n const port = getPort(registryUrl);\n let hasSubTests = false;\n const subResults: SubTestResult[] = [];\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 async subTest(label: string, fn: () => Promise<void>): Promise<void> {\n hasSubTests = true;\n const subStart = Date.now();\n try {\n await fn();\n const duration = Date.now() - subStart;\n subResults.push({ label, passed: true, duration });\n reportSubTestResult(label, true, duration);\n } catch (err) {\n const duration = Date.now() - subStart;\n const error = err instanceof Error ? err.message : String(err);\n subResults.push({ label, passed: false, duration, error });\n reportSubTestResult(label, false, duration);\n throw err;\n }\n },\n };\n\n const start = Date.now();\n\n return new Promise<TestResult & { hasSubTests: boolean }>((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 hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\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 hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\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 hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\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, result.hasSubTests);\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":"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"}
|
|
@@ -1,60 +1,100 @@
|
|
|
1
1
|
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let debug = require("debug");
|
|
3
|
+
debug = require_runtime.__toESM(debug);
|
|
4
|
+
let path = require("path");
|
|
5
|
+
let fs_promises = require("fs/promises");
|
|
2
6
|
let assert = require("assert");
|
|
3
7
|
assert = require_runtime.__toESM(assert);
|
|
4
8
|
//#region src/tests/deprecate.ts
|
|
9
|
+
var debug$1 = (0, debug.default)("verdaccio:e2e-cli:test:deprecate");
|
|
5
10
|
async function publishPkg(ctx, tempFolder, pkgName) {
|
|
11
|
+
if (ctx.adapter.type === "yarn-modern") {
|
|
12
|
+
debug$1("running yarn install before publish for %s", pkgName);
|
|
13
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "install");
|
|
14
|
+
}
|
|
15
|
+
debug$1("publishing %s from %s", pkgName, tempFolder);
|
|
6
16
|
await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
17
|
+
debug$1("published %s successfully", pkgName);
|
|
7
18
|
}
|
|
8
19
|
async function deprecate(ctx, tempFolder, packageVersion, message) {
|
|
9
|
-
|
|
20
|
+
debug$1("deprecating %s with message: %s", packageVersion, message || "(empty, un-deprecate)");
|
|
21
|
+
const jsonFlag = ctx.adapter.type === "yarn-modern" ? [] : ["--json"];
|
|
22
|
+
await ctx.adapter.exec({ cwd: tempFolder }, "deprecate", packageVersion, message, ...jsonFlag, ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
23
|
+
debug$1("deprecate command completed for %s", packageVersion);
|
|
10
24
|
}
|
|
11
|
-
async function getInfo(ctx, pkgName) {
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
async function getInfo(ctx, tempFolder, pkgName) {
|
|
26
|
+
debug$1("fetching info for %s", pkgName);
|
|
27
|
+
const resp = await ctx.adapter.exec({ cwd: tempFolder }, "info", pkgName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
28
|
+
const parsed = JSON.parse(resp.stdout);
|
|
29
|
+
debug$1("info for %s: deprecated=%s", pkgName, parsed.deprecated ?? "(not set)");
|
|
30
|
+
return parsed;
|
|
14
31
|
}
|
|
15
32
|
async function bumpVersion(ctx, tempFolder) {
|
|
16
|
-
|
|
33
|
+
debug$1("bumping version (minor) in %s", tempFolder);
|
|
34
|
+
if (ctx.adapter.type === "yarn-modern") {
|
|
35
|
+
const pkgPath = (0, path.join)(tempFolder, "package.json");
|
|
36
|
+
const pkg = JSON.parse(await (0, fs_promises.readFile)(pkgPath, "utf8"));
|
|
37
|
+
const [major, minor, patch] = pkg.version.split(".").map(Number);
|
|
38
|
+
pkg.version = `${major}.${minor + 1}.${patch}`;
|
|
39
|
+
debug$1("bumped %s to %s", pkgPath, pkg.version);
|
|
40
|
+
await (0, fs_promises.writeFile)(pkgPath, JSON.stringify(pkg, null, 2));
|
|
41
|
+
} else await ctx.adapter.exec({ cwd: tempFolder }, "version", "minor", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
42
|
+
}
|
|
43
|
+
async function prepareDeprecateProject(ctx, pkgName, version) {
|
|
44
|
+
debug$1("preparing project for %s@%s", pkgName, version);
|
|
45
|
+
const { tempFolder } = await ctx.adapter.prepareProject(pkgName, version, ctx.registryUrl, ctx.port, ctx.token);
|
|
46
|
+
if (ctx.adapter.importPlugin) {
|
|
47
|
+
debug$1("importing npm-deprecate plugin into %s", tempFolder);
|
|
48
|
+
await ctx.adapter.importPlugin(tempFolder, "npm-deprecate");
|
|
49
|
+
}
|
|
50
|
+
return tempFolder;
|
|
17
51
|
}
|
|
18
52
|
async function testDeprecate(ctx) {
|
|
19
53
|
const id = ctx.runId;
|
|
20
|
-
const pkgName1 = `@verdaccio/dep1-${id}`;
|
|
21
54
|
const message = "some message";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
await deprecate
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
await ctx.subTest("deprecate single version", async () => {
|
|
56
|
+
const pkgName = `@verdaccio/dep1-${id}`;
|
|
57
|
+
const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
|
|
58
|
+
await publishPkg(ctx, tf, pkgName);
|
|
59
|
+
await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);
|
|
60
|
+
const info = await getInfo(ctx, tf, pkgName);
|
|
61
|
+
assert.default.strictEqual(info.name, pkgName);
|
|
62
|
+
assert.default.strictEqual(info.deprecated, message, "Package should be deprecated");
|
|
63
|
+
});
|
|
64
|
+
await ctx.subTest("un-deprecate", async () => {
|
|
65
|
+
const pkgName = `@verdaccio/dep2-${id}`;
|
|
66
|
+
const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
|
|
67
|
+
await publishPkg(ctx, tf, pkgName);
|
|
68
|
+
await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);
|
|
69
|
+
const info1 = await getInfo(ctx, tf, pkgName);
|
|
70
|
+
assert.default.strictEqual(info1.deprecated, message);
|
|
71
|
+
await deprecate(ctx, tf, `${pkgName}@1.0.0`, "");
|
|
72
|
+
const info2 = await getInfo(ctx, tf, pkgName);
|
|
73
|
+
assert.default.strictEqual(info2.deprecated, void 0, "Package should be un-deprecated");
|
|
74
|
+
});
|
|
75
|
+
await ctx.subTest("deprecate multiple versions", async () => {
|
|
76
|
+
const pkgName = `@verdaccio/dep3-${id}`;
|
|
77
|
+
const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
|
|
78
|
+
await publishPkg(ctx, tf, pkgName);
|
|
79
|
+
for (let i = 0; i < 3; i++) {
|
|
80
|
+
await bumpVersion(ctx, tf);
|
|
81
|
+
await publishPkg(ctx, tf, pkgName);
|
|
82
|
+
}
|
|
83
|
+
await deprecate(ctx, tf, pkgName, message);
|
|
84
|
+
for (const v of [
|
|
85
|
+
"1.0.0",
|
|
86
|
+
"1.1.0",
|
|
87
|
+
"1.2.0",
|
|
88
|
+
"1.3.0"
|
|
89
|
+
]) {
|
|
90
|
+
const info = await getInfo(ctx, tf, `${pkgName}@${v}`);
|
|
91
|
+
assert.default.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);
|
|
92
|
+
}
|
|
93
|
+
await bumpVersion(ctx, tf);
|
|
94
|
+
await publishPkg(ctx, tf, pkgName);
|
|
95
|
+
const info = await getInfo(ctx, tf, `${pkgName}@1.4.0`);
|
|
96
|
+
assert.default.strictEqual(info.deprecated, void 0, "New version should not be deprecated");
|
|
97
|
+
});
|
|
58
98
|
}
|
|
59
99
|
var deprecateTest = {
|
|
60
100
|
name: "deprecate",
|