@verdaccio/e2e-cli 2.6.0 → 2.8.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 (56) hide show
  1. package/build/adapters/bun.d.ts +2 -0
  2. package/build/adapters/deno.d.ts +2 -0
  3. package/build/adapters/index.d.ts +2 -0
  4. package/build/cjs/adapters/bun.cjs +63 -0
  5. package/build/cjs/adapters/bun.cjs.map +1 -0
  6. package/build/cjs/adapters/deno.cjs +58 -0
  7. package/build/cjs/adapters/deno.cjs.map +1 -0
  8. package/build/cjs/adapters/index.cjs +2 -0
  9. package/build/cjs/index.cjs +16 -6
  10. package/build/cjs/index.cjs.map +1 -1
  11. package/build/cjs/scenarios/index.cjs +6 -0
  12. package/build/cjs/scenarios/index.cjs.map +1 -0
  13. package/build/cjs/scenarios/install-multiple-deps.cjs +116 -0
  14. package/build/cjs/scenarios/install-multiple-deps.cjs.map +1 -0
  15. package/build/cjs/tests/audit.cjs +24 -4
  16. package/build/cjs/tests/audit.cjs.map +1 -1
  17. package/build/cjs/tests/ci.cjs +83 -0
  18. package/build/cjs/tests/ci.cjs.map +1 -0
  19. package/build/cjs/tests/index.cjs +6 -1
  20. package/build/cjs/tests/index.cjs.map +1 -1
  21. package/build/cjs/tests/info.cjs +3 -0
  22. package/build/cjs/tests/info.cjs.map +1 -1
  23. package/build/cjs/tests/install.cjs +0 -1
  24. package/build/cjs/tests/install.cjs.map +1 -1
  25. package/build/cjs/tests/publish.cjs +1 -0
  26. package/build/cjs/tests/publish.cjs.map +1 -1
  27. package/build/esm/adapters/bun.js +61 -0
  28. package/build/esm/adapters/bun.js.map +1 -0
  29. package/build/esm/adapters/deno.js +56 -0
  30. package/build/esm/adapters/deno.js.map +1 -0
  31. package/build/esm/adapters/index.js +2 -0
  32. package/build/esm/index.js +11 -4
  33. package/build/esm/index.js.map +1 -1
  34. package/build/esm/scenarios/index.js +7 -0
  35. package/build/esm/scenarios/index.js.map +1 -0
  36. package/build/esm/scenarios/install-multiple-deps.js +113 -0
  37. package/build/esm/scenarios/install-multiple-deps.js.map +1 -0
  38. package/build/esm/tests/audit.js +23 -4
  39. package/build/esm/tests/audit.js.map +1 -1
  40. package/build/esm/tests/ci.js +80 -0
  41. package/build/esm/tests/ci.js.map +1 -0
  42. package/build/esm/tests/index.js +6 -1
  43. package/build/esm/tests/index.js.map +1 -1
  44. package/build/esm/tests/info.js +3 -0
  45. package/build/esm/tests/info.js.map +1 -1
  46. package/build/esm/tests/install.js +0 -1
  47. package/build/esm/tests/install.js.map +1 -1
  48. package/build/esm/tests/publish.js +1 -0
  49. package/build/esm/tests/publish.js.map +1 -1
  50. package/build/index.d.ts +2 -1
  51. package/build/scenarios/index.d.ts +4 -0
  52. package/build/scenarios/install-multiple-deps.d.ts +2 -0
  53. package/build/tests/ci.d.ts +2 -0
  54. package/build/tests/index.d.ts +3 -1
  55. package/build/types.d.ts +2 -2
  56. package/package.json +1 -1
@@ -0,0 +1,80 @@
1
+ import buildDebug from "debug";
2
+ import { join } from "path";
3
+ import { rm } from "fs/promises";
4
+ import assert from "assert";
5
+ //#region src/tests/ci.ts
6
+ var debug = buildDebug("verdaccio:e2e-cli:test:ci");
7
+ /**
8
+ * Test: ci
9
+ *
10
+ * Verifies that lockfile-based install works correctly.
11
+ * Unlike `install`, CI commands skip metadata fetches and resolve
12
+ * tarballs directly from the URLs stored in the lockfile.
13
+ *
14
+ * Flow:
15
+ * 1. Prepare a project with dependencies
16
+ * 2. Run `install` to generate the lockfile
17
+ * 3. Remove node_modules
18
+ * 4. Run the CI-equivalent command (npm ci / pnpm install --frozen-lockfile / yarn --frozen-lockfile / yarn --immutable)
19
+ * 5. Verify it completes successfully
20
+ */
21
+ function getCiArgs(ctx) {
22
+ switch (ctx.adapter.type) {
23
+ case "npm": return ["ci", ...ctx.adapter.registryArg(ctx.registryUrl)];
24
+ case "pnpm": return [
25
+ "install",
26
+ "--frozen-lockfile",
27
+ ...ctx.adapter.registryArg(ctx.registryUrl)
28
+ ];
29
+ case "yarn-classic": return [
30
+ "install",
31
+ "--frozen-lockfile",
32
+ ...ctx.adapter.registryArg(ctx.registryUrl)
33
+ ];
34
+ case "yarn-modern": return ["install", "--immutable"];
35
+ case "bun": return [
36
+ "install",
37
+ "--frozen-lockfile",
38
+ ...ctx.adapter.registryArg(ctx.registryUrl)
39
+ ];
40
+ default: return ["ci", ...ctx.adapter.registryArg(ctx.registryUrl)];
41
+ }
42
+ }
43
+ async function testCi(ctx) {
44
+ if (ctx.adapter.type === "deno") {
45
+ debug("skipping ci test for deno (no ci command)");
46
+ return;
47
+ }
48
+ const { tempFolder } = await ctx.adapter.prepareProject(`ci-test-${ctx.runId}`, "1.0.0", ctx.registryUrl, ctx.port, ctx.token, { "is-odd": "1.0.0" });
49
+ debug("running initial install to generate lockfile in %s", tempFolder);
50
+ await ctx.adapter.exec({ cwd: tempFolder }, "install", ...ctx.adapter.registryArg(ctx.registryUrl));
51
+ debug("lockfile generated, removing node_modules");
52
+ await rm(join(tempFolder, "node_modules"), {
53
+ recursive: true,
54
+ force: true
55
+ });
56
+ await rm(join(tempFolder, ".pnpm-store"), {
57
+ recursive: true,
58
+ force: true
59
+ });
60
+ debug("node_modules removed, running ci command");
61
+ const ciArgs = getCiArgs(ctx);
62
+ debug("ci args: %o", ciArgs);
63
+ const resp = await ctx.adapter.exec({ cwd: tempFolder }, ...ciArgs);
64
+ if (ctx.adapter.type === "npm") {
65
+ debug("npm ci output: %s", resp.stdout + resp.stderr);
66
+ assert.ok(true, "npm ci completed successfully");
67
+ } else {
68
+ debug("ci completed successfully for %s", ctx.adapter.type);
69
+ assert.ok(true, `CI install completed successfully for ${ctx.adapter.type}`);
70
+ }
71
+ }
72
+ var ciTest = {
73
+ name: "ci",
74
+ requires: ["install"],
75
+ run: testCi
76
+ };
77
+ //#endregion
78
+ export { ciTest };
79
+
80
+ //# sourceMappingURL=ci.js.map
@@ -0,0 +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,4 +1,7 @@
1
+ import "../scenarios/install-multiple-deps.js";
2
+ import { allScenarios } from "../scenarios/index.js";
1
3
  import { auditTest } from "./audit.js";
4
+ import { ciTest } from "./ci.js";
2
5
  import { deprecateTest } from "./deprecate.js";
3
6
  import { distTagsTest } from "./dist-tags.js";
4
7
  import { infoTest } from "./info.js";
@@ -13,6 +16,7 @@ import { unpublishTest } from "./unpublish.js";
13
16
  var allTests = [
14
17
  publishTest,
15
18
  installTest,
19
+ ciTest,
16
20
  auditTest,
17
21
  infoTest,
18
22
  deprecateTest,
@@ -21,7 +25,8 @@ var allTests = [
21
25
  pingTest,
22
26
  searchTest,
23
27
  starTest,
24
- unpublishTest
28
+ unpublishTest,
29
+ ...allScenarios
25
30
  ];
26
31
  //#endregion
27
32
  export { allTests };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/tests/index.ts"],"sourcesContent":["import { TestDefinition } from '../types';\n\nimport { auditTest } from './audit';\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 auditTest,\n infoTest,\n deprecateTest,\n distTagsTest,\n loginTest,\n pingTest,\n searchTest,\n starTest,\n unpublishTest,\n];\n\nexport {\n publishTest,\n installTest,\n auditTest,\n infoTest,\n deprecateTest,\n distTagsTest,\n loginTest,\n pingTest,\n searchTest,\n starTest,\n unpublishTest,\n};\n"],"mappings":";;;;;;;;;;;;AAcA,IAAa,WAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/tests/index.ts"],"sourcesContent":["import { TestDefinition } from '../types';\n\nimport { allScenarios, installMultipleDepsScenario } from '../scenarios';\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":";;;;;;;;;;;;;;;AAgBA,IAAa,WAA6B;CACxC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA,GAAG;CACJ"}
@@ -19,6 +19,9 @@ async function testInfo(ctx) {
19
19
  }
20
20
  });
21
21
  assert.ok(dataLine, "Expected yarn info NDJSON to contain an \"inspect\" entry");
22
+ } else if (ctx.adapter.type === "deno") {
23
+ const output = resp.stdout + resp.stderr;
24
+ assert.ok(output.includes("verdaccio"), "Expected deno info output to reference verdaccio");
22
25
  } else {
23
26
  const parsedBody = JSON.parse(resp.stdout);
24
27
  assert.strictEqual(parsedBody.name, "verdaccio", "Expected package name \"verdaccio\"");
@@ -1 +1 @@
1
- {"version":3,"file":"info.js","names":[],"sources":["../../../src/tests/info.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { createTempFolder } from '../utils/project';\nimport { writeFile } from 'fs/promises';\nimport { join } from 'path';\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(join(tempFolder, 'package.json'), JSON.stringify({ name: 'info-test', version: '1.0.0' }));\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 {\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,UAAU,KAAK,YAAY,eAAe,EAAE,KAAK,UAAU;EAAE,MAAM;EAAa,SAAS;EAAS,CAAC,CAAC;CAE1G,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;QACzE;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';\n\nimport { TestContext, TestDefinition } from '../types';\nimport { createTempFolder } from '../utils/project';\nimport { writeFile } from 'fs/promises';\nimport { join } from 'path';\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(join(tempFolder, 'package.json'), JSON.stringify({ name: 'info-test', version: '1.0.0' }));\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,UAAU,KAAK,YAAY,eAAe,EAAE,KAAK,UAAU;EAAE,MAAM;EAAa,SAAS;EAAS,CAAC,CAAC;CAE1G,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"}
@@ -12,7 +12,6 @@ async function testInstall(ctx) {
12
12
  if (isNpm) {
13
13
  const parsedBody = JSON.parse(resp.stdout);
14
14
  assert.ok(parsedBody.added !== void 0, "Expected \"added\" field in install response");
15
- assert.ok(parsedBody.audit !== void 0, "Expected \"audit\" field in install response");
16
15
  } else assert.ok(true, "Install completed successfully");
17
16
  }
18
17
  var installTest = {
@@ -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 assert.ok(parsedBody.audit !== undefined, 'Expected \"audit\" 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;AACvF,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;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"}
@@ -14,6 +14,7 @@ async function testPublish(ctx) {
14
14
  const resp = await ctx.adapter.exec({ cwd: tempFolder }, "publish", "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
15
15
  if (type === "yarn-modern") assert.ok(resp.stdout.match(/Package archive published/), `Expected "Package archive published" for ${pkgName} but got "${resp.stdout}"`);
16
16
  else if (type === "yarn-classic") assert.ok(resp.stdout.length > 0, `Expected publish output for ${pkgName}`);
17
+ else if (type === "bun") assert.ok(true, `Publish succeeded for ${pkgName}`);
17
18
  else try {
18
19
  const parsedBody = JSON.parse(resp.stdout);
19
20
  assert.strictEqual(parsedBody.name, pkgName, `Expected package name "${pkgName}" but got "${parsedBody.name}"`);
@@ -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 {\n // npm / pnpm\n try {\n const parsedBody = JSON.parse(resp.stdout);\n assert.strictEqual(parsedBody.name, pkgName, `Expected package name \"${pkgName}\" but got \"${parsedBody.name}\"`);\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;MAG3E,KAAI;GACF,MAAM,aAAa,KAAK,MAAM,KAAK,OAAO;AAC1C,UAAO,YAAY,WAAW,MAAM,SAAS,0BAA0B,QAAQ,aAAa,WAAW,KAAK,GAAG;AAC/G,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(parsedBody.name, pkgName, `Expected package name \"${pkgName}\" but got \"${parsedBody.name}\"`);\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,YAAY,WAAW,MAAM,SAAS,0BAA0B,QAAQ,aAAa,WAAW,KAAK,GAAG;AAC/G,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"}
package/build/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export declare function main(argv?: string[]): Promise<void>;
2
2
  export { allTests } from './tests';
3
- export { createNpmAdapter, createPnpmAdapter, createYarnClassicAdapter, createYarnModernAdapter } from './adapters';
3
+ export { allScenarios } from './scenarios';
4
+ export { createBunAdapter, createDenoAdapter, createNpmAdapter, createPnpmAdapter, createYarnClassicAdapter, createYarnModernAdapter } from './adapters';
4
5
  export { runAll, runSuite } from './runner';
5
6
  export type { PackageManagerAdapter, TestDefinition, TestContext, CliOptions } from './types';
@@ -0,0 +1,4 @@
1
+ import { TestDefinition } from '../types';
2
+ import { installMultipleDepsScenario } from './install-multiple-deps';
3
+ export declare const allScenarios: TestDefinition[];
4
+ export { installMultipleDepsScenario };
@@ -0,0 +1,2 @@
1
+ import { TestDefinition } from '../types';
2
+ export declare const installMultipleDepsScenario: TestDefinition;
@@ -0,0 +1,2 @@
1
+ import { TestDefinition } from '../types';
2
+ export declare const ciTest: TestDefinition;
@@ -1,5 +1,7 @@
1
1
  import { TestDefinition } from '../types';
2
+ import { allScenarios, installMultipleDepsScenario } from '../scenarios';
2
3
  import { auditTest } from './audit';
4
+ import { ciTest } from './ci';
3
5
  import { deprecateTest } from './deprecate';
4
6
  import { distTagsTest } from './dist-tags';
5
7
  import { infoTest } from './info';
@@ -11,4 +13,4 @@ import { searchTest } from './search';
11
13
  import { starTest } from './star';
12
14
  import { unpublishTest } from './unpublish';
13
15
  export declare const allTests: TestDefinition[];
14
- export { publishTest, installTest, auditTest, infoTest, deprecateTest, distTagsTest, loginTest, pingTest, searchTest, starTest, unpublishTest, };
16
+ export { publishTest, installTest, ciTest, auditTest, infoTest, deprecateTest, distTagsTest, loginTest, pingTest, searchTest, starTest, unpublishTest, installMultipleDepsScenario, allScenarios, };
package/build/types.d.ts CHANGED
@@ -46,8 +46,8 @@ export type TestDefinition = {
46
46
  export interface PackageManagerAdapter {
47
47
  /** Display name, e.g. "npm@10" */
48
48
  name: string;
49
- /** Package manager type: npm, pnpm, yarn-classic, yarn-modern */
50
- type: 'npm' | 'pnpm' | 'yarn-classic' | 'yarn-modern';
49
+ /** Package manager type: npm, pnpm, yarn-classic, yarn-modern, bun, deno */
50
+ type: 'npm' | 'pnpm' | 'yarn-classic' | 'yarn-modern' | 'bun' | 'deno';
51
51
  /** Resolved path to the binary */
52
52
  bin: string;
53
53
  /** Commands this PM supports */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdaccio/e2e-cli",
3
- "version": "2.6.0",
3
+ "version": "2.8.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "CLI tool to run Verdaccio e2e tests against any running registry",