@verdaccio/e2e-cli 2.4.0 → 2.5.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 (38) hide show
  1. package/build/cjs/adapters/yarn-modern.cjs +52 -3
  2. package/build/cjs/adapters/yarn-modern.cjs.map +1 -1
  3. package/build/cjs/reporter.cjs +57 -4
  4. package/build/cjs/reporter.cjs.map +1 -1
  5. package/build/cjs/runner.cjs +40 -6
  6. package/build/cjs/runner.cjs.map +1 -1
  7. package/build/cjs/tests/deprecate.cjs +82 -42
  8. package/build/cjs/tests/deprecate.cjs.map +1 -1
  9. package/build/cjs/tests/index.cjs +2 -0
  10. package/build/cjs/tests/index.cjs.map +1 -1
  11. package/build/cjs/tests/login.cjs +117 -0
  12. package/build/cjs/tests/login.cjs.map +1 -0
  13. package/build/cjs/tests/ping.cjs +15 -3
  14. package/build/cjs/tests/ping.cjs.map +1 -1
  15. package/build/cjs/utils/registry-client.cjs +3 -5
  16. package/build/cjs/utils/registry-client.cjs.map +1 -1
  17. package/build/esm/adapters/yarn-modern.js +52 -3
  18. package/build/esm/adapters/yarn-modern.js.map +1 -1
  19. package/build/esm/reporter.js +56 -5
  20. package/build/esm/reporter.js.map +1 -1
  21. package/build/esm/runner.js +41 -7
  22. package/build/esm/runner.js.map +1 -1
  23. package/build/esm/tests/deprecate.js +81 -42
  24. package/build/esm/tests/deprecate.js.map +1 -1
  25. package/build/esm/tests/index.js +2 -0
  26. package/build/esm/tests/index.js.map +1 -1
  27. package/build/esm/tests/login.js +113 -0
  28. package/build/esm/tests/login.js.map +1 -0
  29. package/build/esm/tests/ping.js +15 -3
  30. package/build/esm/tests/ping.js.map +1 -1
  31. package/build/esm/utils/registry-client.js +3 -5
  32. package/build/esm/utils/registry-client.js.map +1 -1
  33. package/build/reporter.d.ts +2 -1
  34. package/build/tests/index.d.ts +2 -1
  35. package/build/tests/login.d.ts +2 -0
  36. package/build/types.d.ts +11 -0
  37. package/build/utils/registry-client.d.ts +1 -0
  38. package/package.json +2 -1
@@ -14,7 +14,10 @@ var debug$1 = (0, debug.default)("verdaccio:e2e-cli:yarn-modern");
14
14
  var YARN_MODERN_SUPPORTED_COMMANDS = new Set([
15
15
  "publish",
16
16
  "install",
17
- "info"
17
+ "info",
18
+ "ping",
19
+ "deprecate",
20
+ "login"
18
21
  ]);
19
22
  var YARN_ENV = {
20
23
  COREPACK_ENABLE_STRICT: "0",
@@ -74,8 +77,8 @@ function createYamlConfig(registry, token) {
74
77
  unsafeHttpWhitelist: ["localhost"]
75
78
  };
76
79
  if (typeof token === "string") {
77
- const url$1 = new url.URL(registry);
78
- defaultYaml.npmRegistries = { [`//${url$1.hostname}:${url$1.port}`]: {
80
+ new url.URL(registry);
81
+ defaultYaml.npmRegistries = { [registry]: {
79
82
  npmAlwaysAuth: true,
80
83
  npmAuthToken: token
81
84
  } };
@@ -115,6 +118,26 @@ function createYarnModernAdapter(binPath, version) {
115
118
  "info",
116
119
  ...args.slice(1).filter((a) => !a.startsWith("--registry"))
117
120
  ];
121
+ else if (cmd === "ping") yarnArgs = [
122
+ "npm",
123
+ "ping",
124
+ ...args.slice(1).filter((a) => !a.startsWith("--registry"))
125
+ ];
126
+ else if (cmd === "deprecate") yarnArgs = [
127
+ "npm",
128
+ "deprecate",
129
+ ...args.slice(1).filter((a) => !a.startsWith("--registry"))
130
+ ];
131
+ else if (cmd === "login") yarnArgs = [
132
+ "npm",
133
+ "login",
134
+ ...args.slice(1).filter((a) => !a.startsWith("--registry"))
135
+ ];
136
+ else if (cmd === "whoami") yarnArgs = [
137
+ "npm",
138
+ "whoami",
139
+ ...args.slice(1).filter((a) => !a.startsWith("--registry"))
140
+ ];
118
141
  else yarnArgs = args.filter((a) => !a.startsWith("--registry"));
119
142
  return require_process.exec({
120
143
  ...options,
@@ -128,6 +151,32 @@ function createYarnModernAdapter(binPath, version) {
128
151
  await (0, fs_promises.writeFile)((0, path.join)(tempFolder, "package.json"), require_project.getPackageJSON(packageName, version, dependencies, devDependencies));
129
152
  await (0, fs_promises.writeFile)((0, path.join)(tempFolder, "README.md"), require_project.getREADME(packageName));
130
153
  return { tempFolder };
154
+ },
155
+ async importPlugin(cwd, pluginName) {
156
+ debug$1("downloading %s plugin bundle", pluginName);
157
+ const tmpDir = (0, child_process.execSync)("mktemp -d", { encoding: "utf8" }).trim();
158
+ (0, child_process.execSync)(`npm pack ${`@verdaccio/yarn-plugin-${pluginName}`} --pack-destination "${tmpDir}"`, {
159
+ encoding: "utf8",
160
+ timeout: 3e4,
161
+ stdio: "pipe"
162
+ });
163
+ (0, child_process.execSync)(`tar xzf "${tmpDir}"/*.tgz -C "${tmpDir}"`, {
164
+ encoding: "utf8",
165
+ stdio: "pipe"
166
+ });
167
+ const bundlePath = (0, path.join)(tmpDir, `package/bundles/@yarnpkg/plugin-${pluginName}.js`);
168
+ debug$1("importing plugin from %s into %s", bundlePath, cwd);
169
+ await require_process.exec({
170
+ cwd,
171
+ env: {
172
+ ...process.env,
173
+ ...YARN_ENV
174
+ }
175
+ }, bin, [
176
+ "plugin",
177
+ "import",
178
+ bundlePath
179
+ ]);
131
180
  }
132
181
  };
133
182
  }
@@ -1 +1 @@
1
- {"version":3,"file":"yarn-modern.cjs","names":[],"sources":["../../../src/adapters/yarn-modern.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\nimport { writeFile } from 'fs/promises';\nimport YAML from 'js-yaml';\nimport { join } from 'path';\nimport { URL } from 'url';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { createTempFolder, getPackageJSON, getREADME } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:yarn-modern');\n\nconst YARN_MODERN_SUPPORTED_COMMANDS = new Set(['publish', 'install', 'info']);\n\nconst YARN_ENV = {\n COREPACK_ENABLE_STRICT: '0',\n YARN_IGNORE_PATH: '1',\n};\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, {\n env: { ...process.env, ...YARN_ENV },\n encoding: 'utf8',\n timeout: 5000,\n }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction installYarnModern(version = '4'): string {\n const pkg = `@yarnpkg/cli-dist@${version}`;\n debug('installing %s into temp dir', pkg);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n execSync(`npm install --prefix \"${tmpDir}\" ${pkg} --loglevel=error`, {\n encoding: 'utf8',\n timeout: 30000,\n });\n const bin = `${tmpDir}/node_modules/@yarnpkg/cli-dist/bin/yarn.js`;\n const installed = detectVersion(bin);\n debug('installed yarn modern %s at %s', installed, bin);\n console.log(` Auto-installed yarn modern ${installed}`);\n return bin;\n}\n\nfunction resolveYarnBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n\n if (version) {\n return installYarnModern(version);\n }\n\n try {\n const systemYarn = execSync('which yarn', { encoding: 'utf8', timeout: 5000 }).trim();\n const sysVersion = detectVersion(systemYarn);\n const major = parseInt(sysVersion.split('.')[0], 10);\n if (major >= 2) {\n debug('using system yarn Berry %s', sysVersion);\n return systemYarn;\n }\n debug('system yarn is Classic %s, auto-installing Berry', sysVersion);\n } catch {\n debug('no system yarn found, auto-installing Berry');\n }\n\n return installYarnModern();\n}\n\nfunction createYamlConfig(registry: string, token?: string) {\n const defaultYaml: any = {\n npmRegistryServer: registry,\n enableImmutableInstalls: false,\n unsafeHttpWhitelist: ['localhost'],\n };\n\n if (typeof token === 'string') {\n const url = new URL(registry);\n defaultYaml.npmRegistries = {\n [`//${url.hostname}:${url.port}`]: {\n npmAlwaysAuth: true,\n npmAuthToken: token,\n },\n };\n }\n\n return YAML.dump(defaultYaml);\n}\n\nexport function createYarnModernAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolveYarnBin(binPath, version);\n const resolved = detectVersion(bin);\n debug('creating yarn modern adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `yarn-modern@${resolved}`,\n type: 'yarn-modern',\n bin,\n supports: YARN_MODERN_SUPPORTED_COMMANDS,\n\n registryArg(_url: string): string[] {\n return [];\n },\n\n prefixArg(_folder: string): string[] {\n return [];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n const env = { ...process.env, ...options.env, ...YARN_ENV };\n\n const cmd = args[0];\n let yarnArgs: string[];\n if (cmd === 'publish') {\n const filtered = args.slice(1).filter(\n (a) => a !== '--json' && !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'publish', ...filtered];\n } else if (cmd === 'info') {\n const filtered = args.slice(1).filter((a) => !a.startsWith('--registry'));\n yarnArgs = ['npm', 'info', ...filtered];\n } else {\n yarnArgs = args.filter((a) => !a.startsWith('--registry'));\n }\n\n return exec({ ...options, env }, bin, yarnArgs);\n },\n\n async prepareProject(\n packageName: string,\n version: string,\n registryUrl: string,\n _port: number,\n token: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n ): Promise<{ tempFolder: string }> {\n const tempFolder = await createTempFolder(packageName);\n const yamlContent = createYamlConfig(registryUrl, token);\n await writeFile(join(tempFolder, '.yarnrc.yml'), yamlContent);\n await writeFile(\n join(tempFolder, 'package.json'),\n getPackageJSON(packageName, version, dependencies, devDependencies)\n );\n await writeFile(join(tempFolder, 'README.md'), getREADME(packageName));\n return { tempFolder };\n },\n };\n\n return adapter;\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAM,WAAA,GAAA,MAAA,SAAmB,gCAAgC;AAEzD,IAAM,iCAAiC,IAAI,IAAI;CAAC;CAAW;CAAW;CAAO,CAAC;AAE9E,IAAM,WAAW;CACf,wBAAwB;CACxB,kBAAkB;CACnB;AAED,SAAS,cAAc,KAAqB;AAC1C,KAAI;AACF,UAAA,GAAA,cAAA,UAAgB,GAAG,IAAI,aAAa;GAClC,KAAK;IAAE,GAAG,QAAQ;IAAK,GAAG;IAAU;GACpC,UAAU;GACV,SAAS;GACV,CAAC,CAAC,MAAM;SACH;AACN,SAAO;;;AAIX,SAAS,kBAAkB,UAAU,KAAa;CAChD,MAAM,MAAM,qBAAqB;AACjC,SAAM,+BAA+B,IAAI;CACzC,MAAM,UAAA,GAAA,cAAA,UAAkB,aAAa,EAAE,UAAU,QAAQ,CAAC,CAAC,MAAM;AACjE,EAAA,GAAA,cAAA,UAAS,yBAAyB,OAAO,IAAI,IAAI,oBAAoB;EACnE,UAAU;EACV,SAAS;EACV,CAAC;CACF,MAAM,MAAM,GAAG,OAAO;CACtB,MAAM,YAAY,cAAc,IAAI;AACpC,SAAM,kCAAkC,WAAW,IAAI;AACvD,SAAQ,IAAI,gCAAgC,YAAY;AACxD,QAAO;;AAGT,SAAS,eAAe,SAAkB,SAA0B;AAClE,KAAI,QAAS,QAAO;AAEpB,KAAI,QACF,QAAO,kBAAkB,QAAQ;AAGnC,KAAI;EACF,MAAM,cAAA,GAAA,cAAA,UAAsB,cAAc;GAAE,UAAU;GAAQ,SAAS;GAAM,CAAC,CAAC,MAAM;EACrF,MAAM,aAAa,cAAc,WAAW;AAE5C,MADc,SAAS,WAAW,MAAM,IAAI,CAAC,IAAI,GAAG,IACvC,GAAG;AACd,WAAM,8BAA8B,WAAW;AAC/C,UAAO;;AAET,UAAM,oDAAoD,WAAW;SAC/D;AACN,UAAM,8CAA8C;;AAGtD,QAAO,mBAAmB;;AAG5B,SAAS,iBAAiB,UAAkB,OAAgB;CAC1D,MAAM,cAAmB;EACvB,mBAAmB;EACnB,yBAAyB;EACzB,qBAAqB,CAAC,YAAY;EACnC;AAED,KAAI,OAAO,UAAU,UAAU;EAC7B,MAAM,QAAM,IAAI,IAAA,IAAI,SAAS;AAC7B,cAAY,gBAAgB,GACzB,KAAK,MAAI,SAAS,GAAG,MAAI,SAAS;GACjC,eAAe;GACf,cAAc;GACf,EACF;;AAGH,QAAO,QAAA,QAAK,KAAK,YAAY;;AAG/B,SAAgB,wBAAwB,SAAkB,SAAyC;CACjG,MAAM,MAAM,eAAe,SAAS,QAAQ;CAC5C,MAAM,WAAW,cAAc,IAAI;AACnC,SAAM,kDAAkD,KAAK,SAAS;AAyDtE,QAvDuC;EACrC,MAAM,eAAe;EACrB,MAAM;EACN;EACA,UAAU;EAEV,YAAY,MAAwB;AAClC,UAAO,EAAE;;EAGX,UAAU,SAA2B;AACnC,UAAO,EAAE;;EAGX,KAAK,SAAuB,GAAG,MAAqC;GAClE,MAAM,MAAM;IAAE,GAAG,QAAQ;IAAK,GAAG,QAAQ;IAAK,GAAG;IAAU;GAE3D,MAAM,MAAM,KAAK;GACjB,IAAI;AACJ,OAAI,QAAQ,UAIV,YAAW;IAAC;IAAO;IAAW,GAHb,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,MAAM,YAAY,CAAC,EAAE,WAAW,aAAa,CACrD;IACyC;YACjC,QAAQ,OAEjB,YAAW;IAAC;IAAO;IAAQ,GADV,KAAK,MAAM,EAAE,CAAC,QAAQ,MAAM,CAAC,EAAE,WAAW,aAAa,CAAC;IAClC;OAEvC,YAAW,KAAK,QAAQ,MAAM,CAAC,EAAE,WAAW,aAAa,CAAC;AAG5D,UAAO,gBAAA,KAAK;IAAE,GAAG;IAAS;IAAK,EAAE,KAAK,SAAS;;EAGjD,MAAM,eACJ,aACA,SACA,aACA,OACA,OACA,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACX;GACjC,MAAM,aAAa,MAAM,gBAAA,iBAAiB,YAAY;GACtD,MAAM,cAAc,iBAAiB,aAAa,MAAM;AACxD,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MAAqB,YAAY,cAAc,EAAE,YAAY;AAC7D,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MACO,YAAY,eAAe,EAChC,gBAAA,eAAe,aAAa,SAAS,cAAc,gBAAgB,CACpE;AACD,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MAAqB,YAAY,YAAY,EAAE,gBAAA,UAAU,YAAY,CAAC;AACtE,UAAO,EAAE,YAAY;;EAExB"}
1
+ {"version":3,"file":"yarn-modern.cjs","names":[],"sources":["../../../src/adapters/yarn-modern.ts"],"sourcesContent":["import { SpawnOptions, execSync } from 'child_process';\nimport buildDebug from 'debug';\nimport { writeFile } from 'fs/promises';\nimport YAML from 'js-yaml';\nimport { join } from 'path';\nimport { URL } from 'url';\n\nimport { ExecOutput, PackageManagerAdapter } from '../types';\nimport { exec } from '../utils/process';\nimport { createTempFolder, getPackageJSON, getREADME } from '../utils/project';\n\nconst debug = buildDebug('verdaccio:e2e-cli:yarn-modern');\n\nconst YARN_MODERN_SUPPORTED_COMMANDS = new Set(['publish', 'install', 'info', 'ping', 'deprecate', 'login']);\n\nconst YARN_ENV = {\n COREPACK_ENABLE_STRICT: '0',\n YARN_IGNORE_PATH: '1',\n};\n\nfunction detectVersion(bin: string): string {\n try {\n return execSync(`${bin} --version`, {\n env: { ...process.env, ...YARN_ENV },\n encoding: 'utf8',\n timeout: 5000,\n }).trim();\n } catch {\n return 'unknown';\n }\n}\n\nfunction installYarnModern(version = '4'): string {\n const pkg = `@yarnpkg/cli-dist@${version}`;\n debug('installing %s into temp dir', pkg);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n execSync(`npm install --prefix \"${tmpDir}\" ${pkg} --loglevel=error`, {\n encoding: 'utf8',\n timeout: 30000,\n });\n const bin = `${tmpDir}/node_modules/@yarnpkg/cli-dist/bin/yarn.js`;\n const installed = detectVersion(bin);\n debug('installed yarn modern %s at %s', installed, bin);\n console.log(` Auto-installed yarn modern ${installed}`);\n return bin;\n}\n\nfunction resolveYarnBin(binPath?: string, version?: string): string {\n if (binPath) return binPath;\n\n if (version) {\n return installYarnModern(version);\n }\n\n try {\n const systemYarn = execSync('which yarn', { encoding: 'utf8', timeout: 5000 }).trim();\n const sysVersion = detectVersion(systemYarn);\n const major = parseInt(sysVersion.split('.')[0], 10);\n if (major >= 2) {\n debug('using system yarn Berry %s', sysVersion);\n return systemYarn;\n }\n debug('system yarn is Classic %s, auto-installing Berry', sysVersion);\n } catch {\n debug('no system yarn found, auto-installing Berry');\n }\n\n return installYarnModern();\n}\n\nfunction createYamlConfig(registry: string, token?: string) {\n const defaultYaml: any = {\n npmRegistryServer: registry,\n enableImmutableInstalls: false,\n unsafeHttpWhitelist: ['localhost'],\n };\n\n if (typeof token === 'string') {\n const url = new URL(registry);\n defaultYaml.npmRegistries = {\n [registry]: {\n npmAlwaysAuth: true,\n npmAuthToken: token,\n },\n };\n }\n\n return YAML.dump(defaultYaml);\n}\n\nexport function createYarnModernAdapter(binPath?: string, version?: string): PackageManagerAdapter {\n const bin = resolveYarnBin(binPath, version);\n const resolved = detectVersion(bin);\n debug('creating yarn modern adapter with bin: %s (%s)', bin, resolved);\n\n const adapter: PackageManagerAdapter = {\n name: `yarn-modern@${resolved}`,\n type: 'yarn-modern',\n bin,\n supports: YARN_MODERN_SUPPORTED_COMMANDS,\n\n registryArg(_url: string): string[] {\n return [];\n },\n\n prefixArg(_folder: string): string[] {\n return [];\n },\n\n exec(options: SpawnOptions, ...args: string[]): Promise<ExecOutput> {\n const env = { ...process.env, ...options.env, ...YARN_ENV };\n\n const cmd = args[0];\n let yarnArgs: string[];\n if (cmd === 'publish') {\n const filtered = args.slice(1).filter(\n (a) => a !== '--json' && !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'publish', ...filtered];\n } else if (cmd === 'info') {\n const filtered = args.slice(1).filter((a) => !a.startsWith('--registry'));\n yarnArgs = ['npm', 'info', ...filtered];\n } else if (cmd === 'ping') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'ping', ...filtered];\n } else if (cmd === 'deprecate') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'deprecate', ...filtered];\n } else if (cmd === 'login') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'login', ...filtered];\n } else if (cmd === 'whoami') {\n const filtered = args.slice(1).filter(\n (a) => !a.startsWith('--registry')\n );\n yarnArgs = ['npm', 'whoami', ...filtered];\n } else {\n yarnArgs = args.filter((a) => !a.startsWith('--registry'));\n }\n\n return exec({ ...options, env }, bin, yarnArgs);\n },\n\n async prepareProject(\n packageName: string,\n version: string,\n registryUrl: string,\n _port: number,\n token: string,\n dependencies: Record<string, string> = {},\n devDependencies: Record<string, string> = {}\n ): Promise<{ tempFolder: string }> {\n const tempFolder = await createTempFolder(packageName);\n const yamlContent = createYamlConfig(registryUrl, token);\n await writeFile(join(tempFolder, '.yarnrc.yml'), yamlContent);\n await writeFile(\n join(tempFolder, 'package.json'),\n getPackageJSON(packageName, version, dependencies, devDependencies)\n );\n await writeFile(join(tempFolder, 'README.md'), getREADME(packageName));\n return { tempFolder };\n },\n\n async importPlugin(cwd: string, pluginName: string): Promise<void> {\n debug('downloading %s plugin bundle', pluginName);\n const tmpDir = execSync('mktemp -d', { encoding: 'utf8' }).trim();\n const pkg = `@verdaccio/yarn-plugin-${pluginName}`;\n execSync(`npm pack ${pkg} --pack-destination \"${tmpDir}\"`, {\n encoding: 'utf8',\n timeout: 30000,\n stdio: 'pipe',\n });\n execSync(`tar xzf \"${tmpDir}\"/*.tgz -C \"${tmpDir}\"`, {\n encoding: 'utf8',\n stdio: 'pipe',\n });\n const bundlePath = join(tmpDir, `package/bundles/@yarnpkg/plugin-${pluginName}.js`);\n debug('importing plugin from %s into %s', bundlePath, cwd);\n await exec({ cwd, env: { ...process.env, ...YARN_ENV } }, bin, [\n 'plugin',\n 'import',\n bundlePath,\n ]);\n },\n };\n\n return adapter;\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAM,WAAA,GAAA,MAAA,SAAmB,gCAAgC;AAEzD,IAAM,iCAAiC,IAAI,IAAI;CAAC;CAAW;CAAW;CAAQ;CAAQ;CAAa;CAAQ,CAAC;AAE5G,IAAM,WAAW;CACf,wBAAwB;CACxB,kBAAkB;CACnB;AAED,SAAS,cAAc,KAAqB;AAC1C,KAAI;AACF,UAAA,GAAA,cAAA,UAAgB,GAAG,IAAI,aAAa;GAClC,KAAK;IAAE,GAAG,QAAQ;IAAK,GAAG;IAAU;GACpC,UAAU;GACV,SAAS;GACV,CAAC,CAAC,MAAM;SACH;AACN,SAAO;;;AAIX,SAAS,kBAAkB,UAAU,KAAa;CAChD,MAAM,MAAM,qBAAqB;AACjC,SAAM,+BAA+B,IAAI;CACzC,MAAM,UAAA,GAAA,cAAA,UAAkB,aAAa,EAAE,UAAU,QAAQ,CAAC,CAAC,MAAM;AACjE,EAAA,GAAA,cAAA,UAAS,yBAAyB,OAAO,IAAI,IAAI,oBAAoB;EACnE,UAAU;EACV,SAAS;EACV,CAAC;CACF,MAAM,MAAM,GAAG,OAAO;CACtB,MAAM,YAAY,cAAc,IAAI;AACpC,SAAM,kCAAkC,WAAW,IAAI;AACvD,SAAQ,IAAI,gCAAgC,YAAY;AACxD,QAAO;;AAGT,SAAS,eAAe,SAAkB,SAA0B;AAClE,KAAI,QAAS,QAAO;AAEpB,KAAI,QACF,QAAO,kBAAkB,QAAQ;AAGnC,KAAI;EACF,MAAM,cAAA,GAAA,cAAA,UAAsB,cAAc;GAAE,UAAU;GAAQ,SAAS;GAAM,CAAC,CAAC,MAAM;EACrF,MAAM,aAAa,cAAc,WAAW;AAE5C,MADc,SAAS,WAAW,MAAM,IAAI,CAAC,IAAI,GAAG,IACvC,GAAG;AACd,WAAM,8BAA8B,WAAW;AAC/C,UAAO;;AAET,UAAM,oDAAoD,WAAW;SAC/D;AACN,UAAM,8CAA8C;;AAGtD,QAAO,mBAAmB;;AAG5B,SAAS,iBAAiB,UAAkB,OAAgB;CAC1D,MAAM,cAAmB;EACvB,mBAAmB;EACnB,yBAAyB;EACzB,qBAAqB,CAAC,YAAY;EACnC;AAED,KAAI,OAAO,UAAU,UAAU;AACjB,MAAI,IAAA,IAAI,SAAS;AAC7B,cAAY,gBAAgB,GACzB,WAAW;GACV,eAAe;GACf,cAAc;GACf,EACF;;AAGH,QAAO,QAAA,QAAK,KAAK,YAAY;;AAG/B,SAAgB,wBAAwB,SAAkB,SAAyC;CACjG,MAAM,MAAM,eAAe,SAAS,QAAQ;CAC5C,MAAM,WAAW,cAAc,IAAI;AACnC,SAAM,kDAAkD,KAAK,SAAS;AAmGtE,QAjGuC;EACrC,MAAM,eAAe;EACrB,MAAM;EACN;EACA,UAAU;EAEV,YAAY,MAAwB;AAClC,UAAO,EAAE;;EAGX,UAAU,SAA2B;AACnC,UAAO,EAAE;;EAGX,KAAK,SAAuB,GAAG,MAAqC;GAClE,MAAM,MAAM;IAAE,GAAG,QAAQ;IAAK,GAAG,QAAQ;IAAK,GAAG;IAAU;GAE3D,MAAM,MAAM,KAAK;GACjB,IAAI;AACJ,OAAI,QAAQ,UAIV,YAAW;IAAC;IAAO;IAAW,GAHb,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,MAAM,YAAY,CAAC,EAAE,WAAW,aAAa,CACrD;IACyC;YACjC,QAAQ,OAEjB,YAAW;IAAC;IAAO;IAAQ,GADV,KAAK,MAAM,EAAE,CAAC,QAAQ,MAAM,CAAC,EAAE,WAAW,aAAa,CAAC;IAClC;YAC9B,QAAQ,OAIjB,YAAW;IAAC;IAAO;IAAQ,GAHV,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IACsC;YAC9B,QAAQ,YAIjB,YAAW;IAAC;IAAO;IAAa,GAHf,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IAC2C;YACnC,QAAQ,QAIjB,YAAW;IAAC;IAAO;IAAS,GAHX,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IACuC;YAC/B,QAAQ,SAIjB,YAAW;IAAC;IAAO;IAAU,GAHZ,KAAK,MAAM,EAAE,CAAC,QAC5B,MAAM,CAAC,EAAE,WAAW,aAAa,CACnC;IACwC;OAEzC,YAAW,KAAK,QAAQ,MAAM,CAAC,EAAE,WAAW,aAAa,CAAC;AAG5D,UAAO,gBAAA,KAAK;IAAE,GAAG;IAAS;IAAK,EAAE,KAAK,SAAS;;EAGjD,MAAM,eACJ,aACA,SACA,aACA,OACA,OACA,eAAuC,EAAE,EACzC,kBAA0C,EAAE,EACX;GACjC,MAAM,aAAa,MAAM,gBAAA,iBAAiB,YAAY;GACtD,MAAM,cAAc,iBAAiB,aAAa,MAAM;AACxD,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MAAqB,YAAY,cAAc,EAAE,YAAY;AAC7D,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MACO,YAAY,eAAe,EAChC,gBAAA,eAAe,aAAa,SAAS,cAAc,gBAAgB,CACpE;AACD,UAAA,GAAA,YAAA,YAAA,GAAA,KAAA,MAAqB,YAAY,YAAY,EAAE,gBAAA,UAAU,YAAY,CAAC;AACtE,UAAO,EAAE,YAAY;;EAGvB,MAAM,aAAa,KAAa,YAAmC;AACjE,WAAM,gCAAgC,WAAW;GACjD,MAAM,UAAA,GAAA,cAAA,UAAkB,aAAa,EAAE,UAAU,QAAQ,CAAC,CAAC,MAAM;AAEjE,IAAA,GAAA,cAAA,UAAS,YADG,0BAA0B,aACb,uBAAuB,OAAO,IAAI;IACzD,UAAU;IACV,SAAS;IACT,OAAO;IACR,CAAC;AACF,IAAA,GAAA,cAAA,UAAS,YAAY,OAAO,cAAc,OAAO,IAAI;IACnD,UAAU;IACV,OAAO;IACR,CAAC;GACF,MAAM,cAAA,GAAA,KAAA,MAAkB,QAAQ,mCAAmC,WAAW,KAAK;AACnF,WAAM,oCAAoC,YAAY,IAAI;AAC1D,SAAM,gBAAA,KAAK;IAAE;IAAK,KAAK;KAAE,GAAG,QAAQ;KAAK,GAAG;KAAU;IAAE,EAAE,KAAK;IAC7D;IACA;IACA;IACD,CAAC;;EAEL"}
@@ -1,3 +1,5 @@
1
+ require("./_virtual/_rolldown/runtime.cjs");
2
+ let fs = require("fs");
1
3
  //#region src/reporter.ts
2
4
  var COLORS = {
3
5
  reset: "\x1B[0m",
@@ -13,21 +15,31 @@ function formatDuration(ms) {
13
15
  return `${(ms / 1e3).toFixed(1)}s`;
14
16
  }
15
17
  function reportTestStart(adapterName, testName) {
16
- process.stdout.write(` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}...`);
18
+ process.stdout.write(` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}...\n`);
17
19
  }
18
- function reportTestResult(result) {
19
- if (result.passed) process.stdout.write(`\r ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\n`);
20
+ function reportTestResult(result, hasSubTests = false) {
21
+ if (result.passed) if (!hasSubTests) process.stdout.write(` ${COLORS.green}✓${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\n`);
22
+ else process.stdout.write(` ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\n`);
20
23
  else {
21
- process.stdout.write(`\r ${COLORS.red}FAIL${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\n`);
24
+ process.stdout.write(` ${COLORS.red}FAIL${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\n`);
22
25
  if (result.error) {
23
26
  const lines = result.error.split("\n");
24
27
  for (const line of lines) console.log(` ${COLORS.red}${line}${COLORS.reset}`);
28
+ if (process.env.GITHUB_ACTIONS) {
29
+ const msg = result.error.split("\n")[0];
30
+ console.log(`::error title=E2E ${result.name}::${msg}`);
31
+ }
25
32
  }
26
33
  }
27
34
  }
28
35
  function reportSuiteStart(adapterName) {
29
36
  console.log(`\n${COLORS.bold}${COLORS.cyan}${adapterName}${COLORS.reset}`);
30
37
  }
38
+ function reportSubTestResult(label, passed, duration) {
39
+ const icon = passed ? `${COLORS.bold}${COLORS.green}✓${COLORS.reset}` : `${COLORS.bold}${COLORS.red}✗${COLORS.reset}`;
40
+ const dur = duration !== void 0 ? ` ${COLORS.dim}${formatDuration(duration)}${COLORS.reset}` : "";
41
+ process.stdout.write(`\n ${icon} ${COLORS.bold}${label}${COLORS.reset}${dur}\n\n`);
42
+ }
31
43
  function reportSkipped(testName) {
32
44
  console.log(` ${COLORS.yellow}SKIP${COLORS.reset} ${testName}`);
33
45
  }
@@ -49,9 +61,50 @@ function reportSummary(results) {
49
61
  }
50
62
  console.log(`\n Total: ${COLORS.green}${totalPassed} passed${COLORS.reset}, ${COLORS.red}${totalFailed} failed${COLORS.reset}, ${COLORS.yellow}${totalSkipped} skipped${COLORS.reset} ${COLORS.dim}(${formatDuration(totalDuration)})${COLORS.reset}`);
51
63
  console.log(`${COLORS.bold}${"=".repeat(50)}${COLORS.reset}\n`);
64
+ const summaryFile = process.env.GITHUB_STEP_SUMMARY;
65
+ if (summaryFile) writeGitHubSummary(summaryFile, results);
66
+ }
67
+ function writeGitHubSummary(summaryFile, results) {
68
+ const lines = [];
69
+ lines.push("## E2E Test Results\n");
70
+ for (const suite of results) {
71
+ const status = suite.failed > 0 ? "❌" : "✅";
72
+ lines.push(`### ${status} ${suite.adapter}\n`);
73
+ lines.push("| Test | Status | Duration |");
74
+ lines.push("|------|--------|----------|");
75
+ for (const test of suite.tests) {
76
+ const icon = test.passed ? "✅" : "❌";
77
+ const dur = formatDuration(test.duration);
78
+ if (test.subTests && test.subTests.length > 0) {
79
+ lines.push(`| **${test.name}** | ${icon} | ${dur} |`);
80
+ for (const sub of test.subTests) {
81
+ const subIcon = sub.passed ? "✅" : "❌";
82
+ const subDur = formatDuration(sub.duration);
83
+ const label = sub.passed ? sub.label : `${sub.label}: ${sub.error?.split("\n")[0] ?? ""}`;
84
+ lines.push(`| &nbsp;&nbsp;&nbsp;&nbsp;${label} | ${subIcon} | ${subDur} |`);
85
+ }
86
+ } else {
87
+ const label = test.passed ? test.name : `${test.name}: ${test.error?.split("\n")[0] ?? ""}`;
88
+ lines.push(`| ${label} | ${icon} | ${dur} |`);
89
+ }
90
+ }
91
+ lines.push("");
92
+ }
93
+ let totalPassed = 0;
94
+ let totalFailed = 0;
95
+ let totalSkipped = 0;
96
+ for (const suite of results) {
97
+ totalPassed += suite.passed;
98
+ totalFailed += suite.failed;
99
+ totalSkipped += suite.skipped;
100
+ }
101
+ const emoji = totalFailed > 0 ? "❌" : "✅";
102
+ lines.push(`${emoji} **${totalPassed} passed**, **${totalFailed} failed**, **${totalSkipped} skipped**\n`);
103
+ (0, fs.appendFileSync)(summaryFile, lines.join("\n"));
52
104
  }
53
105
  //#endregion
54
106
  exports.reportSkipped = reportSkipped;
107
+ exports.reportSubTestResult = reportSubTestResult;
55
108
  exports.reportSuiteStart = reportSuiteStart;
56
109
  exports.reportSummary = reportSummary;
57
110
  exports.reportTestResult = reportTestResult;
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.cjs","names":[],"sources":["../../src/reporter.ts"],"sourcesContent":["import { SuiteResult, TestResult } from './types';\n\nconst COLORS = {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n};\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nexport function reportTestStart(adapterName: string, testName: string): void {\n process.stdout.write(\n ` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}...`\n );\n}\n\nexport function reportTestResult(result: TestResult): void {\n if (result.passed) {\n process.stdout.write(\n `\\r ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\\n`\n );\n } else {\n process.stdout.write(\n `\\r ${COLORS.red}FAIL${COLORS.reset} ${result.name} ${COLORS.dim}(${formatDuration(result.duration)})${COLORS.reset}\\n`\n );\n if (result.error) {\n const lines = result.error.split('\\n');\n for (const line of lines) {\n console.log(` ${COLORS.red}${line}${COLORS.reset}`);\n }\n }\n }\n}\n\nexport function reportSuiteStart(adapterName: string): void {\n console.log(`\\n${COLORS.bold}${COLORS.cyan}${adapterName}${COLORS.reset}`);\n}\n\nexport function reportSkipped(testName: string): void {\n console.log(` ${COLORS.yellow}SKIP${COLORS.reset} ${testName}`);\n}\n\nexport function reportSummary(results: SuiteResult[]): void {\n console.log(`\\n${COLORS.bold}${'='.repeat(50)}${COLORS.reset}`);\n console.log(`${COLORS.bold}Summary${COLORS.reset}\\n`);\n\n let totalPassed = 0;\n let totalFailed = 0;\n let totalSkipped = 0;\n let totalDuration = 0;\n\n for (const suite of results) {\n const status = suite.failed > 0 ? COLORS.red : COLORS.green;\n const icon = suite.failed > 0 ? 'x' : 'v';\n console.log(\n ` ${status}${icon}${COLORS.reset} ${suite.adapter}: ` +\n `${COLORS.green}${suite.passed} passed${COLORS.reset}, ` +\n `${COLORS.red}${suite.failed} failed${COLORS.reset}, ` +\n `${COLORS.yellow}${suite.skipped} skipped${COLORS.reset} ` +\n `${COLORS.dim}(${formatDuration(suite.duration)})${COLORS.reset}`\n );\n totalPassed += suite.passed;\n totalFailed += suite.failed;\n totalSkipped += suite.skipped;\n totalDuration += suite.duration;\n }\n\n console.log(`\\n Total: ${COLORS.green}${totalPassed} passed${COLORS.reset}, ` +\n `${COLORS.red}${totalFailed} failed${COLORS.reset}, ` +\n `${COLORS.yellow}${totalSkipped} skipped${COLORS.reset} ` +\n `${COLORS.dim}(${formatDuration(totalDuration)})${COLORS.reset}`);\n console.log(`${COLORS.bold}${'='.repeat(50)}${COLORS.reset}\\n`);\n}\n"],"mappings":";AAEA,IAAM,SAAS;CACb,OAAO;CACP,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,KAAK;CACL,MAAM;CACP;AAED,SAAS,eAAe,IAAoB;AAC1C,KAAI,KAAK,IAAM,QAAO,GAAG,GAAG;AAC5B,QAAO,IAAI,KAAK,KAAM,QAAQ,EAAE,CAAC;;AAGnC,SAAgB,gBAAgB,aAAqB,UAAwB;AAC3E,SAAQ,OAAO,MACb,KAAK,OAAO,IAAI,SAAS,OAAO,MAAM,GAAG,YAAY,KAAK,SAAS,KACpE;;AAGH,SAAgB,iBAAiB,QAA0B;AACzD,KAAI,OAAO,OACT,SAAQ,OAAO,MACb,OAAO,OAAO,MAAM,MAAM,OAAO,MAAM,GAAG,OAAO,KAAK,GAAG,OAAO,IAAI,GAAG,eAAe,OAAO,SAAS,CAAC,GAAG,OAAO,MAAM,IACxH;MACI;AACL,UAAQ,OAAO,MACb,OAAO,OAAO,IAAI,MAAM,OAAO,MAAM,GAAG,OAAO,KAAK,GAAG,OAAO,IAAI,GAAG,eAAe,OAAO,SAAS,CAAC,GAAG,OAAO,MAAM,IACtH;AACD,MAAI,OAAO,OAAO;GAChB,MAAM,QAAQ,OAAO,MAAM,MAAM,KAAK;AACtC,QAAK,MAAM,QAAQ,MACjB,SAAQ,IAAI,OAAO,OAAO,MAAM,OAAO,OAAO,QAAQ;;;;AAM9D,SAAgB,iBAAiB,aAA2B;AAC1D,SAAQ,IAAI,KAAK,OAAO,OAAO,OAAO,OAAO,cAAc,OAAO,QAAQ;;AAG5E,SAAgB,cAAc,UAAwB;AACpD,SAAQ,IAAI,KAAK,OAAO,OAAO,MAAM,OAAO,MAAM,GAAG,WAAW;;AAGlE,SAAgB,cAAc,SAA8B;AAC1D,SAAQ,IAAI,KAAK,OAAO,OAAO,IAAI,OAAO,GAAG,GAAG,OAAO,QAAQ;AAC/D,SAAQ,IAAI,GAAG,OAAO,KAAK,SAAS,OAAO,MAAM,IAAI;CAErD,IAAI,cAAc;CAClB,IAAI,cAAc;CAClB,IAAI,eAAe;CACnB,IAAI,gBAAgB;AAEpB,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,SAAS,MAAM,SAAS,IAAI,OAAO,MAAM,OAAO;EACtD,MAAM,OAAO,MAAM,SAAS,IAAI,MAAM;AACtC,UAAQ,IACN,KAAK,SAAS,OAAO,OAAO,MAAM,GAAG,MAAM,QAAQ,IAC9C,OAAO,QAAQ,MAAM,OAAO,SAAS,OAAO,MAAM,IAClD,OAAO,MAAM,MAAM,OAAO,SAAS,OAAO,MAAM,IAChD,OAAO,SAAS,MAAM,QAAQ,UAAU,OAAO,MAAM,GACrD,OAAO,IAAI,GAAG,eAAe,MAAM,SAAS,CAAC,GAAG,OAAO,QAC7D;AACD,iBAAe,MAAM;AACrB,iBAAe,MAAM;AACrB,kBAAgB,MAAM;AACtB,mBAAiB,MAAM;;AAGzB,SAAQ,IAAI,cAAc,OAAO,QAAQ,YAAY,SAAS,OAAO,MAAM,IACtE,OAAO,MAAM,YAAY,SAAS,OAAO,MAAM,IAC/C,OAAO,SAAS,aAAa,UAAU,OAAO,MAAM,GACpD,OAAO,IAAI,GAAG,eAAe,cAAc,CAAC,GAAG,OAAO,QAAQ;AACnE,SAAQ,IAAI,GAAG,OAAO,OAAO,IAAI,OAAO,GAAG,GAAG,OAAO,MAAM,IAAI"}
1
+ {"version":3,"file":"reporter.cjs","names":[],"sources":["../../src/reporter.ts"],"sourcesContent":["import { appendFileSync } from 'fs';\n\nimport { SuiteResult, TestResult } from './types';\n\nconst COLORS = {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n cyan: '\\x1b[36m',\n dim: '\\x1b[2m',\n bold: '\\x1b[1m',\n};\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nexport function reportTestStart(adapterName: string, testName: string): void {\n process.stdout.write(\n ` ${COLORS.dim}running${COLORS.reset} ${adapterName} > ${testName}...\\n`\n );\n}\n\nexport function reportTestResult(result: TestResult, hasSubTests = false): void {\n if (result.passed) {\n if (!hasSubTests) {\n process.stdout.write(\n ` ${COLORS.green}✓${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\\n`\n );\n } else {\n process.stdout.write(\n ` ${COLORS.green}PASS${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\\n`\n );\n }\n } else {\n process.stdout.write(\n ` ${COLORS.red}FAIL${COLORS.reset} ${result.name} ${COLORS.dim}${formatDuration(result.duration)}${COLORS.reset}\\n`\n );\n if (result.error) {\n const lines = result.error.split('\\n');\n for (const line of lines) {\n console.log(` ${COLORS.red}${line}${COLORS.reset}`);\n }\n // GitHub Actions annotation\n if (process.env.GITHUB_ACTIONS) {\n const msg = result.error.split('\\n')[0];\n console.log(`::error title=E2E ${result.name}::${msg}`);\n }\n }\n }\n}\n\nexport function reportSuiteStart(adapterName: string): void {\n console.log(`\\n${COLORS.bold}${COLORS.cyan}${adapterName}${COLORS.reset}`);\n}\n\nexport function reportSubTestResult(label: string, passed: boolean, duration?: number): void {\n const icon = passed\n ? `${COLORS.bold}${COLORS.green}✓${COLORS.reset}`\n : `${COLORS.bold}${COLORS.red}✗${COLORS.reset}`;\n const dur = duration !== undefined ? ` ${COLORS.dim}${formatDuration(duration)}${COLORS.reset}` : '';\n process.stdout.write(`\\n ${icon} ${COLORS.bold}${label}${COLORS.reset}${dur}\\n\\n`);\n}\n\nexport function reportSkipped(testName: string): void {\n console.log(` ${COLORS.yellow}SKIP${COLORS.reset} ${testName}`);\n}\n\nexport function reportSummary(results: SuiteResult[]): void {\n console.log(`\\n${COLORS.bold}${'='.repeat(50)}${COLORS.reset}`);\n console.log(`${COLORS.bold}Summary${COLORS.reset}\\n`);\n\n let totalPassed = 0;\n let totalFailed = 0;\n let totalSkipped = 0;\n let totalDuration = 0;\n\n for (const suite of results) {\n const status = suite.failed > 0 ? COLORS.red : COLORS.green;\n const icon = suite.failed > 0 ? 'x' : 'v';\n console.log(\n ` ${status}${icon}${COLORS.reset} ${suite.adapter}: ` +\n `${COLORS.green}${suite.passed} passed${COLORS.reset}, ` +\n `${COLORS.red}${suite.failed} failed${COLORS.reset}, ` +\n `${COLORS.yellow}${suite.skipped} skipped${COLORS.reset} ` +\n `${COLORS.dim}(${formatDuration(suite.duration)})${COLORS.reset}`\n );\n totalPassed += suite.passed;\n totalFailed += suite.failed;\n totalSkipped += suite.skipped;\n totalDuration += suite.duration;\n }\n\n console.log(`\\n Total: ${COLORS.green}${totalPassed} passed${COLORS.reset}, ` +\n `${COLORS.red}${totalFailed} failed${COLORS.reset}, ` +\n `${COLORS.yellow}${totalSkipped} skipped${COLORS.reset} ` +\n `${COLORS.dim}(${formatDuration(totalDuration)})${COLORS.reset}`);\n console.log(`${COLORS.bold}${'='.repeat(50)}${COLORS.reset}\\n`);\n\n // GitHub Actions Job Summary\n const summaryFile = process.env.GITHUB_STEP_SUMMARY;\n if (summaryFile) {\n writeGitHubSummary(summaryFile, results);\n }\n}\n\nfunction writeGitHubSummary(summaryFile: string, results: SuiteResult[]): void {\n const lines: string[] = [];\n\n lines.push('## E2E Test Results\\n');\n\n for (const suite of results) {\n const status = suite.failed > 0 ? '❌' : '✅';\n lines.push(`### ${status} ${suite.adapter}\\n`);\n lines.push('| Test | Status | Duration |');\n lines.push('|------|--------|----------|');\n\n for (const test of suite.tests) {\n const icon = test.passed ? '✅' : '❌';\n const dur = formatDuration(test.duration);\n\n if (test.subTests && test.subTests.length > 0) {\n // Parent row\n lines.push(`| **${test.name}** | ${icon} | ${dur} |`);\n // Sub-test rows\n for (const sub of test.subTests) {\n const subIcon = sub.passed ? '✅' : '❌';\n const subDur = formatDuration(sub.duration);\n const label = sub.passed ? sub.label : `${sub.label}: ${sub.error?.split('\\n')[0] ?? ''}`;\n lines.push(`| &nbsp;&nbsp;&nbsp;&nbsp;${label} | ${subIcon} | ${subDur} |`);\n }\n } else {\n const label = test.passed ? test.name : `${test.name}: ${test.error?.split('\\n')[0] ?? ''}`;\n lines.push(`| ${label} | ${icon} | ${dur} |`);\n }\n }\n\n lines.push('');\n }\n\n let totalPassed = 0;\n let totalFailed = 0;\n let totalSkipped = 0;\n for (const suite of results) {\n totalPassed += suite.passed;\n totalFailed += suite.failed;\n totalSkipped += suite.skipped;\n }\n\n const emoji = totalFailed > 0 ? '❌' : '✅';\n lines.push(`${emoji} **${totalPassed} passed**, **${totalFailed} failed**, **${totalSkipped} skipped**\\n`);\n\n appendFileSync(summaryFile, lines.join('\\n'));\n}\n"],"mappings":"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"}
@@ -14,13 +14,41 @@ function getPort(registryUrl) {
14
14
  }
15
15
  }
16
16
  async function runSingleTest(adapter, test, registryUrl, token, timeout) {
17
+ const port = getPort(registryUrl);
18
+ let hasSubTests = false;
19
+ const subResults = [];
17
20
  const ctx = {
18
21
  registryUrl,
19
22
  token,
20
- port: getPort(registryUrl),
23
+ port,
21
24
  exec: adapter.exec.bind(adapter),
22
25
  adapter,
23
- runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`
26
+ runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,
27
+ async subTest(label, fn) {
28
+ hasSubTests = true;
29
+ const subStart = Date.now();
30
+ try {
31
+ await fn();
32
+ const duration = Date.now() - subStart;
33
+ subResults.push({
34
+ label,
35
+ passed: true,
36
+ duration
37
+ });
38
+ require_reporter.reportSubTestResult(label, true, duration);
39
+ } catch (err) {
40
+ const duration = Date.now() - subStart;
41
+ const error = err instanceof Error ? err.message : String(err);
42
+ subResults.push({
43
+ label,
44
+ passed: false,
45
+ duration,
46
+ error
47
+ });
48
+ require_reporter.reportSubTestResult(label, false, duration);
49
+ throw err;
50
+ }
51
+ }
24
52
  };
25
53
  const start = Date.now();
26
54
  return new Promise((resolve) => {
@@ -29,7 +57,9 @@ async function runSingleTest(adapter, test, registryUrl, token, timeout) {
29
57
  name: test.name,
30
58
  passed: false,
31
59
  duration: Date.now() - start,
32
- error: `Test timed out after ${timeout}ms`
60
+ error: `Test timed out after ${timeout}ms`,
61
+ hasSubTests,
62
+ subTests: subResults.length > 0 ? subResults : void 0
33
63
  });
34
64
  }, timeout);
35
65
  test.run(ctx).then(() => {
@@ -37,7 +67,9 @@ async function runSingleTest(adapter, test, registryUrl, token, timeout) {
37
67
  resolve({
38
68
  name: test.name,
39
69
  passed: true,
40
- duration: Date.now() - start
70
+ duration: Date.now() - start,
71
+ hasSubTests,
72
+ subTests: subResults.length > 0 ? subResults : void 0
41
73
  });
42
74
  }).catch((err) => {
43
75
  clearTimeout(timer);
@@ -45,7 +77,9 @@ async function runSingleTest(adapter, test, registryUrl, token, timeout) {
45
77
  name: test.name,
46
78
  passed: false,
47
79
  duration: Date.now() - start,
48
- error: err instanceof Error ? err.message : String(err)
80
+ error: err instanceof Error ? err.message : String(err),
81
+ hasSubTests,
82
+ subTests: subResults.length > 0 ? subResults : void 0
49
83
  });
50
84
  });
51
85
  });
@@ -69,7 +103,7 @@ async function runSuite(adapter, tests, registryUrl, token, options) {
69
103
  require_reporter.reportTestStart(adapter.name, test.name);
70
104
  const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);
71
105
  results.push(result);
72
- require_reporter.reportTestResult(result);
106
+ require_reporter.reportTestResult(result, result.hasSubTests);
73
107
  }
74
108
  const passed = results.filter((r) => r.passed).length;
75
109
  const failed = results.filter((r) => !r.passed).length;
@@ -1 +1 @@
1
- {"version":3,"file":"runner.cjs","names":[],"sources":["../../src/runner.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { URL } from 'url';\n\nimport { PackageManagerAdapter, SuiteResult, TestContext, TestDefinition, TestResult } from './types';\nimport { reportSkipped, reportSuiteStart, reportSummary, reportTestResult, reportTestStart } from './reporter';\n\nconst debug = buildDebug('verdaccio:e2e-cli:runner');\n\nfunction getPort(registryUrl: string): number {\n try {\n const url = new URL(registryUrl);\n return parseInt(url.port, 10) || (url.protocol === 'https:' ? 443 : 80);\n } catch {\n return 4873;\n }\n}\n\nasync function runSingleTest(\n adapter: PackageManagerAdapter,\n test: TestDefinition,\n registryUrl: string,\n token: string,\n timeout: number\n): Promise<TestResult> {\n const port = getPort(registryUrl);\n const ctx: TestContext = {\n registryUrl,\n token,\n port,\n exec: adapter.exec.bind(adapter),\n adapter,\n runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,\n };\n\n const start = Date.now();\n\n return new Promise<TestResult>((resolve) => {\n const timer = setTimeout(() => {\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: `Test timed out after ${timeout}ms`,\n });\n }, timeout);\n\n test\n .run(ctx)\n .then(() => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: true,\n duration: Date.now() - start,\n });\n })\n .catch((err) => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n });\n });\n });\n}\n\nexport async function runSuite(\n adapter: PackageManagerAdapter,\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; testFilter?: string[] }\n): Promise<SuiteResult> {\n const suiteStart = Date.now();\n const results: TestResult[] = [];\n let skipped = 0;\n\n reportSuiteStart(adapter.name);\n\n for (const test of tests) {\n // Filter by test name if specified\n if (options.testFilter && options.testFilter.length > 0) {\n if (!options.testFilter.includes(test.name)) {\n continue;\n }\n }\n\n // Check if adapter supports required commands\n if (test.requires) {\n const unsupported = test.requires.filter((cmd) => !adapter.supports.has(cmd));\n if (unsupported.length > 0) {\n reportSkipped(test.name);\n skipped++;\n continue;\n }\n }\n\n reportTestStart(adapter.name, test.name);\n const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);\n results.push(result);\n reportTestResult(result);\n }\n\n const passed = results.filter((r) => r.passed).length;\n const failed = results.filter((r) => !r.passed).length;\n\n return {\n adapter: adapter.name,\n tests: results,\n passed,\n failed,\n skipped,\n duration: Date.now() - suiteStart,\n };\n}\n\nexport async function runAll(\n adapters: PackageManagerAdapter[],\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; concurrency: number; testFilter?: string[] }\n): Promise<{ results: SuiteResult[]; exitCode: number }> {\n debug('running %d adapters with %d tests', adapters.length, tests.length);\n const results: SuiteResult[] = [];\n\n // Run adapters sequentially (each suite is already complex enough)\n for (const adapter of adapters) {\n const result = await runSuite(adapter, tests, registryUrl, token, options);\n results.push(result);\n }\n\n reportSummary(results);\n\n const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);\n return { results, exitCode: totalFailed > 0 ? 1 : 0 };\n}\n"],"mappings":";;;;;;AAMA,IAAM,WAAA,GAAA,MAAA,SAAmB,2BAA2B;AAEpD,SAAS,QAAQ,aAA6B;AAC5C,KAAI;EACF,MAAM,QAAM,IAAI,IAAA,IAAI,YAAY;AAChC,SAAO,SAAS,MAAI,MAAM,GAAG,KAAK,MAAI,aAAa,WAAW,MAAM;SAC9D;AACN,SAAO;;;AAIX,eAAe,cACb,SACA,MACA,aACA,OACA,SACqB;CAErB,MAAM,MAAmB;EACvB;EACA;EACA,MAJW,QAAQ,YAAY;EAK/B,MAAM,QAAQ,KAAK,KAAK,QAAQ;EAChC;EACA,OAAO,GAAG,KAAK,KAAK,CAAC,SAAS,GAAG,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;EAC3E;CAED,MAAM,QAAQ,KAAK,KAAK;AAExB,QAAO,IAAI,SAAqB,YAAY;EAC1C,MAAM,QAAQ,iBAAiB;AAC7B,WAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,KAAK,GAAG;IACvB,OAAO,wBAAwB,QAAQ;IACxC,CAAC;KACD,QAAQ;AAEX,OACG,IAAI,IAAI,CACR,WAAW;AACV,gBAAa,MAAM;AACnB,WAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,KAAK,GAAG;IACxB,CAAC;IACF,CACD,OAAO,QAAQ;AACd,gBAAa,MAAM;AACnB,WAAQ;IACN,MAAM,KAAK;IACX,QAAQ;IACR,UAAU,KAAK,KAAK,GAAG;IACvB,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IACxD,CAAC;IACF;GACJ;;AAGJ,eAAsB,SACpB,SACA,OACA,aACA,OACA,SACsB;CACtB,MAAM,aAAa,KAAK,KAAK;CAC7B,MAAM,UAAwB,EAAE;CAChC,IAAI,UAAU;AAEd,kBAAA,iBAAiB,QAAQ,KAAK;AAE9B,MAAK,MAAM,QAAQ,OAAO;AAExB,MAAI,QAAQ,cAAc,QAAQ,WAAW,SAAS;OAChD,CAAC,QAAQ,WAAW,SAAS,KAAK,KAAK,CACzC;;AAKJ,MAAI,KAAK;OACa,KAAK,SAAS,QAAQ,QAAQ,CAAC,QAAQ,SAAS,IAAI,IAAI,CAAC,CAC7D,SAAS,GAAG;AAC1B,qBAAA,cAAc,KAAK,KAAK;AACxB;AACA;;;AAIJ,mBAAA,gBAAgB,QAAQ,MAAM,KAAK,KAAK;EACxC,MAAM,SAAS,MAAM,cAAc,SAAS,MAAM,aAAa,OAAO,QAAQ,QAAQ;AACtF,UAAQ,KAAK,OAAO;AACpB,mBAAA,iBAAiB,OAAO;;CAG1B,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,OAAO,CAAC;CAC/C,MAAM,SAAS,QAAQ,QAAQ,MAAM,CAAC,EAAE,OAAO,CAAC;AAEhD,QAAO;EACL,SAAS,QAAQ;EACjB,OAAO;EACP;EACA;EACA;EACA,UAAU,KAAK,KAAK,GAAG;EACxB;;AAGH,eAAsB,OACpB,UACA,OACA,aACA,OACA,SACuD;AACvD,SAAM,qCAAqC,SAAS,QAAQ,MAAM,OAAO;CACzE,MAAM,UAAyB,EAAE;AAGjC,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,SAAS,MAAM,SAAS,SAAS,OAAO,aAAa,OAAO,QAAQ;AAC1E,UAAQ,KAAK,OAAO;;AAGtB,kBAAA,cAAc,QAAQ;AAGtB,QAAO;EAAE;EAAS,UADE,QAAQ,QAAQ,KAAK,MAAM,MAAM,EAAE,QAAQ,EAAE,GACvB,IAAI,IAAI;EAAG"}
1
+ {"version":3,"file":"runner.cjs","names":[],"sources":["../../src/runner.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport { URL } from 'url';\n\nimport { PackageManagerAdapter, SubTestResult, SuiteResult, TestContext, TestDefinition, TestResult } from './types';\nimport { reportSkipped, reportSubTestResult, reportSuiteStart, reportSummary, reportTestResult, reportTestStart } from './reporter';\n\nconst debug = buildDebug('verdaccio:e2e-cli:runner');\n\nfunction getPort(registryUrl: string): number {\n try {\n const url = new URL(registryUrl);\n return parseInt(url.port, 10) || (url.protocol === 'https:' ? 443 : 80);\n } catch {\n return 4873;\n }\n}\n\nasync function runSingleTest(\n adapter: PackageManagerAdapter,\n test: TestDefinition,\n registryUrl: string,\n token: string,\n timeout: number\n): Promise<TestResult & { hasSubTests: boolean }> {\n const port = getPort(registryUrl);\n let hasSubTests = false;\n const subResults: SubTestResult[] = [];\n const ctx: TestContext = {\n registryUrl,\n token,\n port,\n exec: adapter.exec.bind(adapter),\n adapter,\n runId: `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,\n async subTest(label: string, fn: () => Promise<void>): Promise<void> {\n hasSubTests = true;\n const subStart = Date.now();\n try {\n await fn();\n const duration = Date.now() - subStart;\n subResults.push({ label, passed: true, duration });\n reportSubTestResult(label, true, duration);\n } catch (err) {\n const duration = Date.now() - subStart;\n const error = err instanceof Error ? err.message : String(err);\n subResults.push({ label, passed: false, duration, error });\n reportSubTestResult(label, false, duration);\n throw err;\n }\n },\n };\n\n const start = Date.now();\n\n return new Promise<TestResult & { hasSubTests: boolean }>((resolve) => {\n const timer = setTimeout(() => {\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: `Test timed out after ${timeout}ms`,\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n }, timeout);\n\n test\n .run(ctx)\n .then(() => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: true,\n duration: Date.now() - start,\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n })\n .catch((err) => {\n clearTimeout(timer);\n resolve({\n name: test.name,\n passed: false,\n duration: Date.now() - start,\n error: err instanceof Error ? err.message : String(err),\n hasSubTests,\n subTests: subResults.length > 0 ? subResults : undefined,\n });\n });\n });\n}\n\nexport async function runSuite(\n adapter: PackageManagerAdapter,\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; testFilter?: string[] }\n): Promise<SuiteResult> {\n const suiteStart = Date.now();\n const results: TestResult[] = [];\n let skipped = 0;\n\n reportSuiteStart(adapter.name);\n\n for (const test of tests) {\n // Filter by test name if specified\n if (options.testFilter && options.testFilter.length > 0) {\n if (!options.testFilter.includes(test.name)) {\n continue;\n }\n }\n\n // Check if adapter supports required commands\n if (test.requires) {\n const unsupported = test.requires.filter((cmd) => !adapter.supports.has(cmd));\n if (unsupported.length > 0) {\n reportSkipped(test.name);\n skipped++;\n continue;\n }\n }\n\n reportTestStart(adapter.name, test.name);\n const result = await runSingleTest(adapter, test, registryUrl, token, options.timeout);\n results.push(result);\n reportTestResult(result, result.hasSubTests);\n }\n\n const passed = results.filter((r) => r.passed).length;\n const failed = results.filter((r) => !r.passed).length;\n\n return {\n adapter: adapter.name,\n tests: results,\n passed,\n failed,\n skipped,\n duration: Date.now() - suiteStart,\n };\n}\n\nexport async function runAll(\n adapters: PackageManagerAdapter[],\n tests: TestDefinition[],\n registryUrl: string,\n token: string,\n options: { timeout: number; concurrency: number; testFilter?: string[] }\n): Promise<{ results: SuiteResult[]; exitCode: number }> {\n debug('running %d adapters with %d tests', adapters.length, tests.length);\n const results: SuiteResult[] = [];\n\n // Run adapters sequentially (each suite is already complex enough)\n for (const adapter of adapters) {\n const result = await runSuite(adapter, tests, registryUrl, token, options);\n results.push(result);\n }\n\n reportSummary(results);\n\n const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);\n return { results, exitCode: totalFailed > 0 ? 1 : 0 };\n}\n"],"mappings":"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"}
@@ -1,60 +1,100 @@
1
1
  const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ let debug = require("debug");
3
+ debug = require_runtime.__toESM(debug);
4
+ let path = require("path");
5
+ let fs_promises = require("fs/promises");
2
6
  let assert = require("assert");
3
7
  assert = require_runtime.__toESM(assert);
4
8
  //#region src/tests/deprecate.ts
9
+ var debug$1 = (0, debug.default)("verdaccio:e2e-cli:test:deprecate");
5
10
  async function publishPkg(ctx, tempFolder, pkgName) {
11
+ if (ctx.adapter.type === "yarn-modern") {
12
+ debug$1("running yarn install before publish for %s", pkgName);
13
+ await ctx.adapter.exec({ cwd: tempFolder }, "install");
14
+ }
15
+ debug$1("publishing %s from %s", pkgName, tempFolder);
6
16
  await ctx.adapter.exec({ cwd: tempFolder }, "publish", ...ctx.adapter.registryArg(ctx.registryUrl));
17
+ debug$1("published %s successfully", pkgName);
7
18
  }
8
19
  async function deprecate(ctx, tempFolder, packageVersion, message) {
9
- await ctx.adapter.exec({ cwd: tempFolder }, "deprecate", packageVersion, message, "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
20
+ debug$1("deprecating %s with message: %s", packageVersion, message || "(empty, un-deprecate)");
21
+ const jsonFlag = ctx.adapter.type === "yarn-modern" ? [] : ["--json"];
22
+ await ctx.adapter.exec({ cwd: tempFolder }, "deprecate", packageVersion, message, ...jsonFlag, ...ctx.adapter.registryArg(ctx.registryUrl));
23
+ debug$1("deprecate command completed for %s", packageVersion);
10
24
  }
11
- async function getInfo(ctx, pkgName) {
12
- const resp = await ctx.adapter.exec({}, "info", pkgName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
13
- return JSON.parse(resp.stdout);
25
+ async function getInfo(ctx, tempFolder, pkgName) {
26
+ debug$1("fetching info for %s", pkgName);
27
+ const resp = await ctx.adapter.exec({ cwd: tempFolder }, "info", pkgName, "--json", ...ctx.adapter.registryArg(ctx.registryUrl));
28
+ const parsed = JSON.parse(resp.stdout);
29
+ debug$1("info for %s: deprecated=%s", pkgName, parsed.deprecated ?? "(not set)");
30
+ return parsed;
14
31
  }
15
32
  async function bumpVersion(ctx, tempFolder) {
16
- await ctx.adapter.exec({ cwd: tempFolder }, "version", "minor", ...ctx.adapter.registryArg(ctx.registryUrl));
33
+ debug$1("bumping version (minor) in %s", tempFolder);
34
+ if (ctx.adapter.type === "yarn-modern") {
35
+ const pkgPath = (0, path.join)(tempFolder, "package.json");
36
+ const pkg = JSON.parse(await (0, fs_promises.readFile)(pkgPath, "utf8"));
37
+ const [major, minor, patch] = pkg.version.split(".").map(Number);
38
+ pkg.version = `${major}.${minor + 1}.${patch}`;
39
+ debug$1("bumped %s to %s", pkgPath, pkg.version);
40
+ await (0, fs_promises.writeFile)(pkgPath, JSON.stringify(pkg, null, 2));
41
+ } else await ctx.adapter.exec({ cwd: tempFolder }, "version", "minor", ...ctx.adapter.registryArg(ctx.registryUrl));
42
+ }
43
+ async function prepareDeprecateProject(ctx, pkgName, version) {
44
+ debug$1("preparing project for %s@%s", pkgName, version);
45
+ const { tempFolder } = await ctx.adapter.prepareProject(pkgName, version, ctx.registryUrl, ctx.port, ctx.token);
46
+ if (ctx.adapter.importPlugin) {
47
+ debug$1("importing npm-deprecate plugin into %s", tempFolder);
48
+ await ctx.adapter.importPlugin(tempFolder, "npm-deprecate");
49
+ }
50
+ return tempFolder;
17
51
  }
18
52
  async function testDeprecate(ctx) {
19
53
  const id = ctx.runId;
20
- const pkgName1 = `@verdaccio/dep1-${id}`;
21
54
  const message = "some message";
22
- const { tempFolder: tf1 } = await ctx.adapter.prepareProject(pkgName1, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
23
- await publishPkg(ctx, tf1, pkgName1);
24
- await deprecate(ctx, tf1, `${pkgName1}@1.0.0`, message);
25
- const info1 = await getInfo(ctx, pkgName1);
26
- assert.default.strictEqual(info1.name, pkgName1);
27
- assert.default.strictEqual(info1.deprecated, message, "Package should be deprecated");
28
- const pkgName2 = `@verdaccio/dep2-${id}`;
29
- const { tempFolder: tf2 } = await ctx.adapter.prepareProject(pkgName2, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
30
- await publishPkg(ctx, tf2, pkgName2);
31
- await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, message);
32
- const info2a = await getInfo(ctx, pkgName2);
33
- assert.default.strictEqual(info2a.deprecated, message);
34
- await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, "");
35
- const info2b = await getInfo(ctx, pkgName2);
36
- assert.default.strictEqual(info2b.deprecated, void 0, "Package should be un-deprecated");
37
- const pkgName3 = `@verdaccio/dep3-${id}`;
38
- const { tempFolder: tf3 } = await ctx.adapter.prepareProject(pkgName3, "1.0.0", ctx.registryUrl, ctx.port, ctx.token);
39
- await publishPkg(ctx, tf3, pkgName3);
40
- for (let i = 0; i < 3; i++) {
41
- await bumpVersion(ctx, tf3);
42
- await publishPkg(ctx, tf3, pkgName3);
43
- }
44
- await deprecate(ctx, tf3, pkgName3, message);
45
- for (const v of [
46
- "1.0.0",
47
- "1.1.0",
48
- "1.2.0",
49
- "1.3.0"
50
- ]) {
51
- const info = await getInfo(ctx, `${pkgName3}@${v}`);
52
- assert.default.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);
53
- }
54
- await bumpVersion(ctx, tf3);
55
- await publishPkg(ctx, tf3, pkgName3);
56
- const info3 = await getInfo(ctx, `${pkgName3}@1.4.0`);
57
- assert.default.strictEqual(info3.deprecated, void 0, "New version should not be deprecated");
55
+ await ctx.subTest("deprecate single version", async () => {
56
+ const pkgName = `@verdaccio/dep1-${id}`;
57
+ const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
58
+ await publishPkg(ctx, tf, pkgName);
59
+ await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);
60
+ const info = await getInfo(ctx, tf, pkgName);
61
+ assert.default.strictEqual(info.name, pkgName);
62
+ assert.default.strictEqual(info.deprecated, message, "Package should be deprecated");
63
+ });
64
+ await ctx.subTest("un-deprecate", async () => {
65
+ const pkgName = `@verdaccio/dep2-${id}`;
66
+ const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
67
+ await publishPkg(ctx, tf, pkgName);
68
+ await deprecate(ctx, tf, `${pkgName}@1.0.0`, message);
69
+ const info1 = await getInfo(ctx, tf, pkgName);
70
+ assert.default.strictEqual(info1.deprecated, message);
71
+ await deprecate(ctx, tf, `${pkgName}@1.0.0`, "");
72
+ const info2 = await getInfo(ctx, tf, pkgName);
73
+ assert.default.strictEqual(info2.deprecated, void 0, "Package should be un-deprecated");
74
+ });
75
+ await ctx.subTest("deprecate multiple versions", async () => {
76
+ const pkgName = `@verdaccio/dep3-${id}`;
77
+ const tf = await prepareDeprecateProject(ctx, pkgName, "1.0.0");
78
+ await publishPkg(ctx, tf, pkgName);
79
+ for (let i = 0; i < 3; i++) {
80
+ await bumpVersion(ctx, tf);
81
+ await publishPkg(ctx, tf, pkgName);
82
+ }
83
+ await deprecate(ctx, tf, pkgName, message);
84
+ for (const v of [
85
+ "1.0.0",
86
+ "1.1.0",
87
+ "1.2.0",
88
+ "1.3.0"
89
+ ]) {
90
+ const info = await getInfo(ctx, tf, `${pkgName}@${v}`);
91
+ assert.default.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);
92
+ }
93
+ await bumpVersion(ctx, tf);
94
+ await publishPkg(ctx, tf, pkgName);
95
+ const info = await getInfo(ctx, tf, `${pkgName}@1.4.0`);
96
+ assert.default.strictEqual(info.deprecated, void 0, "New version should not be deprecated");
97
+ });
58
98
  }
59
99
  var deprecateTest = {
60
100
  name: "deprecate",
@@ -1 +1 @@
1
- {"version":3,"file":"deprecate.cjs","names":[],"sources":["../../../src/tests/deprecate.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { TestContext, TestDefinition } from '../types';\n\nasync function publishPkg(ctx: TestContext, tempFolder: string, pkgName: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'publish',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function deprecate(\n ctx: TestContext,\n tempFolder: string,\n packageVersion: string,\n message: string\n) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'deprecate',\n packageVersion,\n message,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function getInfo(ctx: TestContext, pkgName: string) {\n const resp = await ctx.adapter.exec(\n {},\n 'info',\n pkgName,\n '--json',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n return JSON.parse(resp.stdout);\n}\n\nasync function bumpVersion(ctx: TestContext, tempFolder: string) {\n await ctx.adapter.exec(\n { cwd: tempFolder },\n 'version',\n 'minor',\n ...ctx.adapter.registryArg(ctx.registryUrl)\n );\n}\n\nasync function testDeprecate(ctx: TestContext): Promise<void> {\n const id = ctx.runId;\n\n // Test 1: deprecate a single version\n const pkgName1 = `@verdaccio/dep1-${id}`;\n const message = 'some message';\n const { tempFolder: tf1 } = await ctx.adapter.prepareProject(\n pkgName1,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tf1, pkgName1);\n await deprecate(ctx, tf1, `${pkgName1}@1.0.0`, message);\n const info1 = await getInfo(ctx, pkgName1);\n assert.strictEqual(info1.name, pkgName1);\n assert.strictEqual(info1.deprecated, message, 'Package should be deprecated');\n\n // Test 2: un-deprecate\n const pkgName2 = `@verdaccio/dep2-${id}`;\n const { tempFolder: tf2 } = await ctx.adapter.prepareProject(\n pkgName2,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tf2, pkgName2);\n await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, message);\n const info2a = await getInfo(ctx, pkgName2);\n assert.strictEqual(info2a.deprecated, message);\n // empty string = undeprecate\n await deprecate(ctx, tf2, `${pkgName2}@1.0.0`, '');\n const info2b = await getInfo(ctx, pkgName2);\n assert.strictEqual(info2b.deprecated, undefined, 'Package should be un-deprecated');\n\n // Test 3: deprecate multiple versions\n const pkgName3 = `@verdaccio/dep3-${id}`;\n const { tempFolder: tf3 } = await ctx.adapter.prepareProject(\n pkgName3,\n '1.0.0',\n ctx.registryUrl,\n ctx.port,\n ctx.token\n );\n await publishPkg(ctx, tf3, pkgName3);\n for (let i = 0; i < 3; i++) {\n await bumpVersion(ctx, tf3);\n await publishPkg(ctx, tf3, pkgName3);\n }\n await deprecate(ctx, tf3, pkgName3, message);\n for (const v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) {\n const info = await getInfo(ctx, `${pkgName3}@${v}`);\n assert.strictEqual(info.deprecated, message, `Version ${v} should be deprecated`);\n }\n // publish a new version after deprecation — should NOT be deprecated\n await bumpVersion(ctx, tf3);\n await publishPkg(ctx, tf3, pkgName3);\n const info3 = await getInfo(ctx, `${pkgName3}@1.4.0`);\n assert.strictEqual(info3.deprecated, undefined, 'New version should not be deprecated');\n}\n\nexport const deprecateTest: TestDefinition = {\n name: 'deprecate',\n requires: ['deprecate'],\n run: testDeprecate,\n};\n"],"mappings":";;;;AAIA,eAAe,WAAW,KAAkB,YAAoB,SAAiB;AAC/E,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,UACb,KACA,YACA,gBACA,SACA;AACA,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,aACA,gBACA,SACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,QAAQ,KAAkB,SAAiB;CACxD,MAAM,OAAO,MAAM,IAAI,QAAQ,KAC7B,EAAE,EACF,QACA,SACA,UACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;AACD,QAAO,KAAK,MAAM,KAAK,OAAO;;AAGhC,eAAe,YAAY,KAAkB,YAAoB;AAC/D,OAAM,IAAI,QAAQ,KAChB,EAAE,KAAK,YAAY,EACnB,WACA,SACA,GAAG,IAAI,QAAQ,YAAY,IAAI,YAAY,CAC5C;;AAGH,eAAe,cAAc,KAAiC;CAC5D,MAAM,KAAK,IAAI;CAGf,MAAM,WAAW,mBAAmB;CACpC,MAAM,UAAU;CAChB,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,KAAK,SAAS;AACpC,OAAM,UAAU,KAAK,KAAK,GAAG,SAAS,SAAS,QAAQ;CACvD,MAAM,QAAQ,MAAM,QAAQ,KAAK,SAAS;AAC1C,QAAA,QAAO,YAAY,MAAM,MAAM,SAAS;AACxC,QAAA,QAAO,YAAY,MAAM,YAAY,SAAS,+BAA+B;CAG7E,MAAM,WAAW,mBAAmB;CACpC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,KAAK,SAAS;AACpC,OAAM,UAAU,KAAK,KAAK,GAAG,SAAS,SAAS,QAAQ;CACvD,MAAM,SAAS,MAAM,QAAQ,KAAK,SAAS;AAC3C,QAAA,QAAO,YAAY,OAAO,YAAY,QAAQ;AAE9C,OAAM,UAAU,KAAK,KAAK,GAAG,SAAS,SAAS,GAAG;CAClD,MAAM,SAAS,MAAM,QAAQ,KAAK,SAAS;AAC3C,QAAA,QAAO,YAAY,OAAO,YAAY,KAAA,GAAW,kCAAkC;CAGnF,MAAM,WAAW,mBAAmB;CACpC,MAAM,EAAE,YAAY,QAAQ,MAAM,IAAI,QAAQ,eAC5C,UACA,SACA,IAAI,aACJ,IAAI,MACJ,IAAI,MACL;AACD,OAAM,WAAW,KAAK,KAAK,SAAS;AACpC,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,WAAW,KAAK,KAAK,SAAS;;AAEtC,OAAM,UAAU,KAAK,KAAK,UAAU,QAAQ;AAC5C,MAAK,MAAM,KAAK;EAAC;EAAS;EAAS;EAAS;EAAQ,EAAE;EACpD,MAAM,OAAO,MAAM,QAAQ,KAAK,GAAG,SAAS,GAAG,IAAI;AACnD,SAAA,QAAO,YAAY,KAAK,YAAY,SAAS,WAAW,EAAE,uBAAuB;;AAGnF,OAAM,YAAY,KAAK,IAAI;AAC3B,OAAM,WAAW,KAAK,KAAK,SAAS;CACpC,MAAM,QAAQ,MAAM,QAAQ,KAAK,GAAG,SAAS,QAAQ;AACrD,QAAA,QAAO,YAAY,MAAM,YAAY,KAAA,GAAW,uCAAuC;;AAGzF,IAAa,gBAAgC;CAC3C,MAAM;CACN,UAAU,CAAC,YAAY;CACvB,KAAK;CACN"}
1
+ {"version":3,"file":"deprecate.cjs","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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"}
@@ -3,6 +3,7 @@ const require_deprecate = require("./deprecate.cjs");
3
3
  const require_dist_tags = require("./dist-tags.cjs");
4
4
  const require_info = require("./info.cjs");
5
5
  const require_install = require("./install.cjs");
6
+ const require_login = require("./login.cjs");
6
7
  const require_ping = require("./ping.cjs");
7
8
  const require_publish = require("./publish.cjs");
8
9
  const require_search = require("./search.cjs");
@@ -16,6 +17,7 @@ var allTests = [
16
17
  require_info.infoTest,
17
18
  require_deprecate.deprecateTest,
18
19
  require_dist_tags.distTagsTest,
20
+ require_login.loginTest,
19
21
  require_ping.pingTest,
20
22
  require_search.searchTest,
21
23
  require_star.starTest,
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","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 { 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 pingTest,\n searchTest,\n starTest,\n unpublishTest,\n];\n\nexport {\n publishTest,\n installTest,\n auditTest,\n infoTest,\n deprecateTest,\n distTagsTest,\n pingTest,\n searchTest,\n starTest,\n unpublishTest,\n};\n"],"mappings":";;;;;;;;;;;AAaA,IAAa,WAA6B;CACxC,gBAAA;CACA,gBAAA;CACA,cAAA;CACA,aAAA;CACA,kBAAA;CACA,kBAAA;CACA,aAAA;CACA,eAAA;CACA,aAAA;CACA,kBAAA;CACD"}
1
+ {"version":3,"file":"index.cjs","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,gBAAA;CACA,gBAAA;CACA,cAAA;CACA,aAAA;CACA,kBAAA;CACA,kBAAA;CACA,cAAA;CACA,aAAA;CACA,eAAA;CACA,aAAA;CACA,kBAAA;CACD"}