@verdaccio/e2e-cli 2.10.2 → 3.0.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/Cargo.lock +1591 -0
- package/Cargo.toml +19 -0
- package/bin/e2e-cli.js +26 -6
- package/build/bin/verdaccio-e2e +0 -0
- package/build/cjs/index.cjs +11 -166
- package/build/esm/index.js +10 -153
- package/build/index.d.ts +15 -6
- package/package.json +14 -16
- package/scripts/build-js-package.mjs +25 -0
- package/src/e2e_tests/audit.rs +51 -0
- package/src/e2e_tests/ci.rs +32 -0
- package/src/e2e_tests/deprecate.rs +64 -0
- package/src/e2e_tests/dist_tags.rs +56 -0
- package/src/e2e_tests/info.rs +43 -0
- package/src/e2e_tests/install.rs +27 -0
- package/src/e2e_tests/login.rs +64 -0
- package/src/e2e_tests/mod.rs +104 -0
- package/src/e2e_tests/ping.rs +33 -0
- package/src/e2e_tests/publish.rs +68 -0
- package/src/e2e_tests/search.rs +14 -0
- package/src/e2e_tests/unpublish.rs +37 -0
- package/src/main.rs +1411 -0
- package/src/scenarios/install_multiple_deps.rs +99 -0
- package/src/scenarios/minimum_release_age.rs +45 -0
- package/src/scenarios/mod.rs +11 -0
- package/build/adapters/adapter.d.ts +0 -1
- package/build/adapters/bun.d.ts +0 -2
- package/build/adapters/deno.d.ts +0 -2
- package/build/adapters/index.d.ts +0 -6
- package/build/adapters/npm.d.ts +0 -2
- package/build/adapters/pnpm.d.ts +0 -2
- package/build/adapters/yarn-classic.d.ts +0 -2
- package/build/adapters/yarn-modern.d.ts +0 -2
- package/build/cjs/_virtual/_rolldown/runtime.cjs +0 -23
- package/build/cjs/adapters/bun.cjs +0 -63
- package/build/cjs/adapters/bun.cjs.map +0 -1
- package/build/cjs/adapters/deno.cjs +0 -58
- package/build/cjs/adapters/deno.cjs.map +0 -1
- package/build/cjs/adapters/index.cjs +0 -6
- package/build/cjs/adapters/npm.cjs +0 -75
- package/build/cjs/adapters/npm.cjs.map +0 -1
- package/build/cjs/adapters/pnpm.cjs +0 -104
- package/build/cjs/adapters/pnpm.cjs.map +0 -1
- package/build/cjs/adapters/yarn-classic.cjs +0 -98
- package/build/cjs/adapters/yarn-classic.cjs.map +0 -1
- package/build/cjs/adapters/yarn-modern.cjs +0 -206
- package/build/cjs/adapters/yarn-modern.cjs.map +0 -1
- package/build/cjs/index.cjs.map +0 -1
- package/build/cjs/reporter.cjs +0 -113
- package/build/cjs/reporter.cjs.map +0 -1
- package/build/cjs/runner.cjs +0 -141
- package/build/cjs/runner.cjs.map +0 -1
- package/build/cjs/scenarios/index.cjs +0 -8
- package/build/cjs/scenarios/index.cjs.map +0 -1
- package/build/cjs/scenarios/install-multiple-deps.cjs +0 -117
- package/build/cjs/scenarios/install-multiple-deps.cjs.map +0 -1
- package/build/cjs/scenarios/minimum-release-age.cjs +0 -112
- package/build/cjs/scenarios/minimum-release-age.cjs.map +0 -1
- package/build/cjs/tests/audit.cjs +0 -47
- package/build/cjs/tests/audit.cjs.map +0 -1
- package/build/cjs/tests/ci.cjs +0 -83
- package/build/cjs/tests/ci.cjs.map +0 -1
- package/build/cjs/tests/deprecate.cjs +0 -107
- package/build/cjs/tests/deprecate.cjs.map +0 -1
- package/build/cjs/tests/dist-tags.cjs +0 -43
- package/build/cjs/tests/dist-tags.cjs.map +0 -1
- package/build/cjs/tests/index.cjs +0 -33
- package/build/cjs/tests/index.cjs.map +0 -1
- package/build/cjs/tests/info.cjs +0 -42
- package/build/cjs/tests/info.cjs.map +0 -1
- package/build/cjs/tests/install.cjs +0 -27
- package/build/cjs/tests/install.cjs.map +0 -1
- package/build/cjs/tests/login.cjs +0 -117
- package/build/cjs/tests/login.cjs.map +0 -1
- package/build/cjs/tests/ping.cjs +0 -30
- package/build/cjs/tests/ping.cjs.map +0 -1
- package/build/cjs/tests/publish.cjs +0 -37
- package/build/cjs/tests/publish.cjs.map +0 -1
- package/build/cjs/tests/search.cjs +0 -19
- package/build/cjs/tests/search.cjs.map +0 -1
- package/build/cjs/tests/unpublish.cjs +0 -40
- package/build/cjs/tests/unpublish.cjs.map +0 -1
- package/build/cjs/utils/info.cjs +0 -25
- package/build/cjs/utils/info.cjs.map +0 -1
- package/build/cjs/utils/process.cjs +0 -85
- package/build/cjs/utils/process.cjs.map +0 -1
- package/build/cjs/utils/project.cjs +0 -55
- package/build/cjs/utils/project.cjs.map +0 -1
- package/build/cjs/utils/registry-client.cjs +0 -56
- package/build/cjs/utils/registry-client.cjs.map +0 -1
- package/build/esm/adapters/bun.js +0 -61
- package/build/esm/adapters/bun.js.map +0 -1
- package/build/esm/adapters/deno.js +0 -56
- package/build/esm/adapters/deno.js.map +0 -1
- package/build/esm/adapters/index.js +0 -7
- package/build/esm/adapters/npm.js +0 -73
- package/build/esm/adapters/npm.js.map +0 -1
- package/build/esm/adapters/pnpm.js +0 -102
- package/build/esm/adapters/pnpm.js.map +0 -1
- package/build/esm/adapters/yarn-classic.js +0 -96
- package/build/esm/adapters/yarn-classic.js.map +0 -1
- package/build/esm/adapters/yarn-modern.js +0 -203
- package/build/esm/adapters/yarn-modern.js.map +0 -1
- package/build/esm/index.js.map +0 -1
- package/build/esm/reporter.js +0 -107
- package/build/esm/reporter.js.map +0 -1
- package/build/esm/runner.js +0 -138
- package/build/esm/runner.js.map +0 -1
- package/build/esm/scenarios/index.js +0 -8
- package/build/esm/scenarios/index.js.map +0 -1
- package/build/esm/scenarios/install-multiple-deps.js +0 -114
- package/build/esm/scenarios/install-multiple-deps.js.map +0 -1
- package/build/esm/scenarios/minimum-release-age.js +0 -109
- package/build/esm/scenarios/minimum-release-age.js.map +0 -1
- package/build/esm/tests/audit.js +0 -44
- package/build/esm/tests/audit.js.map +0 -1
- package/build/esm/tests/ci.js +0 -80
- package/build/esm/tests/ci.js.map +0 -1
- package/build/esm/tests/deprecate.js +0 -104
- package/build/esm/tests/deprecate.js.map +0 -1
- package/build/esm/tests/dist-tags.js +0 -41
- package/build/esm/tests/dist-tags.js.map +0 -1
- package/build/esm/tests/index.js +0 -33
- package/build/esm/tests/index.js.map +0 -1
- package/build/esm/tests/info.js +0 -40
- package/build/esm/tests/info.js.map +0 -1
- package/build/esm/tests/install.js +0 -25
- package/build/esm/tests/install.js.map +0 -1
- package/build/esm/tests/login.js +0 -113
- package/build/esm/tests/login.js.map +0 -1
- package/build/esm/tests/ping.js +0 -28
- package/build/esm/tests/ping.js.map +0 -1
- package/build/esm/tests/publish.js +0 -35
- package/build/esm/tests/publish.js.map +0 -1
- package/build/esm/tests/search.js +0 -17
- package/build/esm/tests/search.js.map +0 -1
- package/build/esm/tests/unpublish.js +0 -38
- package/build/esm/tests/unpublish.js.map +0 -1
- package/build/esm/utils/info.js +0 -24
- package/build/esm/utils/info.js.map +0 -1
- package/build/esm/utils/process.js +0 -82
- package/build/esm/utils/process.js.map +0 -1
- package/build/esm/utils/project.js +0 -50
- package/build/esm/utils/project.js.map +0 -1
- package/build/esm/utils/registry-client.js +0 -53
- package/build/esm/utils/registry-client.js.map +0 -1
- package/build/reporter.d.ts +0 -7
- package/build/runner.d.ts +0 -13
- package/build/scenarios/index.d.ts +0 -5
- package/build/scenarios/install-multiple-deps.d.ts +0 -2
- package/build/scenarios/minimum-release-age.d.ts +0 -11
- package/build/tests/audit.d.ts +0 -2
- package/build/tests/ci.d.ts +0 -2
- package/build/tests/deprecate.d.ts +0 -2
- package/build/tests/dist-tags.d.ts +0 -2
- package/build/tests/index.d.ts +0 -15
- package/build/tests/info.d.ts +0 -2
- package/build/tests/install.d.ts +0 -2
- package/build/tests/login.d.ts +0 -2
- package/build/tests/ping.d.ts +0 -2
- package/build/tests/publish.d.ts +0 -2
- package/build/tests/search.d.ts +0 -2
- package/build/tests/unpublish.d.ts +0 -2
- package/build/types.d.ts +0 -81
- package/build/utils/index.d.ts +0 -4
- package/build/utils/info.d.ts +0 -14
- package/build/utils/process.d.ts +0 -4
- package/build/utils/project.d.ts +0 -6
- package/build/utils/registry-client.d.ts +0 -15
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { normalizeInfo } from "../utils/info.js";
|
|
2
|
-
import buildDebug from "debug";
|
|
3
|
-
import assert from "assert";
|
|
4
|
-
//#region src/scenarios/install-multiple-deps.ts
|
|
5
|
-
var debug = buildDebug("verdaccio:e2e-cli:scenario:install-multiple-deps");
|
|
6
|
-
/**
|
|
7
|
-
* Scenario: install-multiple-deps
|
|
8
|
-
*
|
|
9
|
-
* Publishes several packages to the registry (some scoped, some unscoped,
|
|
10
|
-
* some with inter-dependencies), then creates a consumer project that
|
|
11
|
-
* depends on all of them and runs `install`.
|
|
12
|
-
*
|
|
13
|
-
* This exercises the registry under realistic load:
|
|
14
|
-
* - many parallel tarball downloads
|
|
15
|
-
* - metadata resolution for multiple packages
|
|
16
|
-
* - scoped-package authentication
|
|
17
|
-
* - transitive dependency resolution
|
|
18
|
-
*/
|
|
19
|
-
var SEED_PACKAGES_COUNT = 5;
|
|
20
|
-
/**
|
|
21
|
-
* Parse `info --json` output across all adapters.
|
|
22
|
-
* Yarn classic wraps the result in NDJSON lines with `{ type: "inspect", data: { ... } }`.
|
|
23
|
-
*/
|
|
24
|
-
function parseInfoOutput(stdout, adapterType) {
|
|
25
|
-
if (adapterType === "yarn-classic") {
|
|
26
|
-
const lines = stdout.split("\n").filter(Boolean);
|
|
27
|
-
for (const line of lines) try {
|
|
28
|
-
const obj = JSON.parse(line);
|
|
29
|
-
if (obj.type === "inspect" && obj.data) return obj.data;
|
|
30
|
-
} catch {}
|
|
31
|
-
return normalizeInfo(JSON.parse(stdout));
|
|
32
|
-
}
|
|
33
|
-
return normalizeInfo(JSON.parse(stdout));
|
|
34
|
-
}
|
|
35
|
-
async function publishSeedPackage(ctx, pkgName, version, dependencies = {}) {
|
|
36
|
-
debug("publishing seed package %s@%s", pkgName, version);
|
|
37
|
-
const { tempFolder } = await ctx.adapter.prepareProject(pkgName, version, ctx.registryUrl, ctx.port, ctx.token, dependencies);
|
|
38
|
-
if (ctx.adapter.type === "yarn-modern") await ctx.adapter.exec({ cwd: tempFolder }, "install");
|
|
39
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
40
|
-
debug("published %s@%s", pkgName, version);
|
|
41
|
-
}
|
|
42
|
-
async function testInstallMultipleDeps(ctx) {
|
|
43
|
-
const id = ctx.runId;
|
|
44
|
-
let projectCwd = "";
|
|
45
|
-
await ctx.subTest("publish seed packages", async () => {
|
|
46
|
-
for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) await publishSeedPackage(ctx, `@verdaccio/seed-${id}-${i}`, "1.0.0");
|
|
47
|
-
const sharedPkg = `@verdaccio/seed-shared-${id}`;
|
|
48
|
-
await publishSeedPackage(ctx, sharedPkg, "1.0.0");
|
|
49
|
-
await publishSeedPackage(ctx, `@verdaccio/seed-mid-${id}`, "1.0.0", {
|
|
50
|
-
[`@verdaccio/seed-${id}-1`]: "1.0.0",
|
|
51
|
-
[`@verdaccio/seed-${id}-2`]: "1.0.0",
|
|
52
|
-
[sharedPkg]: "1.0.0"
|
|
53
|
-
});
|
|
54
|
-
debug("all seed packages published");
|
|
55
|
-
});
|
|
56
|
-
await ctx.subTest("install all dependencies in consumer project", async () => {
|
|
57
|
-
const consumerDeps = {};
|
|
58
|
-
for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) consumerDeps[`@verdaccio/seed-${id}-${i}`] = "1.0.0";
|
|
59
|
-
consumerDeps[`@verdaccio/seed-mid-${id}`] = "1.0.0";
|
|
60
|
-
consumerDeps[`@verdaccio/seed-shared-${id}`] = "1.0.0";
|
|
61
|
-
const consumerName = `@verdaccio/consumer-${id}`;
|
|
62
|
-
const { tempFolder } = await ctx.adapter.prepareProject(consumerName, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, consumerDeps);
|
|
63
|
-
projectCwd = tempFolder;
|
|
64
|
-
debug("installing %d dependencies in consumer project", Object.keys(consumerDeps).length);
|
|
65
|
-
const args = ["install", ...ctx.adapter.registryArg(ctx.registryUrl)];
|
|
66
|
-
await ctx.adapter.exec({ cwd: tempFolder }, ...args);
|
|
67
|
-
debug("install completed for consumer project");
|
|
68
|
-
});
|
|
69
|
-
await ctx.subTest("verify installed packages", async () => {
|
|
70
|
-
for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {
|
|
71
|
-
const name = `@verdaccio/seed-${id}-${i}`;
|
|
72
|
-
const info = parseInfoOutput((await ctx.adapter.exec({ cwd: projectCwd }, "info", name, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout, ctx.adapter.type);
|
|
73
|
-
assert.strictEqual(info.name, name, `Expected package name "${name}"`);
|
|
74
|
-
assert.strictEqual(info.version, "1.0.0", `Expected version 1.0.0 for ${name}`);
|
|
75
|
-
}
|
|
76
|
-
const midName = `@verdaccio/seed-mid-${id}`;
|
|
77
|
-
const midInfo = parseInfoOutput((await ctx.adapter.exec({ cwd: projectCwd }, "info", midName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout, ctx.adapter.type);
|
|
78
|
-
assert.strictEqual(midInfo.name, midName);
|
|
79
|
-
const deps = midInfo.dependencies || {};
|
|
80
|
-
assert.strictEqual(deps[`@verdaccio/seed-${id}-1`], "1.0.0", "Intermediate should depend on seed-1");
|
|
81
|
-
assert.strictEqual(deps[`@verdaccio/seed-${id}-2`], "1.0.0", "Intermediate should depend on seed-2");
|
|
82
|
-
assert.strictEqual(deps[`@verdaccio/seed-shared-${id}`], "1.0.0", "Intermediate should depend on shared");
|
|
83
|
-
debug("all packages verified");
|
|
84
|
-
});
|
|
85
|
-
await ctx.subTest("update and re-install", async () => {
|
|
86
|
-
const leafName = `@verdaccio/seed-${id}-1`;
|
|
87
|
-
await publishSeedPackage(ctx, leafName, "2.0.0");
|
|
88
|
-
const sharedName = `@verdaccio/seed-shared-${id}`;
|
|
89
|
-
await publishSeedPackage(ctx, sharedName, "2.0.0");
|
|
90
|
-
const consumerDeps = {
|
|
91
|
-
[leafName]: "^1.0.0",
|
|
92
|
-
[sharedName]: "^1.0.0"
|
|
93
|
-
};
|
|
94
|
-
const consumerName = `@verdaccio/consumer-update-${id}`;
|
|
95
|
-
const { tempFolder } = await ctx.adapter.prepareProject(consumerName, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, consumerDeps);
|
|
96
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "install", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
97
|
-
const leafInfo = parseInfoOutput((await ctx.adapter.exec({ cwd: tempFolder }, "info", leafName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout, ctx.adapter.type);
|
|
98
|
-
assert.strictEqual(leafInfo["dist-tags"]?.latest ?? leafInfo.version, "2.0.0", `Expected latest version of ${leafName} to be 2.0.0`);
|
|
99
|
-
debug("update and re-install verified");
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
var installMultipleDepsScenario = {
|
|
103
|
-
name: "scenario:install-multiple-deps",
|
|
104
|
-
requires: [
|
|
105
|
-
"publish",
|
|
106
|
-
"install",
|
|
107
|
-
"info"
|
|
108
|
-
],
|
|
109
|
-
run: testInstallMultipleDeps
|
|
110
|
-
};
|
|
111
|
-
//#endregion
|
|
112
|
-
export { installMultipleDepsScenario };
|
|
113
|
-
|
|
114
|
-
//# sourceMappingURL=install-multiple-deps.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"install-multiple-deps.js","names":[],"sources":["../../../src/scenarios/install-multiple-deps.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { normalizeInfo } from '../utils/info';\n\nconst debug = buildDebug('verdaccio:e2e-cli:scenario:install-multiple-deps');\n\n/**\n * Scenario: install-multiple-deps\n *\n * Publishes several packages to the registry (some scoped, some unscoped,\n * some with inter-dependencies), then creates a consumer project that\n * depends on all of them and runs `install`.\n *\n * This exercises the registry under realistic load:\n * - many parallel tarball downloads\n * - metadata resolution for multiple packages\n * - scoped-package authentication\n * - transitive dependency resolution\n */\n\nconst SEED_PACKAGES_COUNT = 5;\n\n/**\n * Parse `info --json` output across all adapters.\n * Yarn classic wraps the result in NDJSON lines with `{ type: \"inspect\", data: { ... } }`.\n */\nfunction parseInfoOutput(stdout: string, adapterType: string): any {\n if (adapterType === 'yarn-classic') {\n // Yarn classic outputs NDJSON — find the \"inspect\" line that holds package data\n const lines = stdout.split('\\n').filter(Boolean);\n for (const line of lines) {\n try {\n const obj = JSON.parse(line);\n if (obj.type === 'inspect' && obj.data) {\n return obj.data;\n }\n } catch {\n // skip non-JSON lines\n }\n }\n // Fallback: try parsing the whole output\n return normalizeInfo(JSON.parse(stdout));\n }\n return normalizeInfo(JSON.parse(stdout));\n}\n\nasync function publishSeedPackage(\n ctx: TestContext,\n pkgName: string,\n version: string,\n dependencies: Record<string, string> = {}\n): Promise<void> {\n debug('publishing seed package %s@%s', pkgName, version);\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n version,\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n dependencies\n );\n\n if (ctx.adapter.type === 'yarn-modern') {\n await ctx.adapter.exec({ cwd: tempFolder }, 'install');\n }\n\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n debug('published %s@%s', pkgName, version);\n}\n\nasync function testInstallMultipleDeps(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Shared project folder used as cwd for info commands across subtests.\n // Yarn modern requires a project context (package.json + .yarnrc.yml) for `yarn npm info`.\n let projectCwd = '';\n\n // --- Phase 1: Publish a tree of seed packages ---\n await ctx.subTest('publish seed packages', async () => {\n // Leaf packages (no dependencies of their own)\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n const name = `@verdaccio/seed-${id}-${i}`;\n await publishSeedPackage(ctx, name, '1.0.0');\n }\n\n // A \"shared\" package that multiple consumers will pull in\n const sharedPkg = `@verdaccio/seed-shared-${id}`;\n await publishSeedPackage(ctx, sharedPkg, '1.0.0');\n\n // An intermediate package that depends on some leaf packages + shared\n const intermediatePkg = `@verdaccio/seed-mid-${id}`;\n await publishSeedPackage(ctx, intermediatePkg, '1.0.0', {\n [`@verdaccio/seed-${id}-1`]: '1.0.0',\n [`@verdaccio/seed-${id}-2`]: '1.0.0',\n [sharedPkg]: '1.0.0',\n });\n\n debug('all seed packages published');\n });\n\n // --- Phase 2: Create a consumer project that depends on everything ---\n await ctx.subTest('install all dependencies in consumer project', async () => {\n const consumerDeps: Record<string, string> = {};\n\n // Direct deps on all leaf packages\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n consumerDeps[`@verdaccio/seed-${id}-${i}`] = '1.0.0';\n }\n\n // Also depend on the intermediate (pulls in transitive deps)\n consumerDeps[`@verdaccio/seed-mid-${id}`] = '1.0.0';\n\n // And the shared package directly (already a transitive dep of mid)\n consumerDeps[`@verdaccio/seed-shared-${id}`] = '1.0.0';\n\n const consumerName = `@verdaccio/consumer-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n consumerName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n consumerDeps\n );\n\n projectCwd = tempFolder;\n\n debug('installing %d dependencies in consumer project', Object.keys(consumerDeps).length);\n\n const args = ['install', ...ctx.adapter.registryArg(ctx.registryUrl)];\n await ctx.adapter.exec({ cwd: tempFolder }, ...args);\n\n debug('install completed for consumer project');\n });\n\n // --- Phase 3: Verify all packages resolved correctly ---\n await ctx.subTest('verify installed packages', async () => {\n // Check that each seed package is retrievable via `info`\n for (let i = 1; i <= SEED_PACKAGES_COUNT; i++) {\n const name = `@verdaccio/seed-${id}-${i}`;\n const resp = await ctx.adapter.exec(\n { cwd: projectCwd },\n 'info',\n name,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const info = parseInfoOutput(resp.stdout, ctx.adapter.type);\n assert.strictEqual(info.name, name, `Expected package name \"${name}\"`);\n assert.strictEqual(info.version, '1.0.0', `Expected version 1.0.0 for ${name}`);\n }\n\n // Verify intermediate package has correct dependencies in registry metadata\n const midName = `@verdaccio/seed-mid-${id}`;\n const resp = await ctx.adapter.exec(\n { cwd: projectCwd },\n 'info',\n midName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const midInfo = parseInfoOutput(resp.stdout, ctx.adapter.type);\n assert.strictEqual(midInfo.name, midName);\n\n const deps = midInfo.dependencies || {};\n assert.strictEqual(\n deps[`@verdaccio/seed-${id}-1`],\n '1.0.0',\n 'Intermediate should depend on seed-1'\n );\n assert.strictEqual(\n deps[`@verdaccio/seed-${id}-2`],\n '1.0.0',\n 'Intermediate should depend on seed-2'\n );\n assert.strictEqual(\n deps[`@verdaccio/seed-shared-${id}`],\n '1.0.0',\n 'Intermediate should depend on shared'\n );\n\n debug('all packages verified');\n });\n\n // --- Phase 4: Publish updated versions and re-install ---\n await ctx.subTest('update and re-install', async () => {\n // Publish v2 of a leaf and the shared package\n const leafName = `@verdaccio/seed-${id}-1`;\n await publishSeedPackage(ctx, leafName, '2.0.0');\n\n const sharedName = `@verdaccio/seed-shared-${id}`;\n await publishSeedPackage(ctx, sharedName, '2.0.0');\n\n // Create a new consumer that uses ^ ranges — should pick up 2.0.0\n const consumerDeps: Record<string, string> = {\n [leafName]: '^1.0.0',\n [sharedName]: '^1.0.0',\n };\n\n const consumerName = `@verdaccio/consumer-update-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n consumerName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n consumerDeps\n );\n\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'install',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n // Verify that the registry now serves both versions\n const leafResp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'info',\n leafName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const leafInfo = parseInfoOutput(leafResp.stdout, ctx.adapter.type);\n\n // dist-tags.latest should be 2.0.0\n assert.strictEqual(\n leafInfo['dist-tags']?.latest ?? leafInfo.version,\n '2.0.0',\n `Expected latest version of ${leafName} to be 2.0.0`\n );\n\n debug('update and re-install verified');\n });\n}\n\nexport const installMultipleDepsScenario: TestDefinition = {\n name: 'scenario:install-multiple-deps',\n requires: ['publish', 'install', 'info'],\n run: testInstallMultipleDeps,\n};\n"],"mappings":"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"}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import buildDebug from "debug";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { writeFile } from "fs/promises";
|
|
4
|
-
import assert from "assert";
|
|
5
|
-
//#region src/scenarios/minimum-release-age.ts
|
|
6
|
-
var debug = buildDebug("verdaccio:e2e-cli:scenario:minimum-release-age");
|
|
7
|
-
/**
|
|
8
|
-
* Scenario: minimum-release-age (pnpm 11.1+ only)
|
|
9
|
-
*
|
|
10
|
-
* Exercises pnpm's `minimumReleaseAge` cooldown together with
|
|
11
|
-
* `minimumReleaseAgeExclude`. With a 7-day (10080 minute) cooldown, freshly
|
|
12
|
-
* published versions are normally not installable until they age past the
|
|
13
|
-
* threshold — but packages matching the exclude globs bypass the check.
|
|
14
|
-
*
|
|
15
|
-
* minimumReleaseAge: 10080
|
|
16
|
-
* minimumReleaseAgeExclude:
|
|
17
|
-
* - '@verdaccio/*'
|
|
18
|
-
* - 'verdaccio-*'
|
|
19
|
-
*
|
|
20
|
-
* The scenario publishes brand-new (age ~0) packages and asserts:
|
|
21
|
-
* - an excluded scoped package (@verdaccio/*) installs despite the cooldown
|
|
22
|
-
* - an excluded unscoped package (verdaccio-*) installs despite the cooldown
|
|
23
|
-
* - a non-excluded package is blocked by the cooldown (proving it is active)
|
|
24
|
-
*
|
|
25
|
-
* pnpm reads these settings from `pnpm-workspace.yaml`, mirroring the
|
|
26
|
-
* configuration used by the repo root. The cooldown is only enforced from
|
|
27
|
-
* pnpm 11.1.0 onward (11.0.x silently ignores it), so the scenario is gated to
|
|
28
|
-
* that version range — see {@link isPnpm11Plus}.
|
|
29
|
-
*/
|
|
30
|
-
var MINIMUM_RELEASE_AGE = 10080;
|
|
31
|
-
var PNPM_WORKSPACE_YAML = [
|
|
32
|
-
`minimumReleaseAge: ${MINIMUM_RELEASE_AGE}`,
|
|
33
|
-
"minimumReleaseAgeExclude:",
|
|
34
|
-
...["@verdaccio/*", "verdaccio-*"].map((glob) => ` - '${glob}'`),
|
|
35
|
-
""
|
|
36
|
-
].join("\n");
|
|
37
|
-
/**
|
|
38
|
-
* True only for pnpm versions that actually enforce minimumReleaseAge.
|
|
39
|
-
*
|
|
40
|
-
* The cooldown is honored in pnpm 11.1.0+, but it is silently ignored in
|
|
41
|
-
* 11.0.0 / 11.0.1 (and the 11.0.0 release candidates) — those versions install
|
|
42
|
-
* brand-new packages regardless of the configured cooldown. We scope this
|
|
43
|
-
* scenario to pnpm 11.1.0 and newer so it doesn't false-fail on that regression.
|
|
44
|
-
*/
|
|
45
|
-
function isPnpm11Plus(adapter) {
|
|
46
|
-
if (adapter.type !== "pnpm") return false;
|
|
47
|
-
const match = adapter.name.match(/pnpm@(\d+)\.(\d+)/);
|
|
48
|
-
if (!match) return false;
|
|
49
|
-
const major = parseInt(match[1], 10);
|
|
50
|
-
const minor = parseInt(match[2], 10);
|
|
51
|
-
return major > 11 || major === 11 && minor >= 1;
|
|
52
|
-
}
|
|
53
|
-
async function publishPackage(ctx, pkgName, version) {
|
|
54
|
-
debug("publishing %s@%s", pkgName, version);
|
|
55
|
-
const { tempFolder } = await ctx.adapter.prepareProject(pkgName, version, ctx.registryUrl, ctx.port, ctx.token);
|
|
56
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
57
|
-
debug("published %s@%s", pkgName, version);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Build a consumer project with the minimumReleaseAge cooldown configured in
|
|
61
|
-
* pnpm-workspace.yaml, depending on the given packages.
|
|
62
|
-
*/
|
|
63
|
-
async function prepareCooldownConsumer(ctx, consumerName, dependencies) {
|
|
64
|
-
const { tempFolder } = await ctx.adapter.prepareProject(consumerName, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, dependencies);
|
|
65
|
-
await writeFile(join(tempFolder, "pnpm-workspace.yaml"), PNPM_WORKSPACE_YAML);
|
|
66
|
-
debug("prepared cooldown consumer %s at %s", consumerName, tempFolder);
|
|
67
|
-
return tempFolder;
|
|
68
|
-
}
|
|
69
|
-
async function testMinimumReleaseAge(ctx) {
|
|
70
|
-
const id = ctx.runId;
|
|
71
|
-
const excludedScoped = `@verdaccio/release-age-${id}`;
|
|
72
|
-
const excludedUnscoped = `verdaccio-release-age-${id}`;
|
|
73
|
-
const blocked = `e2e-release-age-blocked-${id}`;
|
|
74
|
-
await ctx.subTest("publish fresh packages", async () => {
|
|
75
|
-
await publishPackage(ctx, excludedScoped, "1.0.0");
|
|
76
|
-
await publishPackage(ctx, excludedUnscoped, "1.0.0");
|
|
77
|
-
await publishPackage(ctx, blocked, "1.0.0");
|
|
78
|
-
});
|
|
79
|
-
await ctx.subTest("excluded packages bypass the cooldown", async () => {
|
|
80
|
-
const tempFolder = await prepareCooldownConsumer(ctx, `@verdaccio/consumer-excluded-${id}`, {
|
|
81
|
-
[excludedScoped]: "1.0.0",
|
|
82
|
-
[excludedUnscoped]: "1.0.0"
|
|
83
|
-
});
|
|
84
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "install", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
85
|
-
debug("excluded packages installed successfully under cooldown");
|
|
86
|
-
});
|
|
87
|
-
await ctx.subTest("non-excluded fresh package is blocked", async () => {
|
|
88
|
-
const tempFolder = await prepareCooldownConsumer(ctx, `e2e-consumer-blocked-${id}`, { [blocked]: "1.0.0" });
|
|
89
|
-
let errorMessage = "";
|
|
90
|
-
try {
|
|
91
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "install", "--frozen-lockfile=false", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
92
|
-
} catch (err) {
|
|
93
|
-
errorMessage = err instanceof Error ? err.message : String(err);
|
|
94
|
-
debug("install correctly rejected by cooldown: %s", errorMessage);
|
|
95
|
-
}
|
|
96
|
-
assert.ok(errorMessage, `Expected install of fresh non-excluded package "${blocked}" to be blocked by minimumReleaseAge (${MINIMUM_RELEASE_AGE} min), but it succeeded`);
|
|
97
|
-
assert.ok(/minimumReleaseAge|NO_MATURE_MATCHING_VERSION/i.test(errorMessage), `Install of "${blocked}" failed for an unexpected reason (expected a minimumReleaseAge cooldown error):\n${errorMessage}`);
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
var minimumReleaseAgeScenario = {
|
|
101
|
-
name: "scenario:minimum-release-age",
|
|
102
|
-
requires: ["publish", "install"],
|
|
103
|
-
appliesTo: isPnpm11Plus,
|
|
104
|
-
run: testMinimumReleaseAge
|
|
105
|
-
};
|
|
106
|
-
//#endregion
|
|
107
|
-
export { minimumReleaseAgeScenario };
|
|
108
|
-
|
|
109
|
-
//# sourceMappingURL=minimum-release-age.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"minimum-release-age.js","names":[],"sources":["../../../src/scenarios/minimum-release-age.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\nimport { writeFile } from 'fs/promises';\nimport { join } from 'path';\n\nimport { PackageManagerAdapter, TestContext, TestDefinition } from '../types';\n\nconst debug = buildDebug('verdaccio:e2e-cli:scenario:minimum-release-age');\n\n/**\n * Scenario: minimum-release-age (pnpm 11.1+ only)\n *\n * Exercises pnpm's `minimumReleaseAge` cooldown together with\n * `minimumReleaseAgeExclude`. With a 7-day (10080 minute) cooldown, freshly\n * published versions are normally not installable until they age past the\n * threshold — but packages matching the exclude globs bypass the check.\n *\n * minimumReleaseAge: 10080\n * minimumReleaseAgeExclude:\n * - '@verdaccio/*'\n * - 'verdaccio-*'\n *\n * The scenario publishes brand-new (age ~0) packages and asserts:\n * - an excluded scoped package (@verdaccio/*) installs despite the cooldown\n * - an excluded unscoped package (verdaccio-*) installs despite the cooldown\n * - a non-excluded package is blocked by the cooldown (proving it is active)\n *\n * pnpm reads these settings from `pnpm-workspace.yaml`, mirroring the\n * configuration used by the repo root. The cooldown is only enforced from\n * pnpm 11.1.0 onward (11.0.x silently ignores it), so the scenario is gated to\n * that version range — see {@link isPnpm11Plus}.\n */\n\nconst MINIMUM_RELEASE_AGE = 10080; // 7 days, in minutes\nconst MINIMUM_RELEASE_AGE_EXCLUDE = ['@verdaccio/*', 'verdaccio-*'];\n\nconst PNPM_WORKSPACE_YAML = [\n `minimumReleaseAge: ${MINIMUM_RELEASE_AGE}`,\n 'minimumReleaseAgeExclude:',\n ...MINIMUM_RELEASE_AGE_EXCLUDE.map((glob) => ` - '${glob}'`),\n '',\n].join('\\n');\n\n/**\n * True only for pnpm versions that actually enforce minimumReleaseAge.\n *\n * The cooldown is honored in pnpm 11.1.0+, but it is silently ignored in\n * 11.0.0 / 11.0.1 (and the 11.0.0 release candidates) — those versions install\n * brand-new packages regardless of the configured cooldown. We scope this\n * scenario to pnpm 11.1.0 and newer so it doesn't false-fail on that regression.\n */\nexport function isPnpm11Plus(adapter: PackageManagerAdapter): boolean {\n if (adapter.type !== 'pnpm') {\n return false;\n }\n const match = adapter.name.match(/pnpm@(\\d+)\\.(\\d+)/);\n if (!match) {\n return false;\n }\n const major = parseInt(match[1], 10);\n const minor = parseInt(match[2], 10);\n return major > 11 || (major === 11 && minor >= 1);\n}\n\nasync function publishPackage(\n ctx: TestContext,\n pkgName: string,\n version: string\n): Promise<void> {\n debug('publishing %s@%s', pkgName, version);\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n version,\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n debug('published %s@%s', pkgName, version);\n}\n\n/**\n * Build a consumer project with the minimumReleaseAge cooldown configured in\n * pnpm-workspace.yaml, depending on the given packages.\n */\nasync function prepareCooldownConsumer(\n ctx: TestContext,\n consumerName: string,\n dependencies: Record<string, string>\n): Promise<string> {\n const { tempFolder } = await ctx.adapter.prepareProject(\n consumerName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n dependencies\n );\n await writeFile(join(tempFolder, 'pnpm-workspace.yaml'), PNPM_WORKSPACE_YAML);\n debug('prepared cooldown consumer %s at %s', consumerName, tempFolder);\n return tempFolder;\n}\n\nasync function testMinimumReleaseAge(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n const excludedScoped = `@verdaccio/release-age-${id}`;\n const excludedUnscoped = `verdaccio-release-age-${id}`;\n const blocked = `e2e-release-age-blocked-${id}`;\n\n // --- Phase 1: Publish brand-new (age ~0) packages ---\n await ctx.subTest('publish fresh packages', async () => {\n await publishPackage(ctx, excludedScoped, '1.0.0');\n await publishPackage(ctx, excludedUnscoped, '1.0.0');\n await publishPackage(ctx, blocked, '1.0.0');\n });\n\n // --- Phase 2: Excluded packages install despite the cooldown ---\n await ctx.subTest('excluded packages bypass the cooldown', async () => {\n const tempFolder = await prepareCooldownConsumer(ctx, `@verdaccio/consumer-excluded-${id}`, {\n [excludedScoped]: '1.0.0',\n [excludedUnscoped]: '1.0.0',\n });\n\n // Should succeed: both deps match the exclude globs.\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'install',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n debug('excluded packages installed successfully under cooldown');\n });\n\n // --- Phase 3: Non-excluded fresh package is blocked by the cooldown ---\n await ctx.subTest('non-excluded fresh package is blocked', async () => {\n const tempFolder = await prepareCooldownConsumer(ctx, `e2e-consumer-blocked-${id}`, {\n [blocked]: '1.0.0',\n });\n\n let errorMessage = '';\n try {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'install',\n '--frozen-lockfile=false',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n } catch (err) {\n errorMessage = err instanceof Error ? err.message : String(err);\n debug('install correctly rejected by cooldown: %s', errorMessage);\n }\n\n assert.ok(\n errorMessage,\n `Expected install of fresh non-excluded package \"${blocked}\" to be blocked by ` +\n `minimumReleaseAge (${MINIMUM_RELEASE_AGE} min), but it succeeded`\n );\n // pnpm reports ERR_PNPM_NO_MATURE_MATCHING_VERSION / \"minimumReleaseAge\" when a\n // version is too new. Assert the failure is the cooldown, not an unrelated error.\n assert.ok(\n /minimumReleaseAge|NO_MATURE_MATCHING_VERSION/i.test(errorMessage),\n `Install of \"${blocked}\" failed for an unexpected reason (expected a minimumReleaseAge ` +\n `cooldown error):\\n${errorMessage}`\n );\n });\n}\n\nexport const minimumReleaseAgeScenario: TestDefinition = {\n name: 'scenario:minimum-release-age',\n requires: ['publish', 'install'],\n appliesTo: isPnpm11Plus,\n run: testMinimumReleaseAge,\n};\n"],"mappings":";;;;;AAOA,IAAM,QAAQ,WAAW,iDAAiD;;;;;;;;;;;;;;;;;;;;;;;;AA0B1E,IAAM,sBAAsB;AAG5B,IAAM,sBAAsB;CAC1B,sBAAsB;CACtB;CACA,GAAG,CALgC,gBAAgB,cAKhD,CAA4B,KAAK,SAAS,QAAQ,KAAK,GAAG;CAC7D;CACD,CAAC,KAAK,KAAK;;;;;;;;;AAUZ,SAAgB,aAAa,SAAyC;CACpE,IAAI,QAAQ,SAAS,QACnB,OAAO;CAET,MAAM,QAAQ,QAAQ,KAAK,MAAM,oBAAoB;CACrD,IAAI,CAAC,OACH,OAAO;CAET,MAAM,QAAQ,SAAS,MAAM,IAAI,GAAG;CACpC,MAAM,QAAQ,SAAS,MAAM,IAAI,GAAG;CACpC,OAAO,QAAQ,MAAO,UAAU,MAAM,SAAS;;AAGjD,eAAe,eACb,KACA,SACA,SACe;CACf,MAAM,oBAAoB,SAAS,QAAQ;CAC3C,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;CACD,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,MAAM,mBAAmB,SAAS,QAAQ;;;;;;AAO5C,eAAe,wBACb,KACA,cACA,cACiB;CACjB,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,cACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,aACD;CACD,MAAM,UAAU,KAAK,YAAY,sBAAsB,EAAE,oBAAoB;CAC7E,MAAM,uCAAuC,cAAc,WAAW;CACtE,OAAO;;AAGT,eAAe,sBAAsB,KAAiC;CACpE,MAAM,KAAK,IAAI;CAEf,MAAM,iBAAiB,0BAA0B;CACjD,MAAM,mBAAmB,yBAAyB;CAClD,MAAM,UAAU,2BAA2B;CAG3C,MAAM,IAAI,QAAQ,0BAA0B,YAAY;EACtD,MAAM,eAAe,KAAK,gBAAgB,QAAQ;EAClD,MAAM,eAAe,KAAK,kBAAkB,QAAQ;EACpD,MAAM,eAAe,KAAK,SAAS,QAAQ;GAC3C;CAGF,MAAM,IAAI,QAAQ,yCAAyC,YAAY;EACrE,MAAM,aAAa,MAAM,wBAAwB,KAAK,gCAAgC,MAAM;IACzF,iBAAiB;IACjB,mBAAmB;GACrB,CAAC;EAGF,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;EAED,MAAM,0DAA0D;GAChE;CAGF,MAAM,IAAI,QAAQ,yCAAyC,YAAY;EACrE,MAAM,aAAa,MAAM,wBAAwB,KAAK,wBAAwB,MAAM,GACjF,UAAU,SACZ,CAAC;EAEF,IAAI,eAAe;EACnB,IAAI;GACF,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,2BACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;WACM,KAAK;GACZ,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;GAC/D,MAAM,8CAA8C,aAAa;;EAGnE,OAAO,GACL,cACA,mDAAmD,QAAQ,wCACnC,oBAAoB,yBAC7C;EAGD,OAAO,GACL,gDAAgD,KAAK,aAAa,EAClE,eAAe,QAAQ,oFACA,eACxB;GACD;;AAGJ,IAAa,4BAA4C;CACvD,MAAM;CACN,UAAU,CAAC,WAAW,UAAU;CAChC,WAAW;CACX,KAAK;CACN"}
|
package/build/esm/tests/audit.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import buildDebug from "debug";
|
|
2
|
-
import assert from "assert";
|
|
3
|
-
//#region src/tests/audit.ts
|
|
4
|
-
var debug = buildDebug("verdaccio:e2e-cli:test:audit");
|
|
5
|
-
async function testAudit(ctx) {
|
|
6
|
-
if (ctx.adapter.type !== "npm" && ctx.adapter.type !== "bun") {
|
|
7
|
-
debug("skipping audit test for %s (npm/bun only)", ctx.adapter.type);
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
const packages = [`verdaccio-audit-${ctx.runId}`, `@verdaccio/audit-${ctx.runId}`];
|
|
11
|
-
for (const pkgName of packages) {
|
|
12
|
-
const { tempFolder } = await ctx.adapter.prepareProject(pkgName, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, { jquery: "3.6.1" });
|
|
13
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "install", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
14
|
-
try {
|
|
15
|
-
if ((await fetch(`${ctx.registryUrl}/-/npm/v1/security/audits/quick`, {
|
|
16
|
-
method: "POST",
|
|
17
|
-
headers: { "Content-Type": "application/json" },
|
|
18
|
-
body: "{}"
|
|
19
|
-
})).status === 404) {
|
|
20
|
-
debug("audit endpoint not supported by this registry (404), skipping");
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
} catch {
|
|
24
|
-
debug("audit endpoint probe failed, skipping");
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
const resp = await ctx.adapter.exec({ cwd: tempFolder }, "audit", "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
28
|
-
if (ctx.adapter.type === "bun") assert.ok(resp.stdout.length > 0 || resp.stderr.length > 0, "Expected audit output");
|
|
29
|
-
else {
|
|
30
|
-
const parsedBody = JSON.parse(resp.stdout);
|
|
31
|
-
assert.ok(parsedBody.auditReportVersion !== void 0, "Expected \"auditReportVersion\" in audit response");
|
|
32
|
-
assert.ok(parsedBody.vulnerabilities !== void 0, "Expected \"vulnerabilities\" in audit response");
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
var auditTest = {
|
|
37
|
-
name: "audit",
|
|
38
|
-
requires: ["audit"],
|
|
39
|
-
run: testAudit
|
|
40
|
-
};
|
|
41
|
-
//#endregion
|
|
42
|
-
export { auditTest };
|
|
43
|
-
|
|
44
|
-
//# sourceMappingURL=audit.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","names":[],"sources":["../../../src/tests/audit.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\n\nimport { TestContext, TestDefinition } from '../types';\n\nconst debug = buildDebug('verdaccio:e2e-cli:test:audit');\n\nasync function testAudit(ctx: TestContext): Promise<void> {\n // Audit is only reliable with npm and bun — pnpm/yarn audit output varies too much\n if (ctx.adapter.type !== 'npm' && ctx.adapter.type !== 'bun') {\n debug('skipping audit test for %s (npm/bun only)', ctx.adapter.type);\n return;\n }\n\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 // npm audit exits with code 1 both when vulnerabilities are found AND when\n // the endpoint is unavailable. We need to distinguish between the two.\n // Probe the audit endpoint first to avoid false failures on registries\n // that don't support it (e.g. verdaccio next-7+).\n try {\n const probe = await fetch(`${ctx.registryUrl}/-/npm/v1/security/audits/quick`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: '{}',\n });\n if (probe.status === 404) {\n debug('audit endpoint not supported by this registry (404), skipping');\n return;\n }\n } catch {\n debug('audit endpoint probe failed, skipping');\n return;\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 if (ctx.adapter.type === 'bun') {\n // bun audit output may differ — exit code 0 is sufficient for basic validation\n assert.ok(resp.stdout.length > 0 || resp.stderr.length > 0, 'Expected audit output');\n } else {\n const parsedBody = JSON.parse(resp.stdout);\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 }\n }\n}\n\nexport const auditTest: TestDefinition = {\n name: 'audit',\n requires: ['audit'],\n run: testAudit,\n};\n"],"mappings":";;;AAKA,IAAM,QAAQ,WAAW,+BAA+B;AAExD,eAAe,UAAU,KAAiC;CAExD,IAAI,IAAI,QAAQ,SAAS,SAAS,IAAI,QAAQ,SAAS,OAAO;EAC5D,MAAM,6CAA6C,IAAI,QAAQ,KAAK;EACpE;;CAGF,MAAM,WAAW,CAAC,mBAAmB,IAAI,SAAS,oBAAoB,IAAI,QAAQ;CAElF,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,EAAE,QAAQ,SAAS,CACpB;EAGD,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;EAMD,IAAI;GAMF,KAAI,MALgB,MAAM,GAAG,IAAI,YAAY,kCAAkC;IAC7E,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAC/C,MAAM;IACP,CAAC,EACQ,WAAW,KAAK;IACxB,MAAM,gEAAgE;IACtE;;UAEI;GACN,MAAM,wCAAwC;GAC9C;;EAGF,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,SACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;EAED,IAAI,IAAI,QAAQ,SAAS,OAEvB,OAAO,GAAG,KAAK,OAAO,SAAS,KAAK,KAAK,OAAO,SAAS,GAAG,wBAAwB;OAC/E;GACL,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;GAC1C,OAAO,GACL,WAAW,uBAAuB,KAAA,GAClC,oDACD;GACD,OAAO,GACL,WAAW,oBAAoB,KAAA,GAC/B,iDACD;;;;AAKP,IAAa,YAA4B;CACvC,MAAM;CACN,UAAU,CAAC,QAAQ;CACnB,KAAK;CACN"}
|
package/build/esm/tests/ci.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import buildDebug from "debug";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { rm } from "fs/promises";
|
|
4
|
-
import assert from "assert";
|
|
5
|
-
//#region src/tests/ci.ts
|
|
6
|
-
var debug = buildDebug("verdaccio:e2e-cli:test:ci");
|
|
7
|
-
/**
|
|
8
|
-
* Test: ci
|
|
9
|
-
*
|
|
10
|
-
* Verifies that lockfile-based install works correctly.
|
|
11
|
-
* Unlike `install`, CI commands skip metadata fetches and resolve
|
|
12
|
-
* tarballs directly from the URLs stored in the lockfile.
|
|
13
|
-
*
|
|
14
|
-
* Flow:
|
|
15
|
-
* 1. Prepare a project with dependencies
|
|
16
|
-
* 2. Run `install` to generate the lockfile
|
|
17
|
-
* 3. Remove node_modules
|
|
18
|
-
* 4. Run the CI-equivalent command (npm ci / pnpm install --frozen-lockfile / yarn --frozen-lockfile / yarn --immutable)
|
|
19
|
-
* 5. Verify it completes successfully
|
|
20
|
-
*/
|
|
21
|
-
function getCiArgs(ctx) {
|
|
22
|
-
switch (ctx.adapter.type) {
|
|
23
|
-
case "npm": return ["ci", ...ctx.adapter.registryArg(ctx.registryUrl)];
|
|
24
|
-
case "pnpm": return [
|
|
25
|
-
"install",
|
|
26
|
-
"--frozen-lockfile",
|
|
27
|
-
...ctx.adapter.registryArg(ctx.registryUrl)
|
|
28
|
-
];
|
|
29
|
-
case "yarn-classic": return [
|
|
30
|
-
"install",
|
|
31
|
-
"--frozen-lockfile",
|
|
32
|
-
...ctx.adapter.registryArg(ctx.registryUrl)
|
|
33
|
-
];
|
|
34
|
-
case "yarn-modern": return ["install", "--immutable"];
|
|
35
|
-
case "bun": return [
|
|
36
|
-
"install",
|
|
37
|
-
"--frozen-lockfile",
|
|
38
|
-
...ctx.adapter.registryArg(ctx.registryUrl)
|
|
39
|
-
];
|
|
40
|
-
default: return ["ci", ...ctx.adapter.registryArg(ctx.registryUrl)];
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
async function testCi(ctx) {
|
|
44
|
-
if (ctx.adapter.type === "deno") {
|
|
45
|
-
debug("skipping ci test for deno (no ci command)");
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const { tempFolder } = await ctx.adapter.prepareProject(`ci-test-${ctx.runId}`, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, { "is-odd": "1.0.0" });
|
|
49
|
-
debug("running initial install to generate lockfile in %s", tempFolder);
|
|
50
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "install", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
51
|
-
debug("lockfile generated, removing node_modules");
|
|
52
|
-
await rm(join(tempFolder, "node_modules"), {
|
|
53
|
-
recursive: true,
|
|
54
|
-
force: true
|
|
55
|
-
});
|
|
56
|
-
await rm(join(tempFolder, ".pnpm-store"), {
|
|
57
|
-
recursive: true,
|
|
58
|
-
force: true
|
|
59
|
-
});
|
|
60
|
-
debug("node_modules removed, running ci command");
|
|
61
|
-
const ciArgs = getCiArgs(ctx);
|
|
62
|
-
debug("ci args: %o", ciArgs);
|
|
63
|
-
const resp = await ctx.adapter.exec({ cwd: tempFolder }, ...ciArgs);
|
|
64
|
-
if (ctx.adapter.type === "npm") {
|
|
65
|
-
debug("npm ci output: %s", resp.stdout + resp.stderr);
|
|
66
|
-
assert.ok(true, "npm ci completed successfully");
|
|
67
|
-
} else {
|
|
68
|
-
debug("ci completed successfully for %s", ctx.adapter.type);
|
|
69
|
-
assert.ok(true, `CI install completed successfully for ${ctx.adapter.type}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
var ciTest = {
|
|
73
|
-
name: "ci",
|
|
74
|
-
requires: ["install"],
|
|
75
|
-
run: testCi
|
|
76
|
-
};
|
|
77
|
-
//#endregion
|
|
78
|
-
export { ciTest };
|
|
79
|
-
|
|
80
|
-
//# sourceMappingURL=ci.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ci.js","names":[],"sources":["../../../src/tests/ci.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\nimport { rm } from 'fs/promises';\nimport { join } from 'path';\n\nimport { TestContext, TestDefinition } from '../types';\n\nconst debug = buildDebug('verdaccio:e2e-cli:test:ci');\n\n/**\n * Test: ci\n *\n * Verifies that lockfile-based install works correctly.\n * Unlike `install`, CI commands skip metadata fetches and resolve\n * tarballs directly from the URLs stored in the lockfile.\n *\n * Flow:\n * 1. Prepare a project with dependencies\n * 2. Run `install` to generate the lockfile\n * 3. Remove node_modules\n * 4. Run the CI-equivalent command (npm ci / pnpm install --frozen-lockfile / yarn --frozen-lockfile / yarn --immutable)\n * 5. Verify it completes successfully\n */\n\nfunction getCiArgs(ctx: TestContext): string[] {\n switch (ctx.adapter.type) {\n case 'npm':\n // `npm ci` — separate command, reads package-lock.json\n return ['ci', ...ctx.adapter.registryArg(ctx.registryUrl)];\n case 'pnpm':\n // `pnpm install --frozen-lockfile` — same command, strict mode\n return ['install', '--frozen-lockfile', ...ctx.adapter.registryArg(ctx.registryUrl)];\n case 'yarn-classic':\n // `yarn install --frozen-lockfile`\n return ['install', '--frozen-lockfile', ...ctx.adapter.registryArg(ctx.registryUrl)];\n case 'yarn-modern':\n // `yarn install --immutable`\n return ['install', '--immutable'];\n case 'bun':\n // `bun install --frozen-lockfile`\n return ['install', '--frozen-lockfile', ...ctx.adapter.registryArg(ctx.registryUrl)];\n default:\n return ['ci', ...ctx.adapter.registryArg(ctx.registryUrl)];\n }\n}\n\nasync function testCi(ctx: TestContext): Promise<void> {\n // deno doesn't have a CI/frozen-lockfile equivalent\n if (ctx.adapter.type === 'deno') {\n debug('skipping ci test for deno (no ci command)');\n return;\n }\n\n const { tempFolder } = await ctx.adapter.prepareProject(\n `ci-test-${ctx.runId}`,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n { 'is-odd': '1.0.0' }\n );\n\n debug('running initial install to generate lockfile in %s', tempFolder);\n\n // Step 1: Run install to generate the lockfile\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'install',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n debug('lockfile generated, removing node_modules');\n\n // Step 2: Remove node_modules to force a clean install from lockfile\n const nodeModulesPath = join(tempFolder, 'node_modules');\n await rm(nodeModulesPath, { recursive: true, force: true });\n\n // For pnpm, also clean the virtual store\n const pnpmStorePath = join(tempFolder, '.pnpm-store');\n await rm(pnpmStorePath, { recursive: true, force: true });\n\n debug('node_modules removed, running ci command');\n\n // Step 3: Run CI-equivalent command (tarball-only, no metadata fetches)\n const ciArgs = getCiArgs(ctx);\n debug('ci args: %o', ciArgs);\n const resp = await ctx.adapter.exec({ cwd: tempFolder }, ...ciArgs);\n\n // Step 4: Verify success\n if (ctx.adapter.type === 'npm') {\n // npm ci with --json is not reliable, just check exit code 0\n // and verify output mentions added packages\n const output = resp.stdout + resp.stderr;\n debug('npm ci output: %s', output);\n assert.ok(true, 'npm ci completed successfully');\n } else {\n debug('ci completed successfully for %s', ctx.adapter.type);\n assert.ok(true, `CI install completed successfully for ${ctx.adapter.type}`);\n }\n}\n\nexport const ciTest: TestDefinition = {\n name: 'ci',\n requires: ['install'],\n run: testCi,\n};\n"],"mappings":";;;;;AAOA,IAAM,QAAQ,WAAW,4BAA4B;;;;;;;;;;;;;;;AAiBrD,SAAS,UAAU,KAA4B;CAC7C,QAAQ,IAAI,QAAQ,MAApB;EACE,KAAK,OAEH,OAAO,CAAC,MAAM,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;EAC5D,KAAK,QAEH,OAAO;GAAC;GAAW;GAAqB,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;GAAC;EACtF,KAAK,gBAEH,OAAO;GAAC;GAAW;GAAqB,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;GAAC;EACtF,KAAK,eAEH,OAAO,CAAC,WAAW,cAAc;EACnC,KAAK,OAEH,OAAO;GAAC;GAAW;GAAqB,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;GAAC;EACtF,SACE,OAAO,CAAC,MAAM,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;;;AAIhE,eAAe,OAAO,KAAiC;CAErD,IAAI,IAAI,QAAQ,SAAS,QAAQ;EAC/B,MAAM,4CAA4C;EAClD;;CAGF,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,WAAW,IAAI,SACf,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,EAAE,UAAU,SAAS,CACtB;CAED,MAAM,sDAAsD,WAAW;CAGvE,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CAED,MAAM,4CAA4C;CAIlD,MAAM,GADkB,KAAK,YAAY,eAChC,EAAiB;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;CAI3D,MAAM,GADgB,KAAK,YAAY,cAC9B,EAAe;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;CAEzD,MAAM,2CAA2C;CAGjD,MAAM,SAAS,UAAU,IAAI;CAC7B,MAAM,eAAe,OAAO;CAC5B,MAAM,OAAO,MAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,YAAY,EAAE,GAAG,OAAO;CAGnE,IAAI,IAAI,QAAQ,SAAS,OAAO;EAI9B,MAAM,qBADS,KAAK,SAAS,KAAK,OACA;EAClC,OAAO,GAAG,MAAM,gCAAgC;QAC3C;EACL,MAAM,oCAAoC,IAAI,QAAQ,KAAK;EAC3D,OAAO,GAAG,MAAM,yCAAyC,IAAI,QAAQ,OAAO;;;AAIhF,IAAa,SAAyB;CACpC,MAAM;CACN,UAAU,CAAC,UAAU;CACrB,KAAK;CACN"}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { parseInfoJson } from "../utils/info.js";
|
|
2
|
-
import buildDebug from "debug";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import { readFile, writeFile } from "fs/promises";
|
|
5
|
-
import assert from "assert";
|
|
6
|
-
//#region src/tests/deprecate.ts
|
|
7
|
-
var debug = buildDebug("verdaccio:e2e-cli:test:deprecate");
|
|
8
|
-
async function publishPkg(ctx, tempFolder, pkgName) {
|
|
9
|
-
if (ctx.adapter.type === "yarn-modern") {
|
|
10
|
-
debug("running yarn install before publish for %s", pkgName);
|
|
11
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "install");
|
|
12
|
-
}
|
|
13
|
-
debug("publishing %s from %s", pkgName, tempFolder);
|
|
14
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
15
|
-
debug("published %s successfully", pkgName);
|
|
16
|
-
}
|
|
17
|
-
async function deprecate(ctx, tempFolder, packageVersion, message) {
|
|
18
|
-
debug("deprecating %s with message: %s", packageVersion, message || "(empty, un-deprecate)");
|
|
19
|
-
const jsonFlag = ctx.adapter.type === "yarn-modern" ? [] : ["--json"];
|
|
20
|
-
await ctx.adapter.exec({ cwd: tempFolder }, "deprecate", packageVersion, message, ...jsonFlag, ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
21
|
-
debug("deprecate command completed for %s", packageVersion);
|
|
22
|
-
}
|
|
23
|
-
async function getInfo(ctx, tempFolder, pkgName) {
|
|
24
|
-
debug("fetching info for %s", pkgName);
|
|
25
|
-
const parsed = parseInfoJson((await ctx.adapter.exec({ cwd: tempFolder }, "info", pkgName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl))).stdout);
|
|
26
|
-
debug("info for %s: deprecated=%s", pkgName, parsed.deprecated ?? "(not set)");
|
|
27
|
-
return parsed;
|
|
28
|
-
}
|
|
29
|
-
async function bumpVersion(ctx, tempFolder) {
|
|
30
|
-
debug("bumping version (minor) in %s", tempFolder);
|
|
31
|
-
if (ctx.adapter.type === "yarn-modern") {
|
|
32
|
-
const pkgPath = join(tempFolder, "package.json");
|
|
33
|
-
const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
|
|
34
|
-
const [major, minor, patch] = pkg.version.split(".").map(Number);
|
|
35
|
-
pkg.version = `${major}.${minor + 1}.${patch}`;
|
|
36
|
-
debug("bumped %s to %s", pkgPath, pkg.version);
|
|
37
|
-
await writeFile(pkgPath, JSON.stringify(pkg, null, 2));
|
|
38
|
-
} else await ctx.adapter.exec({ cwd: tempFolder }, "version", "minor", ...ctx.adapter.registryArg(ctx.registryUrl));
|
|
39
|
-
}
|
|
40
|
-
async function prepareDeprecateProject(ctx, pkgName, version) {
|
|
41
|
-
debug("preparing project for %s@%s", pkgName, version);
|
|
42
|
-
const { tempFolder } = await ctx.adapter.prepareProject(pkgName, version, ctx.registryUrl, ctx.port, ctx.token);
|
|
43
|
-
if (ctx.adapter.importPlugin) {
|
|
44
|
-
debug("importing npm-deprecate plugin into %s", tempFolder);
|
|
45
|
-
await ctx.adapter.importPlugin(tempFolder, "npm-deprecate");
|
|
46
|
-
}
|
|
47
|
-
return tempFolder;
|
|
48
|
-
}
|
|
49
|
-
async function testDeprecate(ctx) {
|
|
50
|
-
const id = ctx.runId;
|
|
51
|
-
const message = "some message";
|
|
52
|
-
await ctx.subTest("deprecate single version", async () => {
|
|
53
|
-
const pkgName = `@verdaccio/dep1-${id}`;
|
|
54
|
-
const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
|
|
55
|
-
await publishPkg(ctx, tf, pkgName);
|
|
56
|
-
await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);
|
|
57
|
-
const info = await getInfo(ctx, tf, pkgName);
|
|
58
|
-
assert.strictEqual(info.name, pkgName);
|
|
59
|
-
assert.strictEqual(info.deprecated, message, "Package should be deprecated");
|
|
60
|
-
});
|
|
61
|
-
await ctx.subTest("un-deprecate", async () => {
|
|
62
|
-
const pkgName = `@verdaccio/dep2-${id}`;
|
|
63
|
-
const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
|
|
64
|
-
await publishPkg(ctx, tf, pkgName);
|
|
65
|
-
await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);
|
|
66
|
-
const info1 = await getInfo(ctx, tf, pkgName);
|
|
67
|
-
assert.strictEqual(info1.deprecated, message);
|
|
68
|
-
await deprecate(ctx, tf, `${pkgName}@1.0.0`, "");
|
|
69
|
-
const info2 = await getInfo(ctx, tf, pkgName);
|
|
70
|
-
assert.strictEqual(info2.deprecated, void 0, "Package should be un-deprecated");
|
|
71
|
-
});
|
|
72
|
-
await ctx.subTest("deprecate multiple versions", async () => {
|
|
73
|
-
const pkgName = `@verdaccio/dep3-${id}`;
|
|
74
|
-
const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
|
|
75
|
-
await publishPkg(ctx, tf, pkgName);
|
|
76
|
-
for (let i = 0; i < 3; i++) {
|
|
77
|
-
await bumpVersion(ctx, tf);
|
|
78
|
-
await publishPkg(ctx, tf, pkgName);
|
|
79
|
-
}
|
|
80
|
-
await deprecate(ctx, tf, pkgName, message);
|
|
81
|
-
for (const v of [
|
|
82
|
-
"1.0.0",
|
|
83
|
-
"1.1.0",
|
|
84
|
-
"1.2.0",
|
|
85
|
-
"1.3.0"
|
|
86
|
-
]) {
|
|
87
|
-
const info = await getInfo(ctx, tf, `${pkgName}@${v}`);
|
|
88
|
-
assert.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);
|
|
89
|
-
}
|
|
90
|
-
await bumpVersion(ctx, tf);
|
|
91
|
-
await publishPkg(ctx, tf, pkgName);
|
|
92
|
-
const info = await getInfo(ctx, tf, `${pkgName}@1.4.0`);
|
|
93
|
-
assert.strictEqual(info.deprecated, void 0, "New version should not be deprecated");
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
var deprecateTest = {
|
|
97
|
-
name: "deprecate",
|
|
98
|
-
requires: ["deprecate"],
|
|
99
|
-
run: testDeprecate
|
|
100
|
-
};
|
|
101
|
-
//#endregion
|
|
102
|
-
export { deprecateTest };
|
|
103
|
-
|
|
104
|
-
//# sourceMappingURL=deprecate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deprecate.js","names":[],"sources":["../../../src/tests/deprecate.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\nimport { readFile, writeFile } from 'fs/promises';\nimport { join } from 'path';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { parseInfoJson } from '../utils/info';\n\nconst debug = buildDebug('verdaccio:e2e-cli:test:deprecate');\n\nasync function publishPkg(ctx: TestContext, tempFolder: string, pkgName: string) {\n if (ctx.adapter.type === 'yarn-modern') {\n debug('running yarn install before publish for %s', pkgName);\n await ctx.adapter.exec({ cwd: tempFolder }, 'install');\n }\n debug('publishing %s from %s', pkgName, tempFolder);\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n debug('published %s successfully', pkgName);\n}\n\nasync function deprecate(\n ctx: TestContext,\n tempFolder: string,\n packageVersion: string,\n message: string\n) {\n debug('deprecating %s with message: %s', packageVersion, message || '(empty, un-deprecate)');\n const jsonFlag = ctx.adapter.type === 'yarn-modern' ? [] : ['--json'];\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'deprecate',\n packageVersion,\n message,\n ...jsonFlag,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n debug('deprecate command completed for %s', packageVersion);\n}\n\nasync function getInfo(ctx: TestContext, tempFolder: string, pkgName: string) {\n debug('fetching info for %s', pkgName);\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'info',\n pkgName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const parsed = parseInfoJson(resp.stdout);\n debug('info for %s: deprecated=%s', pkgName, parsed.deprecated ?? '(not set)');\n return parsed;\n}\n\nasync function bumpVersion(ctx: TestContext, tempFolder: string) {\n debug('bumping version (minor) in %s', tempFolder);\n if (ctx.adapter.type === 'yarn-modern') {\n // Bump version by editing package.json directly to avoid\n // requiring the version plugin (not bundled in Yarn 3)\n const pkgPath = join(tempFolder, 'package.json');\n const pkg = JSON.parse(await readFile(pkgPath, 'utf8'));\n const [major, minor, patch] = pkg.version.split('.').map(Number);\n pkg.version = `${major}.${minor + 1}.${patch}`;\n debug('bumped %s to %s', pkgPath, pkg.version);\n await writeFile(pkgPath, JSON.stringify(pkg, null, 2));\n } else {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'version',\n 'minor',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n }\n}\n\nasync function prepareDeprecateProject(\n ctx: TestContext,\n pkgName: string,\n version: string\n): Promise<string> {\n debug('preparing project for %s@%s', pkgName, version);\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n version,\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n if (ctx.adapter.importPlugin) {\n debug('importing npm-deprecate plugin into %s', tempFolder);\n await ctx.adapter.importPlugin(tempFolder, 'npm-deprecate');\n }\n return tempFolder;\n}\n\nasync function testDeprecate(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n const message = 'some message';\n\n await ctx.subTest('deprecate single version', async () => {\n const pkgName = `@verdaccio/dep1-${id}`;\n const tf = await prepareDeprecateProject(ctx, pkgName, '1.0.0');\n await publishPkg(ctx, tf, pkgName);\n await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);\n const info = await getInfo(ctx, tf, pkgName);\n assert.strictEqual(info.name, pkgName);\n assert.strictEqual(info.deprecated, message, 'Package should be deprecated');\n });\n\n await ctx.subTest('un-deprecate', async () => {\n const pkgName = `@verdaccio/dep2-${id}`;\n const tf = await prepareDeprecateProject(ctx, pkgName, '1.0.0');\n await publishPkg(ctx, tf, pkgName);\n await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);\n const info1 = await getInfo(ctx, tf, pkgName);\n assert.strictEqual(info1.deprecated, message);\n await deprecate(ctx, tf, `${pkgName}@1.0.0`, '');\n const info2 = await getInfo(ctx, tf, pkgName);\n assert.strictEqual(info2.deprecated, undefined, 'Package should be un-deprecated');\n });\n\n await ctx.subTest('deprecate multiple versions', async () => {\n const pkgName = `@verdaccio/dep3-${id}`;\n const tf = await prepareDeprecateProject(ctx, pkgName, '1.0.0');\n await publishPkg(ctx, tf, pkgName);\n for (let i = 0; i < 3; i++) {\n await bumpVersion(ctx, tf);\n await publishPkg(ctx, tf, pkgName);\n }\n await deprecate(ctx, tf, pkgName, message);\n for (const v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) {\n const info = await getInfo(ctx, tf, `${pkgName}@${v}`);\n assert.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);\n }\n await bumpVersion(ctx, tf);\n await publishPkg(ctx, tf, pkgName);\n const info = await getInfo(ctx, tf, `${pkgName}@1.4.0`);\n assert.strictEqual(info.deprecated, undefined, 'New version should not be deprecated');\n });\n}\n\nexport const deprecateTest: TestDefinition = {\n name: 'deprecate',\n requires: ['deprecate'],\n run: testDeprecate,\n};\n"],"mappings":"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"}
|
|
@@ -1,41 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dist-tags.js","names":[],"sources":["../../../src/tests/dist-tags.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function publishPkg(ctx: TestContext, tempFolder: string, extraArgs: string[] = []) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...extraArgs,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\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 testDistTags(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Test 1: list dist-tags\n const pkgName1 = `@foo/dt1-${id}`;\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);\n await bumpVersion(ctx, tf1);\n await publishPkg(ctx, tf1, ['--tag', 'beta']);\n const resp1 = await ctx.adapter.exec(\n { cwd: tf1 },\n 'dist-tag',\n 'ls',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.strictEqual(resp1.stdout, 'beta: 1.1.0latest: 1.0.0');\n\n // Test 2: remove tag\n const pkgName2 = `@verdaccio/dt2-${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);\n await bumpVersion(ctx, tf2);\n await publishPkg(ctx, tf2, ['--tag', 'beta']);\n const resp2 = await ctx.adapter.exec(\n { cwd: tf2 },\n 'dist-tag',\n 'rm',\n `${pkgName2}@1.1.0`,\n 'beta',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.strictEqual(resp2.stdout, `-beta: ${pkgName2}@1.1.0`);\n\n // Test 3: add tag\n const pkgName3 = `@verdaccio/dt3-${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);\n await bumpVersion(ctx, tf3);\n await publishPkg(ctx, tf3);\n const resp3 = await ctx.adapter.exec(\n { cwd: tf3 },\n 'dist-tag',\n 'add',\n `${pkgName3}@1.1.0`,\n 'alfa',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.strictEqual(resp3.stdout, `+alfa: ${pkgName3}@1.1.0`);\n}\n\nexport const distTagsTest: TestDefinition = {\n name: 'dist-tags',\n requires: ['dist-tag'],\n run: testDistTags,\n};\n"],"mappings":";;AAIA,eAAe,WAAW,KAAkB,YAAoB,YAAsB,EAAE,EAAE;CACxF,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,WACH,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,YAAY,KAAkB,YAAoB;CAC/D,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,SACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,aAAa,KAAiC;CAC3D,MAAM,KAAK,IAAI;CAGf,MAAM,WAAW,YAAY;CAC7B,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;CACD,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,WAAW,KAAK,KAAK,CAAC,SAAS,OAAO,CAAC;CAC7C,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,YACA,MACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,OAAO,YAAY,MAAM,QAAQ,2BAA2B;CAG5D,MAAM,WAAW,kBAAkB;CACnC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;CACD,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,WAAW,KAAK,KAAK,CAAC,SAAS,OAAO,CAAC;CAC7C,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,YACA,MACA,GAAG,SAAS,SACZ,QACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,OAAO,YAAY,MAAM,QAAQ,UAAU,SAAS,QAAQ;CAG5D,MAAM,WAAW,kBAAkB;CACnC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;CACD,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,YACA,OACA,GAAG,SAAS,SACZ,QACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,OAAO,YAAY,MAAM,QAAQ,UAAU,SAAS,QAAQ;;AAG9D,IAAa,eAA+B;CAC1C,MAAM;CACN,UAAU,CAAC,WAAW;CACtB,KAAK;CACN"}
|
package/build/esm/tests/index.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import "../scenarios/install-multiple-deps.js";
|
|
2
|
-
import "../scenarios/minimum-release-age.js";
|
|
3
|
-
import { allScenarios } from "../scenarios/index.js";
|
|
4
|
-
import { auditTest } from "./audit.js";
|
|
5
|
-
import { ciTest } from "./ci.js";
|
|
6
|
-
import { deprecateTest } from "./deprecate.js";
|
|
7
|
-
import { distTagsTest } from "./dist-tags.js";
|
|
8
|
-
import { infoTest } from "./info.js";
|
|
9
|
-
import { installTest } from "./install.js";
|
|
10
|
-
import { loginTest } from "./login.js";
|
|
11
|
-
import { pingTest } from "./ping.js";
|
|
12
|
-
import { publishTest } from "./publish.js";
|
|
13
|
-
import { searchTest } from "./search.js";
|
|
14
|
-
import { unpublishTest } from "./unpublish.js";
|
|
15
|
-
//#region src/tests/index.ts
|
|
16
|
-
var allTests = [
|
|
17
|
-
publishTest,
|
|
18
|
-
installTest,
|
|
19
|
-
ciTest,
|
|
20
|
-
auditTest,
|
|
21
|
-
infoTest,
|
|
22
|
-
deprecateTest,
|
|
23
|
-
distTagsTest,
|
|
24
|
-
loginTest,
|
|
25
|
-
pingTest,
|
|
26
|
-
searchTest,
|
|
27
|
-
unpublishTest,
|
|
28
|
-
...allScenarios
|
|
29
|
-
];
|
|
30
|
-
//#endregion
|
|
31
|
-
export { allTests };
|
|
32
|
-
|
|
33
|
-
//# sourceMappingURL=index.js.map
|