@verdaccio/e2e-cli 2.9.0 → 2.10.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.
Files changed (93) hide show
  1. package/build/cjs/adapters/bun.cjs +1 -1
  2. package/build/cjs/adapters/bun.cjs.map +1 -1
  3. package/build/cjs/adapters/deno.cjs +1 -1
  4. package/build/cjs/adapters/deno.cjs.map +1 -1
  5. package/build/cjs/adapters/npm.cjs +1 -1
  6. package/build/cjs/adapters/npm.cjs.map +1 -1
  7. package/build/cjs/adapters/pnpm.cjs +1 -1
  8. package/build/cjs/adapters/pnpm.cjs.map +1 -1
  9. package/build/cjs/adapters/yarn-classic.cjs +1 -1
  10. package/build/cjs/adapters/yarn-classic.cjs.map +1 -1
  11. package/build/cjs/adapters/yarn-modern.cjs +2 -2
  12. package/build/cjs/adapters/yarn-modern.cjs.map +1 -1
  13. package/build/cjs/index.cjs +3 -2
  14. package/build/cjs/index.cjs.map +1 -1
  15. package/build/cjs/reporter.cjs.map +1 -1
  16. package/build/cjs/runner.cjs +6 -1
  17. package/build/cjs/runner.cjs.map +1 -1
  18. package/build/cjs/scenarios/index.cjs +3 -1
  19. package/build/cjs/scenarios/index.cjs.map +1 -1
  20. package/build/cjs/scenarios/install-multiple-deps.cjs +2 -2
  21. package/build/cjs/scenarios/install-multiple-deps.cjs.map +1 -1
  22. package/build/cjs/scenarios/minimum-release-age.cjs +112 -0
  23. package/build/cjs/scenarios/minimum-release-age.cjs.map +1 -0
  24. package/build/cjs/tests/audit.cjs +2 -2
  25. package/build/cjs/tests/audit.cjs.map +1 -1
  26. package/build/cjs/tests/ci.cjs +2 -2
  27. package/build/cjs/tests/ci.cjs.map +1 -1
  28. package/build/cjs/tests/deprecate.cjs +2 -2
  29. package/build/cjs/tests/deprecate.cjs.map +1 -1
  30. package/build/cjs/tests/dist-tags.cjs +1 -1
  31. package/build/cjs/tests/dist-tags.cjs.map +1 -1
  32. package/build/cjs/tests/index.cjs +1 -0
  33. package/build/cjs/tests/index.cjs.map +1 -1
  34. package/build/cjs/tests/info.cjs +1 -1
  35. package/build/cjs/tests/info.cjs.map +1 -1
  36. package/build/cjs/tests/install.cjs +1 -1
  37. package/build/cjs/tests/install.cjs.map +1 -1
  38. package/build/cjs/tests/login.cjs +3 -3
  39. package/build/cjs/tests/login.cjs.map +1 -1
  40. package/build/cjs/tests/ping.cjs +1 -1
  41. package/build/cjs/tests/ping.cjs.map +1 -1
  42. package/build/cjs/tests/publish.cjs +1 -1
  43. package/build/cjs/tests/publish.cjs.map +1 -1
  44. package/build/cjs/tests/search.cjs +1 -1
  45. package/build/cjs/tests/search.cjs.map +1 -1
  46. package/build/cjs/tests/star.cjs +1 -1
  47. package/build/cjs/tests/star.cjs.map +1 -1
  48. package/build/cjs/tests/unpublish.cjs +1 -1
  49. package/build/cjs/tests/unpublish.cjs.map +1 -1
  50. package/build/cjs/utils/process.cjs +1 -1
  51. package/build/cjs/utils/process.cjs.map +1 -1
  52. package/build/cjs/utils/project.cjs +1 -1
  53. package/build/cjs/utils/project.cjs.map +1 -1
  54. package/build/cjs/utils/registry-client.cjs +1 -1
  55. package/build/cjs/utils/registry-client.cjs.map +1 -1
  56. package/build/esm/adapters/bun.js.map +1 -1
  57. package/build/esm/adapters/deno.js.map +1 -1
  58. package/build/esm/adapters/npm.js.map +1 -1
  59. package/build/esm/adapters/pnpm.js.map +1 -1
  60. package/build/esm/adapters/yarn-classic.js.map +1 -1
  61. package/build/esm/adapters/yarn-modern.js.map +1 -1
  62. package/build/esm/index.js +2 -1
  63. package/build/esm/index.js.map +1 -1
  64. package/build/esm/reporter.js.map +1 -1
  65. package/build/esm/runner.js +5 -0
  66. package/build/esm/runner.js.map +1 -1
  67. package/build/esm/scenarios/index.js +2 -1
  68. package/build/esm/scenarios/index.js.map +1 -1
  69. package/build/esm/scenarios/install-multiple-deps.js.map +1 -1
  70. package/build/esm/scenarios/minimum-release-age.js +109 -0
  71. package/build/esm/scenarios/minimum-release-age.js.map +1 -0
  72. package/build/esm/tests/audit.js.map +1 -1
  73. package/build/esm/tests/ci.js.map +1 -1
  74. package/build/esm/tests/deprecate.js.map +1 -1
  75. package/build/esm/tests/dist-tags.js.map +1 -1
  76. package/build/esm/tests/index.js +1 -0
  77. package/build/esm/tests/index.js.map +1 -1
  78. package/build/esm/tests/info.js.map +1 -1
  79. package/build/esm/tests/install.js.map +1 -1
  80. package/build/esm/tests/login.js.map +1 -1
  81. package/build/esm/tests/ping.js.map +1 -1
  82. package/build/esm/tests/publish.js.map +1 -1
  83. package/build/esm/tests/search.js.map +1 -1
  84. package/build/esm/tests/star.js.map +1 -1
  85. package/build/esm/tests/unpublish.js.map +1 -1
  86. package/build/esm/utils/process.js.map +1 -1
  87. package/build/esm/utils/project.js.map +1 -1
  88. package/build/esm/utils/registry-client.js.map +1 -1
  89. package/build/scenarios/index.d.ts +2 -1
  90. package/build/scenarios/minimum-release-age.d.ts +11 -0
  91. package/build/tests/index.d.ts +2 -2
  92. package/build/types.d.ts +6 -0
  93. package/package.json +3 -3
@@ -0,0 +1,109 @@
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
@@ -0,0 +1 @@
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"}
@@ -1 +1 @@
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;AAExD,KAAI,IAAI,QAAQ,SAAS,SAAS,IAAI,QAAQ,SAAS,OAAO;AAC5D,QAAM,6CAA6C,IAAI,QAAQ,KAAK;AACpE;;CAGF,MAAM,WAAW,CAAC,mBAAmB,IAAI,SAAS,oBAAoB,IAAI,QAAQ;AAElF,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,EAAE,QAAQ,SAAS,CACpB;AAGD,QAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AAMD,MAAI;AAMF,QALc,MAAM,MAAM,GAAG,IAAI,YAAY,kCAAkC;IAC7E,QAAQ;IACR,SAAS,EAAE,gBAAgB,oBAAoB;IAC/C,MAAM;IACP,CAAC,EACQ,WAAW,KAAK;AACxB,UAAM,gEAAgE;AACtE;;UAEI;AACN,SAAM,wCAAwC;AAC9C;;EAGF,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,SACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AAED,MAAI,IAAI,QAAQ,SAAS,MAEvB,QAAO,GAAG,KAAK,OAAO,SAAS,KAAK,KAAK,OAAO,SAAS,GAAG,wBAAwB;OAC/E;GACL,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;AAC1C,UAAO,GACL,WAAW,uBAAuB,KAAA,GAClC,oDACD;AACD,UAAO,GACL,WAAW,oBAAoB,KAAA,GAC/B,iDACD;;;;AAKP,IAAa,YAA4B;CACvC,MAAM;CACN,UAAU,CAAC,QAAQ;CACnB,KAAK;CACN"}
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"}
@@ -1 +1 @@
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;AAC7C,SAAQ,IAAI,QAAQ,MAApB;EACE,KAAK,MAEH,QAAO,CAAC,MAAM,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;EAC5D,KAAK,OAEH,QAAO;GAAC;GAAW;GAAqB,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;GAAC;EACtF,KAAK,eAEH,QAAO;GAAC;GAAW;GAAqB,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;GAAC;EACtF,KAAK,cAEH,QAAO,CAAC,WAAW,cAAc;EACnC,KAAK,MAEH,QAAO;GAAC;GAAW;GAAqB,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;GAAC;EACtF,QACE,QAAO,CAAC,MAAM,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;;;AAIhE,eAAe,OAAO,KAAiC;AAErD,KAAI,IAAI,QAAQ,SAAS,QAAQ;AAC/B,QAAM,4CAA4C;AAClD;;CAGF,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,WAAW,IAAI,SACf,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,EAAE,UAAU,SAAS,CACtB;AAED,OAAM,sDAAsD,WAAW;AAGvE,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AAED,OAAM,4CAA4C;AAIlD,OAAM,GADkB,KAAK,YAAY,eAAe,EAC9B;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAI3D,OAAM,GADgB,KAAK,YAAY,cAAc,EAC7B;EAAE,WAAW;EAAM,OAAO;EAAM,CAAC;AAEzD,OAAM,2CAA2C;CAGjD,MAAM,SAAS,UAAU,IAAI;AAC7B,OAAM,eAAe,OAAO;CAC5B,MAAM,OAAO,MAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,YAAY,EAAE,GAAG,OAAO;AAGnE,KAAI,IAAI,QAAQ,SAAS,OAAO;AAI9B,QAAM,qBADS,KAAK,SAAS,KAAK,OACA;AAClC,SAAO,GAAG,MAAM,gCAAgC;QAC3C;AACL,QAAM,oCAAoC,IAAI,QAAQ,KAAK;AAC3D,SAAO,GAAG,MAAM,yCAAyC,IAAI,QAAQ,OAAO;;;AAIhF,IAAa,SAAyB;CACpC,MAAM;CACN,UAAU,CAAC,UAAU;CACrB,KAAK;CACN"}
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 +1 @@
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';\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 = JSON.parse(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
+ {"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';\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 = JSON.parse(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 +1 @@
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;AACxF,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,WACH,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,YAAY,KAAkB,YAAoB;AAC/D,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,SACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,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;AACD,OAAM,WAAW,KAAK,IAAI;AAC1B,OAAM,YAAY,KAAK,IAAI;AAC3B,OAAM,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;AACD,QAAO,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;AACD,OAAM,WAAW,KAAK,IAAI;AAC1B,OAAM,YAAY,KAAK,IAAI;AAC3B,OAAM,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;AACD,QAAO,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;AACD,OAAM,WAAW,KAAK,IAAI;AAC1B,OAAM,YAAY,KAAK,IAAI;AAC3B,OAAM,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;AACD,QAAO,YAAY,MAAM,QAAQ,UAAU,SAAS,QAAQ;;AAG9D,IAAa,eAA+B;CAC1C,MAAM;CACN,UAAU,CAAC,WAAW;CACtB,KAAK;CACN"}
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"}
@@ -1,4 +1,5 @@
1
1
  import "../scenarios/install-multiple-deps.js";
2
+ import "../scenarios/minimum-release-age.js";
2
3
  import { allScenarios } from "../scenarios/index.js";
3
4
  import { auditTest } from "./audit.js";
4
5
  import { ciTest } from "./ci.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/tests/index.ts"],"sourcesContent":["import { allScenarios, installMultipleDepsScenario } from '../scenarios';\nimport { TestDefinition } from '../types';\nimport { auditTest } from './audit';\nimport { ciTest } from './ci';\nimport { deprecateTest } from './deprecate';\nimport { distTagsTest } from './dist-tags';\nimport { infoTest } from './info';\nimport { installTest } from './install';\nimport { loginTest } from './login';\nimport { pingTest } from './ping';\nimport { publishTest } from './publish';\nimport { searchTest } from './search';\nimport { starTest } from './star';\nimport { unpublishTest } from './unpublish';\n\nexport const allTests: TestDefinition[] = [\n publishTest,\n installTest,\n ciTest,\n auditTest,\n infoTest,\n deprecateTest,\n distTagsTest,\n loginTest,\n pingTest,\n searchTest,\n starTest,\n unpublishTest,\n // Scenarios (complex, multi-step tests)\n ...allScenarios,\n];\n\nexport {\n publishTest,\n installTest,\n ciTest,\n auditTest,\n infoTest,\n deprecateTest,\n distTagsTest,\n loginTest,\n pingTest,\n searchTest,\n starTest,\n unpublishTest,\n // Scenarios\n installMultipleDepsScenario,\n allScenarios,\n};\n"],"mappings":";;;;;;;;;;;;;;;AAeA,IAAa,WAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,GAAG;CACJ"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/tests/index.ts"],"sourcesContent":["import { allScenarios, installMultipleDepsScenario, minimumReleaseAgeScenario } from '../scenarios';\nimport { TestDefinition } from '../types';\nimport { auditTest } from './audit';\nimport { ciTest } from './ci';\nimport { deprecateTest } from './deprecate';\nimport { distTagsTest } from './dist-tags';\nimport { infoTest } from './info';\nimport { installTest } from './install';\nimport { loginTest } from './login';\nimport { pingTest } from './ping';\nimport { publishTest } from './publish';\nimport { searchTest } from './search';\nimport { starTest } from './star';\nimport { unpublishTest } from './unpublish';\n\nexport const allTests: TestDefinition[] = [\n publishTest,\n installTest,\n ciTest,\n auditTest,\n infoTest,\n deprecateTest,\n distTagsTest,\n loginTest,\n pingTest,\n searchTest,\n starTest,\n unpublishTest,\n // Scenarios (complex, multi-step tests)\n ...allScenarios,\n];\n\nexport {\n publishTest,\n installTest,\n ciTest,\n auditTest,\n infoTest,\n deprecateTest,\n distTagsTest,\n loginTest,\n pingTest,\n searchTest,\n starTest,\n unpublishTest,\n // Scenarios\n installMultipleDepsScenario,\n minimumReleaseAgeScenario,\n allScenarios,\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,IAAa,WAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,GAAG;CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"info.js","names":[],"sources":["../../../src/tests/info.ts"],"sourcesContent":["import assert from 'assert';\nimport { writeFile } from 'fs/promises';\nimport { join } from 'path';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { createTempFolder } from '../utils/project';\n\nasync function testInfo(ctx: TestContext): Promise<void> {\n // Create a minimal temp project so yarn modern has a project context\n // and yarn classic doesn't pick up the repo's packageManager field\n const tempFolder = await createTempFolder('info-test');\n await writeFile(\n join(tempFolder, 'package.json'),\n JSON.stringify({ name: 'info-test', version: '1.0.0' })\n );\n\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'info',\n 'verdaccio',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n if (ctx.adapter.type === 'yarn-classic') {\n const lines = resp.stdout.split('\\n').filter(Boolean);\n const dataLine = lines.find((l) => {\n try {\n const obj = JSON.parse(l);\n return obj.type === 'inspect';\n } catch {\n return false;\n }\n });\n assert.ok(dataLine, 'Expected yarn info NDJSON to contain an \"inspect\" entry');\n } else if (ctx.adapter.type === 'deno') {\n // deno info npm:<pkg> outputs a text dependency tree\n const output = resp.stdout + resp.stderr;\n assert.ok(output.includes('verdaccio'), 'Expected deno info output to reference verdaccio');\n } else {\n const parsedBody = JSON.parse(resp.stdout);\n assert.strictEqual(parsedBody.name, 'verdaccio', 'Expected package name \"verdaccio\"');\n assert.ok(parsedBody.dependencies !== undefined, 'Expected \"dependencies\" to be defined');\n }\n}\n\nexport const infoTest: TestDefinition = {\n name: 'info',\n requires: ['info'],\n run: testInfo,\n};\n"],"mappings":";;;;;AAOA,eAAe,SAAS,KAAiC;CAGvD,MAAM,aAAa,MAAM,iBAAiB,YAAY;AACtD,OAAM,UACJ,KAAK,YAAY,eAAe,EAChC,KAAK,UAAU;EAAE,MAAM;EAAa,SAAS;EAAS,CAAC,CACxD;CAED,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,QACA,aACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AAED,KAAI,IAAI,QAAQ,SAAS,gBAAgB;EAEvC,MAAM,WADQ,KAAK,OAAO,MAAM,KAAK,CAAC,OAAO,QAAQ,CAC9B,MAAM,MAAM;AACjC,OAAI;AAEF,WADY,KAAK,MAAM,EAAE,CACd,SAAS;WACd;AACN,WAAO;;IAET;AACF,SAAO,GAAG,UAAU,4DAA0D;YACrE,IAAI,QAAQ,SAAS,QAAQ;EAEtC,MAAM,SAAS,KAAK,SAAS,KAAK;AAClC,SAAO,GAAG,OAAO,SAAS,YAAY,EAAE,mDAAmD;QACtF;EACL,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;AAC1C,SAAO,YAAY,WAAW,MAAM,aAAa,sCAAoC;AACrF,SAAO,GAAG,WAAW,iBAAiB,KAAA,GAAW,0CAAwC;;;AAI7F,IAAa,WAA2B;CACtC,MAAM;CACN,UAAU,CAAC,OAAO;CAClB,KAAK;CACN"}
1
+ {"version":3,"file":"info.js","names":[],"sources":["../../../src/tests/info.ts"],"sourcesContent":["import assert from 'assert';\nimport { writeFile } from 'fs/promises';\nimport { join } from 'path';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { createTempFolder } from '../utils/project';\n\nasync function testInfo(ctx: TestContext): Promise<void> {\n // Create a minimal temp project so yarn modern has a project context\n // and yarn classic doesn't pick up the repo's packageManager field\n const tempFolder = await createTempFolder('info-test');\n await writeFile(\n join(tempFolder, 'package.json'),\n JSON.stringify({ name: 'info-test', version: '1.0.0' })\n );\n\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'info',\n 'verdaccio',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n if (ctx.adapter.type === 'yarn-classic') {\n const lines = resp.stdout.split('\\n').filter(Boolean);\n const dataLine = lines.find((l) => {\n try {\n const obj = JSON.parse(l);\n return obj.type === 'inspect';\n } catch {\n return false;\n }\n });\n assert.ok(dataLine, 'Expected yarn info NDJSON to contain an \"inspect\" entry');\n } else if (ctx.adapter.type === 'deno') {\n // deno info npm:<pkg> outputs a text dependency tree\n const output = resp.stdout + resp.stderr;\n assert.ok(output.includes('verdaccio'), 'Expected deno info output to reference verdaccio');\n } else {\n const parsedBody = JSON.parse(resp.stdout);\n assert.strictEqual(parsedBody.name, 'verdaccio', 'Expected package name \"verdaccio\"');\n assert.ok(parsedBody.dependencies !== undefined, 'Expected \"dependencies\" to be defined');\n }\n}\n\nexport const infoTest: TestDefinition = {\n name: 'info',\n requires: ['info'],\n run: testInfo,\n};\n"],"mappings":";;;;;AAOA,eAAe,SAAS,KAAiC;CAGvD,MAAM,aAAa,MAAM,iBAAiB,YAAY;CACtD,MAAM,UACJ,KAAK,YAAY,eAAe,EAChC,KAAK,UAAU;EAAE,MAAM;EAAa,SAAS;EAAS,CAAC,CACxD;CAED,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,QACA,aACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CAED,IAAI,IAAI,QAAQ,SAAS,gBAAgB;EAEvC,MAAM,WADQ,KAAK,OAAO,MAAM,KAAK,CAAC,OAAO,QAC5B,CAAM,MAAM,MAAM;GACjC,IAAI;IAEF,OADY,KAAK,MAAM,EAChB,CAAI,SAAS;WACd;IACN,OAAO;;IAET;EACF,OAAO,GAAG,UAAU,4DAA0D;QACzE,IAAI,IAAI,QAAQ,SAAS,QAAQ;EAEtC,MAAM,SAAS,KAAK,SAAS,KAAK;EAClC,OAAO,GAAG,OAAO,SAAS,YAAY,EAAE,mDAAmD;QACtF;EACL,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;EAC1C,OAAO,YAAY,WAAW,MAAM,aAAa,sCAAoC;EACrF,OAAO,GAAG,WAAW,iBAAiB,KAAA,GAAW,0CAAwC;;;AAI7F,IAAa,WAA2B;CACtC,MAAM;CACN,UAAU,CAAC,OAAO;CAClB,KAAK;CACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","names":[],"sources":["../../../src/tests/install.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testInstall(ctx: TestContext): Promise<void> {\n const { tempFolder } = await ctx.adapter.prepareProject(\n `install-test-${ctx.runId}`,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n { react: '18.2.0' }\n );\n\n const isNpm = ctx.adapter.type === 'npm';\n\n // pnpm doesn't support --json on install\n const args = isNpm\n ? ['install', '--json', ...ctx.adapter.registryArg(ctx.registryUrl)]\n : ['install', ...ctx.adapter.registryArg(ctx.registryUrl)];\n\n const resp = await ctx.adapter.exec({ cwd: tempFolder }, ...args);\n\n if (isNpm) {\n const parsedBody = JSON.parse(resp.stdout);\n assert.ok(parsedBody.added !== undefined, 'Expected \"added\" field in install response');\n } else {\n // for pnpm/yarn just verify it completed without error (exit code 0)\n assert.ok(true, 'Install completed successfully');\n }\n}\n\nexport const installTest: TestDefinition = {\n name: 'install',\n requires: ['install'],\n run: testInstall,\n};\n"],"mappings":";;AAIA,eAAe,YAAY,KAAiC;CAC1D,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,gBAAgB,IAAI,SACpB,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,EAAE,OAAO,UAAU,CACpB;CAED,MAAM,QAAQ,IAAI,QAAQ,SAAS;CAGnC,MAAM,OAAO,QACT;EAAC;EAAW;EAAU,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;EAAC,GAClE,CAAC,WAAW,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;CAE5D,MAAM,OAAO,MAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,YAAY,EAAE,GAAG,KAAK;AAEjE,KAAI,OAAO;EACT,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;AAC1C,SAAO,GAAG,WAAW,UAAU,KAAA,GAAW,+CAA6C;OAGvF,QAAO,GAAG,MAAM,iCAAiC;;AAIrD,IAAa,cAA8B;CACzC,MAAM;CACN,UAAU,CAAC,UAAU;CACrB,KAAK;CACN"}
1
+ {"version":3,"file":"install.js","names":[],"sources":["../../../src/tests/install.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testInstall(ctx: TestContext): Promise<void> {\n const { tempFolder } = await ctx.adapter.prepareProject(\n `install-test-${ctx.runId}`,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token,\n { react: '18.2.0' }\n );\n\n const isNpm = ctx.adapter.type === 'npm';\n\n // pnpm doesn't support --json on install\n const args = isNpm\n ? ['install', '--json', ...ctx.adapter.registryArg(ctx.registryUrl)]\n : ['install', ...ctx.adapter.registryArg(ctx.registryUrl)];\n\n const resp = await ctx.adapter.exec({ cwd: tempFolder }, ...args);\n\n if (isNpm) {\n const parsedBody = JSON.parse(resp.stdout);\n assert.ok(parsedBody.added !== undefined, 'Expected \"added\" field in install response');\n } else {\n // for pnpm/yarn just verify it completed without error (exit code 0)\n assert.ok(true, 'Install completed successfully');\n }\n}\n\nexport const installTest: TestDefinition = {\n name: 'install',\n requires: ['install'],\n run: testInstall,\n};\n"],"mappings":";;AAIA,eAAe,YAAY,KAAiC;CAC1D,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,gBAAgB,IAAI,SACpB,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,OACJ,EAAE,OAAO,UAAU,CACpB;CAED,MAAM,QAAQ,IAAI,QAAQ,SAAS;CAGnC,MAAM,OAAO,QACT;EAAC;EAAW;EAAU,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY;EAAC,GAClE,CAAC,WAAW,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;CAE5D,MAAM,OAAO,MAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,YAAY,EAAE,GAAG,KAAK;CAEjE,IAAI,OAAO;EACT,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;EAC1C,OAAO,GAAG,WAAW,UAAU,KAAA,GAAW,+CAA6C;QAGvF,OAAO,GAAG,MAAM,iCAAiC;;AAIrD,IAAa,cAA8B;CACzC,MAAM;CACN,UAAU,CAAC,UAAU;CACrB,KAAK;CACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","names":[],"sources":["../../../src/tests/login.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\nimport { writeFile } from 'fs/promises';\nimport YAML from 'js-yaml';\nimport { join } from 'path';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { createTempFolder, getPackageJSON, getREADME } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:test:login');\n\n/**\n * Creates a project with registry config but WITHOUT auth token,\n * so whoami will use the token saved by login to ~/.yarnrc.yml.\n */\nasync function prepareLoginProject(ctx: TestContext, name: string): Promise<string> {\n debug('preparing project for %s (no auth token)', name);\n const tempFolder = await createTempFolder(name);\n const yamlContent = YAML.dump({\n npmRegistryServer: ctx.registryUrl,\n enableImmutableInstalls: false,\n unsafeHttpWhitelist: ['localhost'],\n });\n await writeFile(join(tempFolder, '.yarnrc.yml'), yamlContent);\n await writeFile(join(tempFolder, 'package.json'), JSON.stringify({ name, version: '1.0.0' }));\n if (ctx.adapter.importPlugin) {\n debug('importing npm-login plugin into %s', tempFolder);\n await ctx.adapter.importPlugin(tempFolder, 'npm-login');\n }\n return tempFolder;\n}\n\nasync function yarnLogin(\n ctx: TestContext,\n cwd: string,\n user: string,\n password: string,\n email: string\n) {\n debug('yarn npm login as %s', user);\n return ctx.adapter.exec(\n { cwd },\n 'login',\n '--auth-type=legacy',\n `--user=${user}`,\n `--password=${password}`,\n `--email=${email}`\n );\n}\n\nasync function yarnWhoami(ctx: TestContext, cwd: string): Promise<string> {\n const resp = await ctx.adapter.exec({ cwd }, 'whoami');\n debug('yarn npm whoami: %s', resp.stdout);\n return resp.stdout;\n}\n\nasync function testLogin(ctx: TestContext): Promise<void> {\n const type = ctx.adapter.type;\n const id = ctx.runId;\n\n if (type !== 'yarn-modern') {\n debug('login test only supported for yarn-modern, skipping %s', type);\n return;\n }\n\n const user1 = `login-a-${id}`;\n const password1 = 'test-password-123';\n const email1 = `${user1}@test.example.com`;\n\n await ctx.subTest('create new user + whoami', async () => {\n const tf = await prepareLoginProject(ctx, `verdaccio-login1-${id}`);\n const loginResp = await yarnLogin(ctx, tf, user1, password1, email1);\n assert.ok(\n loginResp.stdout.includes('Logged in') || loginResp.stdout.includes('token saved'),\n `Expected login success message but got \"${loginResp.stdout}\"`\n );\n const who = await yarnWhoami(ctx, tf);\n assert.ok(who.includes(user1), `Expected whoami \"${user1}\" but got \"${who}\"`);\n });\n\n await ctx.subTest('login existing user', async () => {\n const tf = await prepareLoginProject(ctx, `verdaccio-login2-${id}`);\n const loginResp = await yarnLogin(ctx, tf, user1, password1, email1);\n assert.ok(\n loginResp.stdout.includes('Logged in') || loginResp.stdout.includes('token saved'),\n `Expected login success for existing user but got \"${loginResp.stdout}\"`\n );\n const who = await yarnWhoami(ctx, tf);\n assert.ok(who.includes(user1), `Expected \"${user1}\" but got \"${who}\"`);\n });\n\n await ctx.subTest('wrong password fails', async () => {\n const tf = await prepareLoginProject(ctx, `verdaccio-login3-${id}`);\n let loginFailed = false;\n try {\n await yarnLogin(ctx, tf, user1, 'wrong-password', email1);\n } catch {\n loginFailed = true;\n }\n assert.ok(loginFailed, 'Login with wrong password should have failed');\n });\n\n await ctx.subTest('login then publish', async () => {\n const pkgName = `@verdaccio/login-pub-${id}`;\n const tf = await createTempFolder(`login-pub-${id}`);\n const yamlContent = YAML.dump({\n npmRegistryServer: ctx.registryUrl,\n enableImmutableInstalls: false,\n unsafeHttpWhitelist: ['localhost'],\n });\n await writeFile(join(tf, '.yarnrc.yml'), yamlContent);\n await writeFile(join(tf, 'package.json'), getPackageJSON(pkgName, '1.0.0'));\n await writeFile(join(tf, 'README.md'), getREADME(pkgName));\n if (ctx.adapter.importPlugin) {\n await ctx.adapter.importPlugin(tf, 'npm-login');\n }\n await yarnLogin(ctx, tf, user1, password1, email1);\n await ctx.adapter.exec({ cwd: tf }, 'install');\n const pubResp = await ctx.adapter.exec({ cwd: tf }, 'publish');\n assert.ok(\n pubResp.stdout.includes('Package archive published'),\n `Expected publish success but got \"${pubResp.stdout}\"`\n );\n });\n\n await ctx.subTest('switch users', async () => {\n const user2 = `login-b-${id}`;\n const password2 = 'other-password-456';\n const email2 = `${user2}@test.example.com`;\n const tf = await prepareLoginProject(ctx, `verdaccio-login5-${id}`);\n\n await yarnLogin(ctx, tf, user1, password1, email1);\n const who1 = await yarnWhoami(ctx, tf);\n assert.ok(who1.includes(user1), `Expected \"${user1}\" but got \"${who1}\"`);\n\n await yarnLogin(ctx, tf, user2, password2, email2);\n const who2 = await yarnWhoami(ctx, tf);\n assert.ok(who2.includes(user2), `Expected \"${user2}\" after switch but got \"${who2}\"`);\n });\n}\n\nexport const loginTest: TestDefinition = {\n name: 'login',\n requires: ['login'],\n run: testLogin,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"login.js","names":[],"sources":["../../../src/tests/login.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\nimport { writeFile } from 'fs/promises';\nimport YAML from 'js-yaml';\nimport { join } from 'path';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { createTempFolder, getPackageJSON, getREADME } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:test:login');\n\n/**\n * Creates a project with registry config but WITHOUT auth token,\n * so whoami will use the token saved by login to ~/.yarnrc.yml.\n */\nasync function prepareLoginProject(ctx: TestContext, name: string): Promise<string> {\n debug('preparing project for %s (no auth token)', name);\n const tempFolder = await createTempFolder(name);\n const yamlContent = YAML.dump({\n npmRegistryServer: ctx.registryUrl,\n enableImmutableInstalls: false,\n unsafeHttpWhitelist: ['localhost'],\n });\n await writeFile(join(tempFolder, '.yarnrc.yml'), yamlContent);\n await writeFile(join(tempFolder, 'package.json'), JSON.stringify({ name, version: '1.0.0' }));\n if (ctx.adapter.importPlugin) {\n debug('importing npm-login plugin into %s', tempFolder);\n await ctx.adapter.importPlugin(tempFolder, 'npm-login');\n }\n return tempFolder;\n}\n\nasync function yarnLogin(\n ctx: TestContext,\n cwd: string,\n user: string,\n password: string,\n email: string\n) {\n debug('yarn npm login as %s', user);\n return ctx.adapter.exec(\n { cwd },\n 'login',\n '--auth-type=legacy',\n `--user=${user}`,\n `--password=${password}`,\n `--email=${email}`\n );\n}\n\nasync function yarnWhoami(ctx: TestContext, cwd: string): Promise<string> {\n const resp = await ctx.adapter.exec({ cwd }, 'whoami');\n debug('yarn npm whoami: %s', resp.stdout);\n return resp.stdout;\n}\n\nasync function testLogin(ctx: TestContext): Promise<void> {\n const type = ctx.adapter.type;\n const id = ctx.runId;\n\n if (type !== 'yarn-modern') {\n debug('login test only supported for yarn-modern, skipping %s', type);\n return;\n }\n\n const user1 = `login-a-${id}`;\n const password1 = 'test-password-123';\n const email1 = `${user1}@test.example.com`;\n\n await ctx.subTest('create new user + whoami', async () => {\n const tf = await prepareLoginProject(ctx, `verdaccio-login1-${id}`);\n const loginResp = await yarnLogin(ctx, tf, user1, password1, email1);\n assert.ok(\n loginResp.stdout.includes('Logged in') || loginResp.stdout.includes('token saved'),\n `Expected login success message but got \"${loginResp.stdout}\"`\n );\n const who = await yarnWhoami(ctx, tf);\n assert.ok(who.includes(user1), `Expected whoami \"${user1}\" but got \"${who}\"`);\n });\n\n await ctx.subTest('login existing user', async () => {\n const tf = await prepareLoginProject(ctx, `verdaccio-login2-${id}`);\n const loginResp = await yarnLogin(ctx, tf, user1, password1, email1);\n assert.ok(\n loginResp.stdout.includes('Logged in') || loginResp.stdout.includes('token saved'),\n `Expected login success for existing user but got \"${loginResp.stdout}\"`\n );\n const who = await yarnWhoami(ctx, tf);\n assert.ok(who.includes(user1), `Expected \"${user1}\" but got \"${who}\"`);\n });\n\n await ctx.subTest('wrong password fails', async () => {\n const tf = await prepareLoginProject(ctx, `verdaccio-login3-${id}`);\n let loginFailed = false;\n try {\n await yarnLogin(ctx, tf, user1, 'wrong-password', email1);\n } catch {\n loginFailed = true;\n }\n assert.ok(loginFailed, 'Login with wrong password should have failed');\n });\n\n await ctx.subTest('login then publish', async () => {\n const pkgName = `@verdaccio/login-pub-${id}`;\n const tf = await createTempFolder(`login-pub-${id}`);\n const yamlContent = YAML.dump({\n npmRegistryServer: ctx.registryUrl,\n enableImmutableInstalls: false,\n unsafeHttpWhitelist: ['localhost'],\n });\n await writeFile(join(tf, '.yarnrc.yml'), yamlContent);\n await writeFile(join(tf, 'package.json'), getPackageJSON(pkgName, '1.0.0'));\n await writeFile(join(tf, 'README.md'), getREADME(pkgName));\n if (ctx.adapter.importPlugin) {\n await ctx.adapter.importPlugin(tf, 'npm-login');\n }\n await yarnLogin(ctx, tf, user1, password1, email1);\n await ctx.adapter.exec({ cwd: tf }, 'install');\n const pubResp = await ctx.adapter.exec({ cwd: tf }, 'publish');\n assert.ok(\n pubResp.stdout.includes('Package archive published'),\n `Expected publish success but got \"${pubResp.stdout}\"`\n );\n });\n\n await ctx.subTest('switch users', async () => {\n const user2 = `login-b-${id}`;\n const password2 = 'other-password-456';\n const email2 = `${user2}@test.example.com`;\n const tf = await prepareLoginProject(ctx, `verdaccio-login5-${id}`);\n\n await yarnLogin(ctx, tf, user1, password1, email1);\n const who1 = await yarnWhoami(ctx, tf);\n assert.ok(who1.includes(user1), `Expected \"${user1}\" but got \"${who1}\"`);\n\n await yarnLogin(ctx, tf, user2, password2, email2);\n const who2 = await yarnWhoami(ctx, tf);\n assert.ok(who2.includes(user2), `Expected \"${user2}\" after switch but got \"${who2}\"`);\n });\n}\n\nexport const loginTest: TestDefinition = {\n name: 'login',\n requires: ['login'],\n run: testLogin,\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ping.js","names":[],"sources":["../../../src/tests/ping.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testPing(ctx: TestContext): Promise<void> {\n const type = ctx.adapter.type;\n const needsProject = type === 'yarn-modern';\n let cwd: string | undefined;\n\n if (needsProject) {\n const { tempFolder } = await ctx.adapter.prepareProject(\n `verdaccio-ping-${ctx.runId}`,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n cwd = tempFolder;\n if (ctx.adapter.importPlugin) {\n await ctx.adapter.importPlugin(tempFolder, 'npm-ping');\n }\n }\n\n const jsonFlag = type === 'yarn-modern' ? [] : ['--json'];\n const resp = await ctx.adapter.exec(\n { cwd },\n 'ping',\n ...jsonFlag,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n if (type === 'yarn-modern') {\n // yarn npm ping succeeding (exit code 0) is sufficient proof the registry is reachable\n assert.ok(true, 'ping succeeded');\n } else {\n const parsedBody = JSON.parse(resp.stdout);\n assert.strictEqual(\n parsedBody.registry,\n ctx.registryUrl + '/',\n `Expected registry \"${ctx.registryUrl}/\" but got \"${parsedBody.registry}\"`\n );\n }\n}\n\nexport const pingTest: TestDefinition = {\n name: 'ping',\n requires: ['ping'],\n run: testPing,\n};\n"],"mappings":";;AAIA,eAAe,SAAS,KAAiC;CACvD,MAAM,OAAO,IAAI,QAAQ;CACzB,MAAM,eAAe,SAAS;CAC9B,IAAI;AAEJ,KAAI,cAAc;EAChB,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,kBAAkB,IAAI,SACtB,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,QAAM;AACN,MAAI,IAAI,QAAQ,aACd,OAAM,IAAI,QAAQ,aAAa,YAAY,WAAW;;CAI1D,MAAM,WAAW,SAAS,gBAAgB,EAAE,GAAG,CAAC,SAAS;CACzD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,EACP,QACA,GAAG,UACH,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AAED,KAAI,SAAS,cAEX,QAAO,GAAG,MAAM,iBAAiB;MAC5B;EACL,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;AAC1C,SAAO,YACL,WAAW,UACX,IAAI,cAAc,KAClB,sBAAsB,IAAI,YAAY,cAAc,WAAW,SAAS,GACzE;;;AAIL,IAAa,WAA2B;CACtC,MAAM;CACN,UAAU,CAAC,OAAO;CAClB,KAAK;CACN"}
1
+ {"version":3,"file":"ping.js","names":[],"sources":["../../../src/tests/ping.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testPing(ctx: TestContext): Promise<void> {\n const type = ctx.adapter.type;\n const needsProject = type === 'yarn-modern';\n let cwd: string | undefined;\n\n if (needsProject) {\n const { tempFolder } = await ctx.adapter.prepareProject(\n `verdaccio-ping-${ctx.runId}`,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n cwd = tempFolder;\n if (ctx.adapter.importPlugin) {\n await ctx.adapter.importPlugin(tempFolder, 'npm-ping');\n }\n }\n\n const jsonFlag = type === 'yarn-modern' ? [] : ['--json'];\n const resp = await ctx.adapter.exec(\n { cwd },\n 'ping',\n ...jsonFlag,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n if (type === 'yarn-modern') {\n // yarn npm ping succeeding (exit code 0) is sufficient proof the registry is reachable\n assert.ok(true, 'ping succeeded');\n } else {\n const parsedBody = JSON.parse(resp.stdout);\n assert.strictEqual(\n parsedBody.registry,\n ctx.registryUrl + '/',\n `Expected registry \"${ctx.registryUrl}/\" but got \"${parsedBody.registry}\"`\n );\n }\n}\n\nexport const pingTest: TestDefinition = {\n name: 'ping',\n requires: ['ping'],\n run: testPing,\n};\n"],"mappings":";;AAIA,eAAe,SAAS,KAAiC;CACvD,MAAM,OAAO,IAAI,QAAQ;CACzB,MAAM,eAAe,SAAS;CAC9B,IAAI;CAEJ,IAAI,cAAc;EAChB,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,kBAAkB,IAAI,SACtB,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;EACD,MAAM;EACN,IAAI,IAAI,QAAQ,cACd,MAAM,IAAI,QAAQ,aAAa,YAAY,WAAW;;CAI1D,MAAM,WAAW,SAAS,gBAAgB,EAAE,GAAG,CAAC,SAAS;CACzD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,EACP,QACA,GAAG,UACH,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CAED,IAAI,SAAS,eAEX,OAAO,GAAG,MAAM,iBAAiB;MAC5B;EACL,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;EAC1C,OAAO,YACL,WAAW,UACX,IAAI,cAAc,KAClB,sBAAsB,IAAI,YAAY,cAAc,WAAW,SAAS,GACzE;;;AAIL,IAAa,WAA2B;CACtC,MAAM;CACN,UAAU,CAAC,OAAO;CAClB,KAAK;CACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"publish.js","names":[],"sources":["../../../src/tests/publish.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testPublish(ctx: TestContext): Promise<void> {\n const packages = [\n `verdaccio-memory-${ctx.runId}`,\n `verdaccio-${ctx.runId}`,\n `@verdaccio/foo-${ctx.runId}`,\n `@verdaccio/some-foo-${ctx.runId}`,\n ];\n\n const type = ctx.adapter.type;\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 );\n\n // yarn modern requires install before publish to generate lockfile\n if (type === 'yarn-modern') {\n await ctx.adapter.exec({ cwd: tempFolder }, 'install');\n }\n\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n if (type === 'yarn-modern') {\n assert.ok(\n resp.stdout.match(/Package archive published/),\n `Expected \"Package archive published\" for ${pkgName} but got \"${resp.stdout}\"`\n );\n } else if (type === 'yarn-classic') {\n // yarn classic --json outputs NDJSON — just verify no error exit (exit code 0 is enough)\n assert.ok(resp.stdout.length > 0, `Expected publish output for ${pkgName}`);\n } else if (type === 'bun') {\n // bun publish outputs text confirmation — exit code 0 is sufficient\n assert.ok(true, `Publish succeeded for ${pkgName}`);\n } else {\n // npm / pnpm\n try {\n const parsedBody = JSON.parse(resp.stdout);\n assert.strictEqual(\n parsedBody.name,\n pkgName,\n `Expected package name \"${pkgName}\" but got \"${parsedBody.name}\"`\n );\n assert.ok(parsedBody.files, `Expected files to be defined for ${pkgName}`);\n } catch {\n // pnpm v11+ native publish doesn't output JSON — exit code 0 is sufficient\n assert.ok(true, `Publish succeeded for ${pkgName}`);\n }\n }\n }\n}\n\nexport const publishTest: TestDefinition = {\n name: 'publish',\n requires: ['publish'],\n run: testPublish,\n};\n"],"mappings":";;AAIA,eAAe,YAAY,KAAiC;CAC1D,MAAM,WAAW;EACf,oBAAoB,IAAI;EACxB,aAAa,IAAI;EACjB,kBAAkB,IAAI;EACtB,uBAAuB,IAAI;EAC5B;CAED,MAAM,OAAO,IAAI,QAAQ;AAEzB,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AAGD,MAAI,SAAS,cACX,OAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,YAAY,EAAE,UAAU;EAGxD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,WACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AAED,MAAI,SAAS,cACX,QAAO,GACL,KAAK,OAAO,MAAM,4BAA4B,EAC9C,4CAA4C,QAAQ,YAAY,KAAK,OAAO,GAC7E;WACQ,SAAS,eAElB,QAAO,GAAG,KAAK,OAAO,SAAS,GAAG,+BAA+B,UAAU;WAClE,SAAS,MAElB,QAAO,GAAG,MAAM,yBAAyB,UAAU;MAGnD,KAAI;GACF,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;AAC1C,UAAO,YACL,WAAW,MACX,SACA,0BAA0B,QAAQ,aAAa,WAAW,KAAK,GAChE;AACD,UAAO,GAAG,WAAW,OAAO,oCAAoC,UAAU;UACpE;AAEN,UAAO,GAAG,MAAM,yBAAyB,UAAU;;;;AAM3D,IAAa,cAA8B;CACzC,MAAM;CACN,UAAU,CAAC,UAAU;CACrB,KAAK;CACN"}
1
+ {"version":3,"file":"publish.js","names":[],"sources":["../../../src/tests/publish.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testPublish(ctx: TestContext): Promise<void> {\n const packages = [\n `verdaccio-memory-${ctx.runId}`,\n `verdaccio-${ctx.runId}`,\n `@verdaccio/foo-${ctx.runId}`,\n `@verdaccio/some-foo-${ctx.runId}`,\n ];\n\n const type = ctx.adapter.type;\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 );\n\n // yarn modern requires install before publish to generate lockfile\n if (type === 'yarn-modern') {\n await ctx.adapter.exec({ cwd: tempFolder }, 'install');\n }\n\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n\n if (type === 'yarn-modern') {\n assert.ok(\n resp.stdout.match(/Package archive published/),\n `Expected \"Package archive published\" for ${pkgName} but got \"${resp.stdout}\"`\n );\n } else if (type === 'yarn-classic') {\n // yarn classic --json outputs NDJSON — just verify no error exit (exit code 0 is enough)\n assert.ok(resp.stdout.length > 0, `Expected publish output for ${pkgName}`);\n } else if (type === 'bun') {\n // bun publish outputs text confirmation — exit code 0 is sufficient\n assert.ok(true, `Publish succeeded for ${pkgName}`);\n } else {\n // npm / pnpm\n try {\n const parsedBody = JSON.parse(resp.stdout);\n assert.strictEqual(\n parsedBody.name,\n pkgName,\n `Expected package name \"${pkgName}\" but got \"${parsedBody.name}\"`\n );\n assert.ok(parsedBody.files, `Expected files to be defined for ${pkgName}`);\n } catch {\n // pnpm v11+ native publish doesn't output JSON — exit code 0 is sufficient\n assert.ok(true, `Publish succeeded for ${pkgName}`);\n }\n }\n }\n}\n\nexport const publishTest: TestDefinition = {\n name: 'publish',\n requires: ['publish'],\n run: testPublish,\n};\n"],"mappings":";;AAIA,eAAe,YAAY,KAAiC;CAC1D,MAAM,WAAW;EACf,oBAAoB,IAAI;EACxB,aAAa,IAAI;EACjB,kBAAkB,IAAI;EACtB,uBAAuB,IAAI;EAC5B;CAED,MAAM,OAAO,IAAI,QAAQ;CAEzB,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;EAGD,IAAI,SAAS,eACX,MAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,YAAY,EAAE,UAAU;EAGxD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,WACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;EAED,IAAI,SAAS,eACX,OAAO,GACL,KAAK,OAAO,MAAM,4BAA4B,EAC9C,4CAA4C,QAAQ,YAAY,KAAK,OAAO,GAC7E;OACI,IAAI,SAAS,gBAElB,OAAO,GAAG,KAAK,OAAO,SAAS,GAAG,+BAA+B,UAAU;OACtE,IAAI,SAAS,OAElB,OAAO,GAAG,MAAM,yBAAyB,UAAU;OAGnD,IAAI;GACF,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;GAC1C,OAAO,YACL,WAAW,MACX,SACA,0BAA0B,QAAQ,aAAa,WAAW,KAAK,GAChE;GACD,OAAO,GAAG,WAAW,OAAO,oCAAoC,UAAU;UACpE;GAEN,OAAO,GAAG,MAAM,yBAAyB,UAAU;;;;AAM3D,IAAa,cAA8B;CACzC,MAAM;CACN,UAAU,CAAC,UAAU;CACrB,KAAK;CACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","names":[],"sources":["../../../src/tests/search.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testSearch(ctx: TestContext): Promise<void> {\n const resp = await ctx.adapter.exec(\n {},\n 'search',\n '@verdaccio/cli',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const parsedBody = JSON.parse(resp.stdout);\n const pkgFind = parsedBody.find((item: any) => item.name === '@verdaccio/cli');\n assert.ok(pkgFind, 'Expected to find @verdaccio/cli in search results');\n assert.strictEqual(pkgFind.name, '@verdaccio/cli');\n}\n\nexport const searchTest: TestDefinition = {\n name: 'search',\n requires: ['search'],\n run: testSearch,\n};\n"],"mappings":";;AAIA,eAAe,WAAW,KAAiC;CACzD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,EACF,UACA,kBACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CAED,MAAM,UADa,KAAK,MAAM,KAAK,OAAO,CACf,MAAM,SAAc,KAAK,SAAS,iBAAiB;AAC9E,QAAO,GAAG,SAAS,oDAAoD;AACvE,QAAO,YAAY,QAAQ,MAAM,iBAAiB;;AAGpD,IAAa,aAA6B;CACxC,MAAM;CACN,UAAU,CAAC,SAAS;CACpB,KAAK;CACN"}
1
+ {"version":3,"file":"search.js","names":[],"sources":["../../../src/tests/search.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testSearch(ctx: TestContext): Promise<void> {\n const resp = await ctx.adapter.exec(\n {},\n 'search',\n '@verdaccio/cli',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const parsedBody = JSON.parse(resp.stdout);\n const pkgFind = parsedBody.find((item: any) => item.name === '@verdaccio/cli');\n assert.ok(pkgFind, 'Expected to find @verdaccio/cli in search results');\n assert.strictEqual(pkgFind.name, '@verdaccio/cli');\n}\n\nexport const searchTest: TestDefinition = {\n name: 'search',\n requires: ['search'],\n run: testSearch,\n};\n"],"mappings":";;AAIA,eAAe,WAAW,KAAiC;CACzD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,EACF,UACA,kBACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CAED,MAAM,UADa,KAAK,MAAM,KAAK,OACnB,CAAW,MAAM,SAAc,KAAK,SAAS,iBAAiB;CAC9E,OAAO,GAAG,SAAS,oDAAoD;CACvE,OAAO,YAAY,QAAQ,MAAM,iBAAiB;;AAGpD,IAAa,aAA6B;CACxC,MAAM;CACN,UAAU,CAAC,SAAS;CACpB,KAAK;CACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"star.js","names":[],"sources":["../../../src/tests/star.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testStar(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Test 1: star a package\n const pkgName1 = `@verdaccio/star1-${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 ctx.adapter.exec({ cwd: tf1 }, 'publish', ...ctx.adapter.registryArg(ctx.registryUrl));\n const resp1 = await ctx.adapter.exec(\n { cwd: tf1 },\n 'star',\n pkgName1,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp1.stdout.includes(pkgName1),\n `Expected star output to contain \"${pkgName1}\" but got \"${resp1.stdout}\"`\n );\n\n // Test 2: unstar a package\n const pkgName2 = `@verdaccio/star2-${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 ctx.adapter.exec({ cwd: tf2 }, 'publish', ...ctx.adapter.registryArg(ctx.registryUrl));\n await ctx.adapter.exec(\n { cwd: tf2 },\n 'star',\n pkgName2,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const resp2 = await ctx.adapter.exec(\n { cwd: tf2 },\n 'unstar',\n pkgName2,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp2.stdout.includes(pkgName2),\n `Expected unstar output to contain \"${pkgName2}\" but got \"${resp2.stdout}\"`\n );\n}\n\nexport const starTest: TestDefinition = {\n name: 'star',\n requires: ['star'],\n run: testStar,\n};\n"],"mappings":";;AAIA,eAAe,SAAS,KAAiC;CACvD,MAAM,KAAK,IAAI;CAGf,MAAM,WAAW,oBAAoB;CACrC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,KAAK,EAAE,WAAW,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;CAC5F,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,QACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AACD,QAAO,GACL,MAAM,OAAO,SAAS,SAAS,EAC/B,oCAAoC,SAAS,aAAa,MAAM,OAAO,GACxE;CAGD,MAAM,WAAW,oBAAoB;CACrC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,KAAK,EAAE,WAAW,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;AAC5F,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,KAAK,EACZ,QACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,UACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AACD,QAAO,GACL,MAAM,OAAO,SAAS,SAAS,EAC/B,sCAAsC,SAAS,aAAa,MAAM,OAAO,GAC1E;;AAGH,IAAa,WAA2B;CACtC,MAAM;CACN,UAAU,CAAC,OAAO;CAClB,KAAK;CACN"}
1
+ {"version":3,"file":"star.js","names":[],"sources":["../../../src/tests/star.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function testStar(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Test 1: star a package\n const pkgName1 = `@verdaccio/star1-${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 ctx.adapter.exec({ cwd: tf1 }, 'publish', ...ctx.adapter.registryArg(ctx.registryUrl));\n const resp1 = await ctx.adapter.exec(\n { cwd: tf1 },\n 'star',\n pkgName1,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp1.stdout.includes(pkgName1),\n `Expected star output to contain \"${pkgName1}\" but got \"${resp1.stdout}\"`\n );\n\n // Test 2: unstar a package\n const pkgName2 = `@verdaccio/star2-${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 ctx.adapter.exec({ cwd: tf2 }, 'publish', ...ctx.adapter.registryArg(ctx.registryUrl));\n await ctx.adapter.exec(\n { cwd: tf2 },\n 'star',\n pkgName2,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n const resp2 = await ctx.adapter.exec(\n { cwd: tf2 },\n 'unstar',\n pkgName2,\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp2.stdout.includes(pkgName2),\n `Expected unstar output to contain \"${pkgName2}\" but got \"${resp2.stdout}\"`\n );\n}\n\nexport const starTest: TestDefinition = {\n name: 'star',\n requires: ['star'],\n run: testStar,\n};\n"],"mappings":";;AAIA,eAAe,SAAS,KAAiC;CACvD,MAAM,KAAK,IAAI;CAGf,MAAM,WAAW,oBAAoB;CACrC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;CACD,MAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,KAAK,EAAE,WAAW,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;CAC5F,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,QACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,OAAO,GACL,MAAM,OAAO,SAAS,SAAS,EAC/B,oCAAoC,SAAS,aAAa,MAAM,OAAO,GACxE;CAGD,MAAM,WAAW,oBAAoB;CACrC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;CACD,MAAM,IAAI,QAAQ,KAAK,EAAE,KAAK,KAAK,EAAE,WAAW,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAAC;CAC5F,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,KAAK,EACZ,QACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,UACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,OAAO,GACL,MAAM,OAAO,SAAS,SAAS,EAC/B,sCAAsC,SAAS,aAAa,MAAM,OAAO,GAC1E;;AAGH,IAAa,WAA2B;CACtC,MAAM;CACN,UAAU,CAAC,OAAO;CAClB,KAAK;CACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"unpublish.js","names":[],"sources":["../../../src/tests/unpublish.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function publishPkg(ctx: TestContext, tempFolder: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function bumpVersion(ctx: TestContext, tempFolder: string, bump: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'version',\n bump,\n '--no--git-tag-version',\n '--loglevel=info',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function testUnpublish(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Test 1: unpublish a full package\n const pkgName = `@verdaccio/unpub1-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tempFolder);\n await bumpVersion(ctx, tempFolder, 'minor');\n await publishPkg(ctx, tempFolder);\n await bumpVersion(ctx, tempFolder, 'minor');\n await publishPkg(ctx, tempFolder);\n await bumpVersion(ctx, tempFolder, 'major');\n await publishPkg(ctx, tempFolder);\n\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'unpublish',\n pkgName,\n '--force',\n '--loglevel=info',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp.stdout.includes(pkgName),\n `Expected unpublish output to contain \"${pkgName}\" but got \"${resp.stdout}\"`\n );\n\n // Test 2: unpublish a specific version\n const pkgName2 = `@verdaccio/unpub2-${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, 'minor');\n await publishPkg(ctx, tf2);\n\n const resp2 = await ctx.adapter.exec(\n { cwd: tf2 },\n 'unpublish',\n `${pkgName2}@1.0.0`,\n '--force',\n '--loglevel=info',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp2.stdout.includes(pkgName2),\n `Expected unpublish output to contain \"${pkgName2}\" but got \"${resp2.stdout}\"`\n );\n}\n\nexport const unpublishTest: TestDefinition = {\n name: 'unpublish',\n requires: ['unpublish'],\n run: testUnpublish,\n};\n"],"mappings":";;AAIA,eAAe,WAAW,KAAkB,YAAoB;AAC9D,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,YAAY,KAAkB,YAAoB,MAAc;AAC7E,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,MACA,yBACA,mBACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,cAAc,KAAiC;CAC5D,MAAM,KAAK,IAAI;CAGf,MAAM,UAAU,qBAAqB;CACrC,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,WAAW;AACjC,OAAM,YAAY,KAAK,YAAY,QAAQ;AAC3C,OAAM,WAAW,KAAK,WAAW;AACjC,OAAM,YAAY,KAAK,YAAY,QAAQ;AAC3C,OAAM,WAAW,KAAK,WAAW;AACjC,OAAM,YAAY,KAAK,YAAY,QAAQ;AAC3C,OAAM,WAAW,KAAK,WAAW;CAEjC,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,aACA,SACA,WACA,mBACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AACD,QAAO,GACL,KAAK,OAAO,SAAS,QAAQ,EAC7B,yCAAyC,QAAQ,aAAa,KAAK,OAAO,GAC3E;CAGD,MAAM,WAAW,qBAAqB;CACtC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,IAAI;AAC1B,OAAM,YAAY,KAAK,KAAK,QAAQ;AACpC,OAAM,WAAW,KAAK,IAAI;CAE1B,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,aACA,GAAG,SAAS,SACZ,WACA,mBACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AACD,QAAO,GACL,MAAM,OAAO,SAAS,SAAS,EAC/B,yCAAyC,SAAS,aAAa,MAAM,OAAO,GAC7E;;AAGH,IAAa,gBAAgC;CAC3C,MAAM;CACN,UAAU,CAAC,YAAY;CACvB,KAAK;CACN"}
1
+ {"version":3,"file":"unpublish.js","names":[],"sources":["../../../src/tests/unpublish.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function publishPkg(ctx: TestContext, tempFolder: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function bumpVersion(ctx: TestContext, tempFolder: string, bump: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'version',\n bump,\n '--no--git-tag-version',\n '--loglevel=info',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function testUnpublish(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Test 1: unpublish a full package\n const pkgName = `@verdaccio/unpub1-${id}`;\n const { tempFolder } = await ctx.adapter.prepareProject(\n pkgName,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tempFolder);\n await bumpVersion(ctx, tempFolder, 'minor');\n await publishPkg(ctx, tempFolder);\n await bumpVersion(ctx, tempFolder, 'minor');\n await publishPkg(ctx, tempFolder);\n await bumpVersion(ctx, tempFolder, 'major');\n await publishPkg(ctx, tempFolder);\n\n const resp = await ctx.adapter.exec(\n { cwd: tempFolder },\n 'unpublish',\n pkgName,\n '--force',\n '--loglevel=info',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp.stdout.includes(pkgName),\n `Expected unpublish output to contain \"${pkgName}\" but got \"${resp.stdout}\"`\n );\n\n // Test 2: unpublish a specific version\n const pkgName2 = `@verdaccio/unpub2-${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, 'minor');\n await publishPkg(ctx, tf2);\n\n const resp2 = await ctx.adapter.exec(\n { cwd: tf2 },\n 'unpublish',\n `${pkgName2}@1.0.0`,\n '--force',\n '--loglevel=info',\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n assert.ok(\n resp2.stdout.includes(pkgName2),\n `Expected unpublish output to contain \"${pkgName2}\" but got \"${resp2.stdout}\"`\n );\n}\n\nexport const unpublishTest: TestDefinition = {\n name: 'unpublish',\n requires: ['unpublish'],\n run: testUnpublish,\n};\n"],"mappings":";;AAIA,eAAe,WAAW,KAAkB,YAAoB;CAC9D,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,YAAY,KAAkB,YAAoB,MAAc;CAC7E,MAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,MACA,yBACA,mBACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,cAAc,KAAiC;CAC5D,MAAM,KAAK,IAAI;CAGf,MAAM,UAAU,qBAAqB;CACrC,MAAM,EAAE,eAAe,MAAM,IAAI,QAAQ,eACvC,SACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;CACD,MAAM,WAAW,KAAK,WAAW;CACjC,MAAM,YAAY,KAAK,YAAY,QAAQ;CAC3C,MAAM,WAAW,KAAK,WAAW;CACjC,MAAM,YAAY,KAAK,YAAY,QAAQ;CAC3C,MAAM,WAAW,KAAK,WAAW;CACjC,MAAM,YAAY,KAAK,YAAY,QAAQ;CAC3C,MAAM,WAAW,KAAK,WAAW;CAEjC,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,KAAK,YAAY,EACnB,aACA,SACA,WACA,mBACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,OAAO,GACL,KAAK,OAAO,SAAS,QAAQ,EAC7B,yCAAyC,QAAQ,aAAa,KAAK,OAAO,GAC3E;CAGD,MAAM,WAAW,qBAAqB;CACtC,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,KAAK,QAAQ;CACpC,MAAM,WAAW,KAAK,IAAI;CAE1B,MAAM,QAAQ,MAAM,IAAI,QAAQ,KAC9B,EAAE,KAAK,KAAK,EACZ,aACA,GAAG,SAAS,SACZ,WACA,mBACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;CACD,OAAO,GACL,MAAM,OAAO,SAAS,SAAS,EAC/B,yCAAyC,SAAS,aAAa,MAAM,OAAO,GAC7E;;AAGH,IAAa,gBAAgC;CAC3C,MAAM;CACN,UAAU,CAAC,YAAY;CACvB,KAAK;CACN"}
@@ -1 +1 @@
1
- {"version":3,"file":"process.js","names":[],"sources":["../../../src/utils/process.ts"],"sourcesContent":["import { SpawnOptions, spawn } from 'child_process';\nimport buildDebug from 'debug';\nimport { basename } from 'path';\nimport { createInterface } from 'readline';\n\nimport { ExecOutput } from '../types';\n\nconst debug = buildDebug('verdaccio:e2e-cli:process');\nconst debugRead = buildDebug('verdaccio:e2e-cli:line');\n\nlet _verbose = false;\n\nexport function setVerbose(v: boolean) {\n _verbose = v;\n}\n\nconst COLORS = {\n reset: '\\x1b[0m',\n dim: '\\x1b[2m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n};\n\nfunction shortCmd(cmd: string, args: string[]): string {\n const bin = basename(cmd);\n return `${bin} ${args.join(' ')}`;\n}\n\nexport async function exec(\n options: SpawnOptions,\n cmd: string,\n args: string[]\n): Promise<ExecOutput> {\n debug('start exec %o %o %o', options, cmd, args ? args.join(' ') : '');\n let stdout = '';\n let stderr = '';\n\n if (_verbose) {\n const cwd = options.cwd\n ? ` ${COLORS.dim}(cwd: ${basename(String(options.cwd))})${COLORS.reset}`\n : '';\n process.stdout.write(` ${COLORS.cyan}$${COLORS.reset} ${shortCmd(cmd, args)}${cwd}\\n`);\n }\n\n const spawnOptions: SpawnOptions = {\n cwd: options.cwd,\n stdio: options.stdio || 'pipe',\n env: options.env || process.env,\n };\n\n if (process.platform.startsWith('win')) {\n args.unshift('/c', cmd);\n cmd = 'cmd.exe';\n spawnOptions.stdio = 'pipe';\n }\n\n const start = Date.now();\n const childProcess = spawn(cmd, args, spawnOptions);\n\n if (childProcess.stdout) {\n childProcess.stdout.on('data', (data) => {\n debugRead('data %o', data.toString());\n });\n const rl = createInterface({\n input: childProcess.stdout,\n output: process.stdout,\n terminal: false,\n });\n\n rl.on('line', function (line) {\n debugRead('line %o', line);\n stdout += line;\n });\n }\n\n if (childProcess.stderr) {\n childProcess.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n }\n\n const err = new Error(`Running \"${cmd} ${args.join(' ')}\" returned error code `);\n return new Promise((resolve, reject) => {\n childProcess.on('exit', (code) => {\n const duration = Date.now() - start;\n debugRead('exit %o', code);\n\n if (_verbose) {\n const status = code\n ? `${COLORS.red}exit ${code}${COLORS.reset}`\n : `${COLORS.green}ok${COLORS.reset}`;\n process.stdout.write(\n ` ${COLORS.dim} -> ${status} ${COLORS.dim}(${duration}ms)${COLORS.reset}\\n`\n );\n }\n\n if (!code) {\n resolve({ stdout, stderr });\n } else {\n err.message += `${code}...\\n\\nSTDOUT:\\n${stdout}\\n\\nSTDERR:\\n${stderr}\\n`;\n reject(err);\n }\n });\n });\n}\n"],"mappings":";;;;;AAOA,IAAM,QAAQ,WAAW,4BAA4B;AACrD,IAAM,YAAY,WAAW,yBAAyB;AAEtD,IAAI,WAAW;AAEf,SAAgB,WAAW,GAAY;AACrC,YAAW;;AAGb,IAAM,SAAS;CACb,OAAO;CACP,KAAK;CACL,MAAM;CACN,OAAO;CACP,KAAK;CACL,QAAQ;CACT;AAED,SAAS,SAAS,KAAa,MAAwB;AAErD,QAAO,GADK,SAAS,IAAI,CACX,GAAG,KAAK,KAAK,IAAI;;AAGjC,eAAsB,KACpB,SACA,KACA,MACqB;AACrB,OAAM,uBAAuB,SAAS,KAAK,OAAO,KAAK,KAAK,IAAI,GAAG,GAAG;CACtE,IAAI,SAAS;CACb,IAAI,SAAS;AAEb,KAAI,UAAU;EACZ,MAAM,MAAM,QAAQ,MAChB,IAAI,OAAO,IAAI,QAAQ,SAAS,OAAO,QAAQ,IAAI,CAAC,CAAC,GAAG,OAAO,UAC/D;AACJ,UAAQ,OAAO,MAAM,SAAS,OAAO,KAAK,GAAG,OAAO,MAAM,GAAG,SAAS,KAAK,KAAK,GAAG,IAAI,IAAI;;CAG7F,MAAM,eAA6B;EACjC,KAAK,QAAQ;EACb,OAAO,QAAQ,SAAS;EACxB,KAAK,QAAQ,OAAO,QAAQ;EAC7B;AAED,KAAI,QAAQ,SAAS,WAAW,MAAM,EAAE;AACtC,OAAK,QAAQ,MAAM,IAAI;AACvB,QAAM;AACN,eAAa,QAAQ;;CAGvB,MAAM,QAAQ,KAAK,KAAK;CACxB,MAAM,eAAe,MAAM,KAAK,MAAM,aAAa;AAEnD,KAAI,aAAa,QAAQ;AACvB,eAAa,OAAO,GAAG,SAAS,SAAS;AACvC,aAAU,WAAW,KAAK,UAAU,CAAC;IACrC;AACS,kBAAgB;GACzB,OAAO,aAAa;GACpB,QAAQ,QAAQ;GAChB,UAAU;GACX,CAAC,CAEC,GAAG,QAAQ,SAAU,MAAM;AAC5B,aAAU,WAAW,KAAK;AAC1B,aAAU;IACV;;AAGJ,KAAI,aAAa,OACf,cAAa,OAAO,GAAG,SAAS,SAAS;AACvC,YAAU,KAAK,UAAU;GACzB;CAGJ,MAAM,sBAAM,IAAI,MAAM,YAAY,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,wBAAwB;AAChF,QAAO,IAAI,SAAS,SAAS,WAAW;AACtC,eAAa,GAAG,SAAS,SAAS;GAChC,MAAM,WAAW,KAAK,KAAK,GAAG;AAC9B,aAAU,WAAW,KAAK;AAE1B,OAAI,UAAU;IACZ,MAAM,SAAS,OACX,GAAG,OAAO,IAAI,OAAO,OAAO,OAAO,UACnC,GAAG,OAAO,MAAM,IAAI,OAAO;AAC/B,YAAQ,OAAO,MACb,SAAS,OAAO,IAAI,OAAO,OAAO,GAAG,OAAO,IAAI,GAAG,SAAS,KAAK,OAAO,MAAM,IAC/E;;AAGH,OAAI,CAAC,KACH,SAAQ;IAAE;IAAQ;IAAQ,CAAC;QACtB;AACL,QAAI,WAAW,GAAG,KAAK,kBAAkB,OAAO,eAAe,OAAO;AACtE,WAAO,IAAI;;IAEb;GACF"}
1
+ {"version":3,"file":"process.js","names":[],"sources":["../../../src/utils/process.ts"],"sourcesContent":["import { SpawnOptions, spawn } from 'child_process';\nimport buildDebug from 'debug';\nimport { basename } from 'path';\nimport { createInterface } from 'readline';\n\nimport { ExecOutput } from '../types';\n\nconst debug = buildDebug('verdaccio:e2e-cli:process');\nconst debugRead = buildDebug('verdaccio:e2e-cli:line');\n\nlet _verbose = false;\n\nexport function setVerbose(v: boolean) {\n _verbose = v;\n}\n\nconst COLORS = {\n reset: '\\x1b[0m',\n dim: '\\x1b[2m',\n cyan: '\\x1b[36m',\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n};\n\nfunction shortCmd(cmd: string, args: string[]): string {\n const bin = basename(cmd);\n return `${bin} ${args.join(' ')}`;\n}\n\nexport async function exec(\n options: SpawnOptions,\n cmd: string,\n args: string[]\n): Promise<ExecOutput> {\n debug('start exec %o %o %o', options, cmd, args ? args.join(' ') : '');\n let stdout = '';\n let stderr = '';\n\n if (_verbose) {\n const cwd = options.cwd\n ? ` ${COLORS.dim}(cwd: ${basename(String(options.cwd))})${COLORS.reset}`\n : '';\n process.stdout.write(` ${COLORS.cyan}$${COLORS.reset} ${shortCmd(cmd, args)}${cwd}\\n`);\n }\n\n const spawnOptions: SpawnOptions = {\n cwd: options.cwd,\n stdio: options.stdio || 'pipe',\n env: options.env || process.env,\n };\n\n if (process.platform.startsWith('win')) {\n args.unshift('/c', cmd);\n cmd = 'cmd.exe';\n spawnOptions.stdio = 'pipe';\n }\n\n const start = Date.now();\n const childProcess = spawn(cmd, args, spawnOptions);\n\n if (childProcess.stdout) {\n childProcess.stdout.on('data', (data) => {\n debugRead('data %o', data.toString());\n });\n const rl = createInterface({\n input: childProcess.stdout,\n output: process.stdout,\n terminal: false,\n });\n\n rl.on('line', function (line) {\n debugRead('line %o', line);\n stdout += line;\n });\n }\n\n if (childProcess.stderr) {\n childProcess.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n }\n\n const err = new Error(`Running \"${cmd} ${args.join(' ')}\" returned error code `);\n return new Promise((resolve, reject) => {\n childProcess.on('exit', (code) => {\n const duration = Date.now() - start;\n debugRead('exit %o', code);\n\n if (_verbose) {\n const status = code\n ? `${COLORS.red}exit ${code}${COLORS.reset}`\n : `${COLORS.green}ok${COLORS.reset}`;\n process.stdout.write(\n ` ${COLORS.dim} -> ${status} ${COLORS.dim}(${duration}ms)${COLORS.reset}\\n`\n );\n }\n\n if (!code) {\n resolve({ stdout, stderr });\n } else {\n err.message += `${code}...\\n\\nSTDOUT:\\n${stdout}\\n\\nSTDERR:\\n${stderr}\\n`;\n reject(err);\n }\n });\n });\n}\n"],"mappings":";;;;;AAOA,IAAM,QAAQ,WAAW,4BAA4B;AACrD,IAAM,YAAY,WAAW,yBAAyB;AAEtD,IAAI,WAAW;AAEf,SAAgB,WAAW,GAAY;CACrC,WAAW;;AAGb,IAAM,SAAS;CACb,OAAO;CACP,KAAK;CACL,MAAM;CACN,OAAO;CACP,KAAK;CACL,QAAQ;CACT;AAED,SAAS,SAAS,KAAa,MAAwB;CAErD,OAAO,GADK,SAAS,IACX,CAAI,GAAG,KAAK,KAAK,IAAI;;AAGjC,eAAsB,KACpB,SACA,KACA,MACqB;CACrB,MAAM,uBAAuB,SAAS,KAAK,OAAO,KAAK,KAAK,IAAI,GAAG,GAAG;CACtE,IAAI,SAAS;CACb,IAAI,SAAS;CAEb,IAAI,UAAU;EACZ,MAAM,MAAM,QAAQ,MAChB,IAAI,OAAO,IAAI,QAAQ,SAAS,OAAO,QAAQ,IAAI,CAAC,CAAC,GAAG,OAAO,UAC/D;EACJ,QAAQ,OAAO,MAAM,SAAS,OAAO,KAAK,GAAG,OAAO,MAAM,GAAG,SAAS,KAAK,KAAK,GAAG,IAAI,IAAI;;CAG7F,MAAM,eAA6B;EACjC,KAAK,QAAQ;EACb,OAAO,QAAQ,SAAS;EACxB,KAAK,QAAQ,OAAO,QAAQ;EAC7B;CAED,IAAI,QAAQ,SAAS,WAAW,MAAM,EAAE;EACtC,KAAK,QAAQ,MAAM,IAAI;EACvB,MAAM;EACN,aAAa,QAAQ;;CAGvB,MAAM,QAAQ,KAAK,KAAK;CACxB,MAAM,eAAe,MAAM,KAAK,MAAM,aAAa;CAEnD,IAAI,aAAa,QAAQ;EACvB,aAAa,OAAO,GAAG,SAAS,SAAS;GACvC,UAAU,WAAW,KAAK,UAAU,CAAC;IACrC;EAOF,gBAN2B;GACzB,OAAO,aAAa;GACpB,QAAQ,QAAQ;GAChB,UAAU;GACX,CAED,CAAG,GAAG,QAAQ,SAAU,MAAM;GAC5B,UAAU,WAAW,KAAK;GAC1B,UAAU;IACV;;CAGJ,IAAI,aAAa,QACf,aAAa,OAAO,GAAG,SAAS,SAAS;EACvC,UAAU,KAAK,UAAU;GACzB;CAGJ,MAAM,sBAAM,IAAI,MAAM,YAAY,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,wBAAwB;CAChF,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,aAAa,GAAG,SAAS,SAAS;GAChC,MAAM,WAAW,KAAK,KAAK,GAAG;GAC9B,UAAU,WAAW,KAAK;GAE1B,IAAI,UAAU;IACZ,MAAM,SAAS,OACX,GAAG,OAAO,IAAI,OAAO,OAAO,OAAO,UACnC,GAAG,OAAO,MAAM,IAAI,OAAO;IAC/B,QAAQ,OAAO,MACb,SAAS,OAAO,IAAI,OAAO,OAAO,GAAG,OAAO,IAAI,GAAG,SAAS,KAAK,OAAO,MAAM,IAC/E;;GAGH,IAAI,CAAC,MACH,QAAQ;IAAE;IAAQ;IAAQ,CAAC;QACtB;IACL,IAAI,WAAW,GAAG,KAAK,kBAAkB,OAAO,eAAe,OAAO;IACtE,OAAO,IAAI;;IAEb;GACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","names":[],"sources":["../../../src/utils/project.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { mkdirSync } from 'fs';\nimport { mkdtemp, writeFile } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\n\nconst debug = buildDebug('verdaccio:e2e-cli:project');\n\nexport async function createTempFolder(prefix: string): Promise<string> {\n const sanitized = prefix.replace(/[^a-zA-Z0-9-_]/g, '-');\n debug('creating temp folder %o', sanitized);\n return mkdtemp(join(tmpdir(), `verdaccio-e2e-${sanitized}-`));\n}\n\nexport function getPackageJSON(\n packageName: string,\n version = '1.0.0',\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n): string {\n debug('creating package.json %o', packageName);\n const json = {\n name: packageName,\n version,\n description: 'some cool project',\n main: 'index.js',\n scripts: {\n test: 'echo exit 1',\n },\n dependencies,\n devDependencies,\n keywords: ['foo', 'bar'],\n author: 'Verdaccio E2E <verdaccio@example.org>',\n license: 'MIT',\n };\n return JSON.stringify(json);\n}\n\nexport function getREADME(packageName: string): string {\n return `\n # My README ${packageName}\n\n some text\n\n ## subtitle\n\n more text\n `;\n}\n\nexport async function prepareGenericEmptyProject(\n packageName: string,\n version: string,\n port: number,\n token: string,\n registryDomain: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n): Promise<{ tempFolder: string }> {\n debug('preparing generic project %o', packageName);\n const getNPMrc = (port: number, token: string, registry: string) =>\n `//localhost:${port}/:_authToken=${token}\\nregistry=${registry}`;\n const tempFolder = await createTempFolder('temp-folder');\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 await writeFile(join(tempFolder, '.npmrc'), getNPMrc(port, token, registryDomain));\n return { tempFolder };\n}\n"],"mappings":";;;;;AAMA,IAAM,QAAQ,WAAW,4BAA4B;AAErD,eAAsB,iBAAiB,QAAiC;CACtE,MAAM,YAAY,OAAO,QAAQ,mBAAmB,IAAI;AACxD,OAAM,2BAA2B,UAAU;AAC3C,QAAO,QAAQ,KAAK,QAAQ,EAAE,iBAAiB,UAAU,GAAG,CAAC;;AAG/D,SAAgB,eACd,aACA,UAAU,SACV,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACpC;AACR,OAAM,4BAA4B,YAAY;AAe9C,QAAO,KAAK,UAdC;EACX,MAAM;EACN;EACA,aAAa;EACb,MAAM;EACN,SAAS,EACP,MAAM,eACP;EACD;EACA;EACA,UAAU,CAAC,OAAO,MAAM;EACxB,QAAQ;EACR,SAAS;EACV,CAC0B;;AAG7B,SAAgB,UAAU,aAA6B;AACrD,QAAO;iBACQ,YAAY;;;;;;;;;AAU7B,eAAsB,2BACpB,aACA,SACA,MACA,OACA,gBACA,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACX;AACjC,OAAM,gCAAgC,YAAY;CAClD,MAAM,YAAY,MAAc,OAAe,aAC7C,eAAe,KAAK,eAAe,MAAM,aAAa;CACxD,MAAM,aAAa,MAAM,iBAAiB,cAAc;AACxD,OAAM,UACJ,KAAK,YAAY,eAAe,EAChC,eAAe,aAAa,SAAS,cAAc,gBAAgB,CACpE;AACD,OAAM,UAAU,KAAK,YAAY,YAAY,EAAE,UAAU,YAAY,CAAC;AACtE,OAAM,UAAU,KAAK,YAAY,SAAS,EAAE,SAAS,MAAM,OAAO,eAAe,CAAC;AAClF,QAAO,EAAE,YAAY"}
1
+ {"version":3,"file":"project.js","names":[],"sources":["../../../src/utils/project.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { mkdirSync } from 'fs';\nimport { mkdtemp, writeFile } from 'fs/promises';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\n\nconst debug = buildDebug('verdaccio:e2e-cli:project');\n\nexport async function createTempFolder(prefix: string): Promise<string> {\n const sanitized = prefix.replace(/[^a-zA-Z0-9-_]/g, '-');\n debug('creating temp folder %o', sanitized);\n return mkdtemp(join(tmpdir(), `verdaccio-e2e-${sanitized}-`));\n}\n\nexport function getPackageJSON(\n packageName: string,\n version = '1.0.0',\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n): string {\n debug('creating package.json %o', packageName);\n const json = {\n name: packageName,\n version,\n description: 'some cool project',\n main: 'index.js',\n scripts: {\n test: 'echo exit 1',\n },\n dependencies,\n devDependencies,\n keywords: ['foo', 'bar'],\n author: 'Verdaccio E2E <verdaccio@example.org>',\n license: 'MIT',\n };\n return JSON.stringify(json);\n}\n\nexport function getREADME(packageName: string): string {\n return `\n # My README ${packageName}\n\n some text\n\n ## subtitle\n\n more text\n `;\n}\n\nexport async function prepareGenericEmptyProject(\n packageName: string,\n version: string,\n port: number,\n token: string,\n registryDomain: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n): Promise<{ tempFolder: string }> {\n debug('preparing generic project %o', packageName);\n const getNPMrc = (port: number, token: string, registry: string) =>\n `//localhost:${port}/:_authToken=${token}\\nregistry=${registry}`;\n const tempFolder = await createTempFolder('temp-folder');\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 await writeFile(join(tempFolder, '.npmrc'), getNPMrc(port, token, registryDomain));\n return { tempFolder };\n}\n"],"mappings":";;;;;AAMA,IAAM,QAAQ,WAAW,4BAA4B;AAErD,eAAsB,iBAAiB,QAAiC;CACtE,MAAM,YAAY,OAAO,QAAQ,mBAAmB,IAAI;CACxD,MAAM,2BAA2B,UAAU;CAC3C,OAAO,QAAQ,KAAK,QAAQ,EAAE,iBAAiB,UAAU,GAAG,CAAC;;AAG/D,SAAgB,eACd,aACA,UAAU,SACV,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACpC;CACR,MAAM,4BAA4B,YAAY;CAe9C,OAAO,KAAK,UAAU;EAbpB,MAAM;EACN;EACA,aAAa;EACb,MAAM;EACN,SAAS,EACP,MAAM,eACP;EACD;EACA;EACA,UAAU,CAAC,OAAO,MAAM;EACxB,QAAQ;EACR,SAAS;EAEW,CAAK;;AAG7B,SAAgB,UAAU,aAA6B;CACrD,OAAO;iBACQ,YAAY;;;;;;;;;AAU7B,eAAsB,2BACpB,aACA,SACA,MACA,OACA,gBACA,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACX;CACjC,MAAM,gCAAgC,YAAY;CAClD,MAAM,YAAY,MAAc,OAAe,aAC7C,eAAe,KAAK,eAAe,MAAM,aAAa;CACxD,MAAM,aAAa,MAAM,iBAAiB,cAAc;CACxD,MAAM,UACJ,KAAK,YAAY,eAAe,EAChC,eAAe,aAAa,SAAS,cAAc,gBAAgB,CACpE;CACD,MAAM,UAAU,KAAK,YAAY,YAAY,EAAE,UAAU,YAAY,CAAC;CACtE,MAAM,UAAU,KAAK,YAAY,SAAS,EAAE,SAAS,MAAM,OAAO,eAAe,CAAC;CAClF,OAAO,EAAE,YAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry-client.js","names":[],"sources":["../../../src/utils/registry-client.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport { ping } from '@verdaccio/registry-cli';\n\nconst debug = buildDebug('verdaccio:e2e-cli:registry-client');\n\nexport type RegistryAuth = {\n token: string;\n user: string;\n};\n\n/**\n * Creates a user on the registry and returns the auth token.\n * Uses a unique username per run to avoid 409 conflicts.\n * Works against any running Verdaccio instance with htpasswd auth.\n */\nexport async function createUser(\n registryUrl: string,\n user = `e2e-user-${Date.now()}`,\n password = 'e2e-test-password'\n): Promise<RegistryAuth> {\n debug('creating user %s on %s', user, registryUrl);\n const url = `${registryUrl}/-/user/org.couchdb.user:${encodeURIComponent(user)}`;\n const response = await fetch(url, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n name: user,\n password,\n _id: `org.couchdb.user:${user}`,\n type: 'user',\n roles: [],\n date: new Date().toISOString(),\n }),\n });\n\n const body = (await response.json()) as any;\n\n if (response.status === 201 || response.status === 200 || response.status === 409) {\n const token = body.token;\n if (token) {\n debug('user %s authenticated, token obtained', user);\n return { token, user };\n }\n }\n\n throw new Error(\n `Failed to create/login user \"${user}\" on ${registryUrl}: ${response.status} ${JSON.stringify(body)}`\n );\n}\n\n/**\n * Ping the registry to check it's alive.\n * Uses @verdaccio/registry-cli ping.\n */\nexport async function pingRegistry(registryUrl: string): Promise<boolean> {\n debug('pinging %s', registryUrl);\n try {\n const result = await ping(registryUrl);\n return result.ok;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;AAIA,IAAM,QAAQ,WAAW,oCAAoC;;;;;;AAY7D,eAAsB,WACpB,aACA,OAAO,YAAY,KAAK,KAAK,IAC7B,WAAW,qBACY;AACvB,OAAM,0BAA0B,MAAM,YAAY;CAClD,MAAM,MAAM,GAAG,YAAY,2BAA2B,mBAAmB,KAAK;CAC9E,MAAM,WAAW,MAAM,MAAM,KAAK;EAChC,QAAQ;EACR,SAAS,EAAE,gBAAgB,oBAAoB;EAC/C,MAAM,KAAK,UAAU;GACnB,MAAM;GACN;GACA,KAAK,oBAAoB;GACzB,MAAM;GACN,OAAO,EAAE;GACT,uBAAM,IAAI,MAAM,EAAC,aAAa;GAC/B,CAAC;EACH,CAAC;CAEF,MAAM,OAAQ,MAAM,SAAS,MAAM;AAEnC,KAAI,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;EACjF,MAAM,QAAQ,KAAK;AACnB,MAAI,OAAO;AACT,SAAM,yCAAyC,KAAK;AACpD,UAAO;IAAE;IAAO;IAAM;;;AAI1B,OAAM,IAAI,MACR,gCAAgC,KAAK,OAAO,YAAY,IAAI,SAAS,OAAO,GAAG,KAAK,UAAU,KAAK,GACpG;;;;;;AAOH,eAAsB,aAAa,aAAuC;AACxE,OAAM,cAAc,YAAY;AAChC,KAAI;AAEF,UADe,MAAM,KAAK,YAAY,EACxB;SACR;AACN,SAAO"}
1
+ {"version":3,"file":"registry-client.js","names":[],"sources":["../../../src/utils/registry-client.ts"],"sourcesContent":["import buildDebug from 'debug';\n\nimport { ping } from '@verdaccio/registry-cli';\n\nconst debug = buildDebug('verdaccio:e2e-cli:registry-client');\n\nexport type RegistryAuth = {\n token: string;\n user: string;\n};\n\n/**\n * Creates a user on the registry and returns the auth token.\n * Uses a unique username per run to avoid 409 conflicts.\n * Works against any running Verdaccio instance with htpasswd auth.\n */\nexport async function createUser(\n registryUrl: string,\n user = `e2e-user-${Date.now()}`,\n password = 'e2e-test-password'\n): Promise<RegistryAuth> {\n debug('creating user %s on %s', user, registryUrl);\n const url = `${registryUrl}/-/user/org.couchdb.user:${encodeURIComponent(user)}`;\n const response = await fetch(url, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n name: user,\n password,\n _id: `org.couchdb.user:${user}`,\n type: 'user',\n roles: [],\n date: new Date().toISOString(),\n }),\n });\n\n const body = (await response.json()) as any;\n\n if (response.status === 201 || response.status === 200 || response.status === 409) {\n const token = body.token;\n if (token) {\n debug('user %s authenticated, token obtained', user);\n return { token, user };\n }\n }\n\n throw new Error(\n `Failed to create/login user \"${user}\" on ${registryUrl}: ${response.status} ${JSON.stringify(body)}`\n );\n}\n\n/**\n * Ping the registry to check it's alive.\n * Uses @verdaccio/registry-cli ping.\n */\nexport async function pingRegistry(registryUrl: string): Promise<boolean> {\n debug('pinging %s', registryUrl);\n try {\n const result = await ping(registryUrl);\n return result.ok;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;AAIA,IAAM,QAAQ,WAAW,oCAAoC;;;;;;AAY7D,eAAsB,WACpB,aACA,OAAO,YAAY,KAAK,KAAK,IAC7B,WAAW,qBACY;CACvB,MAAM,0BAA0B,MAAM,YAAY;CAClD,MAAM,MAAM,GAAG,YAAY,2BAA2B,mBAAmB,KAAK;CAC9E,MAAM,WAAW,MAAM,MAAM,KAAK;EAChC,QAAQ;EACR,SAAS,EAAE,gBAAgB,oBAAoB;EAC/C,MAAM,KAAK,UAAU;GACnB,MAAM;GACN;GACA,KAAK,oBAAoB;GACzB,MAAM;GACN,OAAO,EAAE;GACT,uBAAM,IAAI,MAAM,EAAC,aAAa;GAC/B,CAAC;EACH,CAAC;CAEF,MAAM,OAAQ,MAAM,SAAS,MAAM;CAEnC,IAAI,SAAS,WAAW,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;EACjF,MAAM,QAAQ,KAAK;EACnB,IAAI,OAAO;GACT,MAAM,yCAAyC,KAAK;GACpD,OAAO;IAAE;IAAO;IAAM;;;CAI1B,MAAM,IAAI,MACR,gCAAgC,KAAK,OAAO,YAAY,IAAI,SAAS,OAAO,GAAG,KAAK,UAAU,KAAK,GACpG;;;;;;AAOH,eAAsB,aAAa,aAAuC;CACxE,MAAM,cAAc,YAAY;CAChC,IAAI;EAEF,QAAO,MADc,KAAK,YAAY,EACxB;SACR;EACN,OAAO"}
@@ -1,4 +1,5 @@
1
1
  import { TestDefinition } from '../types';
2
2
  import { installMultipleDepsScenario } from './install-multiple-deps';
3
+ import { minimumReleaseAgeScenario } from './minimum-release-age';
3
4
  export declare const allScenarios: TestDefinition[];
4
- export { installMultipleDepsScenario };
5
+ export { installMultipleDepsScenario, minimumReleaseAgeScenario };
@@ -0,0 +1,11 @@
1
+ import { PackageManagerAdapter, TestDefinition } from '../types';
2
+ /**
3
+ * True only for pnpm versions that actually enforce minimumReleaseAge.
4
+ *
5
+ * The cooldown is honored in pnpm 11.1.0+, but it is silently ignored in
6
+ * 11.0.0 / 11.0.1 (and the 11.0.0 release candidates) — those versions install
7
+ * brand-new packages regardless of the configured cooldown. We scope this
8
+ * scenario to pnpm 11.1.0 and newer so it doesn't false-fail on that regression.
9
+ */
10
+ export declare function isPnpm11Plus(adapter: PackageManagerAdapter): boolean;
11
+ export declare const minimumReleaseAgeScenario: TestDefinition;
@@ -1,4 +1,4 @@
1
- import { allScenarios, installMultipleDepsScenario } from '../scenarios';
1
+ import { allScenarios, installMultipleDepsScenario, minimumReleaseAgeScenario } from '../scenarios';
2
2
  import { TestDefinition } from '../types';
3
3
  import { auditTest } from './audit';
4
4
  import { ciTest } from './ci';
@@ -13,4 +13,4 @@ import { searchTest } from './search';
13
13
  import { starTest } from './star';
14
14
  import { unpublishTest } from './unpublish';
15
15
  export declare const allTests: TestDefinition[];
16
- export { publishTest, installTest, ciTest, auditTest, infoTest, deprecateTest, distTagsTest, loginTest, pingTest, searchTest, starTest, unpublishTest, installMultipleDepsScenario, allScenarios, };
16
+ export { publishTest, installTest, ciTest, auditTest, infoTest, deprecateTest, distTagsTest, loginTest, pingTest, searchTest, starTest, unpublishTest, installMultipleDepsScenario, minimumReleaseAgeScenario, allScenarios, };
package/build/types.d.ts CHANGED
@@ -41,6 +41,12 @@ export type TestDefinition = {
41
41
  run: (ctx: TestContext) => Promise<void>;
42
42
  /** Commands required for this test (e.g. 'deprecate', 'star'). Skipped if adapter doesn't support them. */
43
43
  requires?: string[];
44
+ /**
45
+ * Predicate to gate a test to specific adapters/versions. Returns false to skip.
46
+ * Use for tests that only make sense on a particular package manager or version
47
+ * (e.g. pnpm-only settings). Evaluated after the `requires` check.
48
+ */
49
+ appliesTo?: (adapter: PackageManagerAdapter) => boolean;
44
50
  };
45
51
  export interface PackageManagerAdapter {
46
52
  /** Display name, e.g. "npm@10" */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/e2e-cli",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "CLI tool to run Verdaccio e2e tests against any running registry",
@@ -30,13 +30,13 @@
30
30
  "@verdaccio/registry-cli": "^1.1.0",
31
31
  "debug": "4.4.0",
32
32
  "get-port": "5.1.1",
33
- "js-yaml": "4.1.0"
33
+ "js-yaml": "4.1.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/debug": "4.1.12",
37
37
  "@types/js-yaml": "4.0.9",
38
38
  "@types/node": "24.12.4",
39
- "vite": "8.0.1"
39
+ "vite": "8.0.11"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "vite build && tsc --emitDeclarationOnly -p tsconfig.build.json",