diff --git a/.changeset/config.json b/.changeset/config.json index 90a7d53bf..7e6622a1f 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -12,6 +12,22 @@ "@verdaccio/ui-theme" ] ], + "ignoredPackages": [ + "@verdaccio/test-cli-commons", + "@verdaccio/e2e-cli-npm6", + "@verdaccio/e2e-cli-npm7", + "@verdaccio/e2e-cli-npm8", + "@verdaccio/e2e-cli-npm9", + "@verdaccio/e2e-cli-npm10", + "@verdaccio/e2e-cli-npm-common", + "@verdaccio/e2e-cli-yarn1", + "@verdaccio/e2e-cli-yarn2", + "@verdaccio/e2e-cli-yarn3", + "@verdaccio/e2e-cli-yarn4", + "@verdaccio/e2e-cli-pnpm8", + "@verdaccio/e2e-cli-pnpm9", + "@verdaccio/e2e-cli-pnpm10" + ], "access": "public", "baseBranch": "master", "updateInternalDependencies": "patch" diff --git a/.changeset/hot-crews-live.md b/.changeset/hot-crews-live.md new file mode 100644 index 000000000..798bb7410 --- /dev/null +++ b/.changeset/hot-crews-live.md @@ -0,0 +1,9 @@ +--- +'@verdaccio/types': patch +'@verdaccio/core': patch +'verdaccio': patch +'@verdaccio/store': patch +'@verdaccio/api': patch +--- + +fix: unpublish a package on storage package diff --git a/.github/workflows/e2e-ci.yml b/.github/workflows/e2e-ci.yml index 33ac4091b..eab74b9e0 100644 --- a/.github/workflows/e2e-ci.yml +++ b/.github/workflows/e2e-ci.yml @@ -26,7 +26,7 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare + corepack prepare - name: set store run: | mkdir ~/.pnpm-store @@ -45,14 +45,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: Use Node + - name: Use Node uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 with: node-version-file: '.nvmrc' - name: Install pnpm run: | corepack enable - corepack prepare + corepack prepare - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.0.2 with: path: ~/.pnpm-store @@ -83,7 +83,7 @@ jobs: e2e-cli-npm: needs: [prepare, build] strategy: - fail-fast: false + fail-fast: false matrix: pkg: [ @@ -93,7 +93,7 @@ jobs: npm9, npm10 ] - node: [20, 21] + node: [20, 22] name: ${{ matrix.pkg }}/ ubuntu-latest / ${{ matrix.node }} runs-on: ubuntu-latest steps: @@ -104,7 +104,7 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare + corepack prepare - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.0.2 with: path: ~/.pnpm-store @@ -136,8 +136,9 @@ jobs: [ pnpm8, pnpm9, + pnpm10, ] - node: [20, 21] + node: [20, 22] name: ${{ matrix.pkg }}/ ubuntu-latest / ${{ matrix.node }} runs-on: ubuntu-latest steps: @@ -176,13 +177,13 @@ jobs: fail-fast: false matrix: pkg: - [ + [ yarn1, yarn2, yarn3, yarn4 ] - node: [20, 21] + node: [20, 22] name: ${{ matrix.pkg }}/ ubuntu-latest / ${{ matrix.node }} runs-on: ubuntu-latest steps: @@ -193,7 +194,7 @@ jobs: - name: Install pnpm run: | corepack enable - corepack prepare + corepack prepare - uses: actions/cache@6849a6489940f00c2f30c0fb92c6274307ccb58a # v4.0.2 with: path: ~/.pnpm-store @@ -215,4 +216,4 @@ jobs: run: pnpm --filter @verdaccio/test-cli-commons build - name: Test CLI run: NODE_ENV=production pnpm test --filter ...@verdaccio/e2e-cli-${{matrix.pkg}} - + diff --git a/e2e/cli/cli-commons/package.json b/e2e/cli/cli-commons/package.json index 082c84c3f..30904bc84 100644 --- a/e2e/cli/cli-commons/package.json +++ b/e2e/cli/cli-commons/package.json @@ -2,8 +2,7 @@ "private": true, "name": "@verdaccio/test-cli-commons", "version": "2.0.0-next-8.0", - "main": "./build/index.js", - "types": "./build/index.d.ts", + "main": "src/index.ts", "devDependencies": { "@verdaccio/config": "workspace:8.0.0-next-8.4", "@verdaccio/core": "workspace:8.0.0-next-8.4", @@ -18,9 +17,6 @@ }, "scripts": { "test": "echo no test", - "type-check": "tsc --noEmit -p tsconfig.build.json", - "build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json", - "build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps", - "build": "pnpm run build:js && pnpm run build:types" + "build": "echo no build" } } diff --git a/e2e/cli/cli-commons/src/npm-utils.ts b/e2e/cli/cli-commons/src/npm-utils.ts index 04b20309c..aa591e450 100644 --- a/e2e/cli/cli-commons/src/npm-utils.ts +++ b/e2e/cli/cli-commons/src/npm-utils.ts @@ -1,24 +1,31 @@ -import { deepEqual } from 'assert'; +import buildDebug from 'debug'; import { addRegistry } from './utils'; +const debug = buildDebug('verdaccio:e2e:npm-utils'); export async function bumbUp(cmd, tempFolder, registry) { await cmd({ cwd: tempFolder }, 'version', 'minor', ...addRegistry(registry.getRegistryUrl())); } -export async function publish(cmd, tempFolder, pkgName, registry, arg: string[] = []) { - const resp = await cmd( +export async function bumpUpPackage(cmd, tempFolder, pkgName, registry, arg: string[] = []) { + debug('bump up package %o', pkgName); + await cmd( { cwd: tempFolder }, - 'publish', + 'version', ...arg, - '--json', + '--no--git-tag-version', + '--loglevel=info', ...addRegistry(registry.getRegistryUrl()) ); - const parsedBody = JSON.parse(resp.stdout as string); - deepEqual(parsedBody.name, pkgName); +} + +export async function publish(cmd, tempFolder, pkgName, registry, arg: string[] = []) { + debug('publishing %o', pkgName); + await cmd({ cwd: tempFolder }, 'publish', ...arg, ...addRegistry(registry.getRegistryUrl())); } export async function getInfoVersions(cmd, pkgName, registry) { + debug('getting info %o', pkgName); const infoResp = await cmd( {}, 'info', @@ -27,5 +34,6 @@ export async function getInfoVersions(cmd, pkgName, registry) { ...addRegistry(registry.getRegistryUrl()) ); const infoBody = JSON.parse(infoResp.stdout as string); + debug('info %o', infoBody); return infoBody; } diff --git a/e2e/cli/cli-commons/src/process.ts b/e2e/cli/cli-commons/src/process.ts index b177ae482..44375a65e 100644 --- a/e2e/cli/cli-commons/src/process.ts +++ b/e2e/cli/cli-commons/src/process.ts @@ -4,6 +4,7 @@ import buildDebug from 'debug'; import { createInterface } from 'readline'; const debug = buildDebug('verdaccio:e2e:process'); +const debugRead = buildDebug('verdaccio:e2e:line'); export type ExecOutput = { stdout: string; @@ -11,7 +12,7 @@ export type ExecOutput = { }; export async function exec(options: SpawnOptions, cmd, args): Promise { - debug('start _exec %o %o %o', options, cmd, args); + debug('start _exec %o %o %o', options, cmd, args ? args.join(' ') : ''); let stdout = ''; let stderr; const env = options.env; @@ -32,9 +33,17 @@ export async function exec(options: SpawnOptions, cmd, args): Promise { + debugRead('data %o', data.toString()); + }); + const rl = createInterface({ + input: childProcess.stdout, + output: process.stdout, + terminal: false, + }); rl.on('line', function (line) { + debugRead('line %o', line); stdout += line; }); } @@ -42,6 +51,7 @@ export async function exec(options: SpawnOptions, cmd, args): Promise { childProcess.on('exit', (error) => { + debugRead('exit %o', error); if (!error) { resolve({ stdout, stderr }); } else { diff --git a/e2e/cli/cli-commons/src/registry.ts b/e2e/cli/cli-commons/src/registry.ts index 0069b02b2..3cfc81599 100644 --- a/e2e/cli/cli-commons/src/registry.ts +++ b/e2e/cli/cli-commons/src/registry.ts @@ -17,7 +17,7 @@ export type Setup = { const log = process.env.NODE_ENV === 'production' ? { type: 'stdout', format: 'json', level: 'warn' } - : { type: 'stdout', format: 'pretty', level: 'info' }; + : { type: 'stdout', format: 'pretty', level: 'debug' }; const defaultConfig = { ...getDefaultConfig(), diff --git a/e2e/cli/cli-commons/src/utils.ts b/e2e/cli/cli-commons/src/utils.ts index 8f017f316..0a697b9bd 100644 --- a/e2e/cli/cli-commons/src/utils.ts +++ b/e2e/cli/cli-commons/src/utils.ts @@ -1,9 +1,12 @@ +import buildDebug from 'debug'; import fs from 'fs-extra'; import { cp, readFile, writeFile } from 'fs/promises'; import { join } from 'path'; import { fileUtils } from '@verdaccio/core'; +const debug = buildDebug('verdaccio:e2e:utils'); + export function createProject(projectName: string) { const tempRootFolder = global.__namespace.getItem('dir-suite-root'); const verdaccioInstall = join(tempRootFolder, projectName); @@ -13,12 +16,14 @@ export function createProject(projectName: string) { } export function copyConfigFile(rootFolder, configTemplate): string { const configPath = join(rootFolder, 'config.yaml'); + debug('copying config file %o', configPath); copyTo(join(__dirname, configTemplate), configPath); return configPath; } export async function createTempFolder(prefix: string) { + debug('creating temp folder %o', prefix); return fileUtils.createTempFolder(prefix); } @@ -31,10 +36,12 @@ export function cleanUpTemp(tmpFolder) { } export function addRegistry(registryUrl) { + debug('adding registry %o', registryUrl); return ['--registry', registryUrl]; } export function addNpmPrefix(installFolder) { + debug('adding prefix %o', installFolder); return ['--prefix', installFolder]; } @@ -50,6 +57,7 @@ export async function prepareYarnModernProject( registryDomain: string, yarnPath: string ) { + debug('preparing yarn project %o', projectName); const tempFolder = await createTempFolder(projectName); // FUTURE: native copy folder instead fs-extra fs.copySync(templatePath, tempFolder); @@ -67,6 +75,7 @@ export const getPackageJSON = ( dependencies = {}, devDependencies = {} ) => { + debug('creating package.json %o', packageName); const json = { name: packageName, version, @@ -103,6 +112,7 @@ export async function prepareGenericEmptyProject( dependencies: any = {}, devDependencies: any = {} ) { + debug('preparing generic project %o', packageName); const getNPMrc = (port, token, registry) => `//localhost:${port}/:_authToken=${token} registry=${registry}`; const tempFolder = await createTempFolder('temp-folder'); diff --git a/e2e/cli/e2e-npm-commons/.babelrc b/e2e/cli/e2e-npm-commons/.babelrc new file mode 100644 index 000000000..851856e59 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "../../../.babelrc" +} diff --git a/e2e/cli/e2e-npm-commons/.eslintrc b/e2e/cli/e2e-npm-commons/.eslintrc new file mode 100644 index 000000000..eb2ac4c85 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/.eslintrc @@ -0,0 +1,7 @@ +{ + "rules": { + "no-console": 0, + "@typescript-eslint/no-var-requires": 0, + "@typescript-eslint/explicit-member-accessibility": 0 + } +} diff --git a/e2e/cli/e2e-npm-commons/audit.ts b/e2e/cli/e2e-npm-commons/audit.ts new file mode 100644 index 000000000..0d819c6f1 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/audit.ts @@ -0,0 +1,45 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +export function runAudit(npm) { + describe('audit a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['verdaccio-memory', '@verdaccio/cli']])( + 'should audit a package %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl(), + { jquery: '3.6.1' } + ); + // install is required to create package lock file + await npm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); + const resp = await npm( + { cwd: tempFolder }, + 'audit', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.metadata).toBeDefined(); + expect(parsedBody.auditReportVersion).toBeDefined(); + expect(parsedBody.vulnerabilities).toBeDefined(); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/deprecate.ts b/e2e/cli/e2e-npm-commons/deprecate.ts new file mode 100644 index 000000000..c15f82725 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/deprecate.ts @@ -0,0 +1,119 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + npmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runDeprecate(npm) { + describe('deprecate a package', () => { + let registry; + + async function deprecate(tempFolder, packageVersion, registry, message) { + await npm( + { cwd: tempFolder }, + 'deprecate', + packageVersion, + message, + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + } + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@verdaccio/deprecated-1']])( + 'should deprecate a single package %s', + async (pkgName) => { + const message = 'some message'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + // deprecate one version + await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); + // verify is deprecated + const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); + expect(infoBody.name).toEqual(pkgName); + expect(infoBody.deprecated).toEqual(message); + } + ); + + test.each([['@verdaccio/deprecated-2']])( + 'should un-deprecate a package %s', + async (pkgName) => { + const message = 'some message'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + // deprecate one version + await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); + // verify is deprecated + const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); + expect(infoBody.deprecated).toEqual(message); + // empty string is same as undeprecate + await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); + const infoBody2 = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); + expect(infoBody2.deprecated).toBeUndefined(); + } + ); + + test.each([['@verdaccio/deprecated-3']])( + 'should deprecate a multiple packages %s', + async (pkgName) => { + const message = 'some message'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + // publish 1.0.0 + await npmUtils.publish(npm, tempFolder, pkgName, registry); + // publish 1.1.0 + await npmUtils.bumbUp(npm, tempFolder, registry); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + // publish 1.2.0 + await npmUtils.bumbUp(npm, tempFolder, registry); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + // publish 1.3.0 + await npmUtils.bumbUp(npm, tempFolder, registry); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + // // deprecate all version + await deprecate(tempFolder, pkgName, registry, message); + // verify is deprecated + for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { + const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@${v}`, registry); + expect(infoResp.deprecated).toEqual(message); + } + // publish normal version + // publish 1.4.0 + await npmUtils.bumbUp(npm, tempFolder, registry); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@1.4.0`, registry); + // must be not deprecated + expect(infoResp.deprecated).toBeUndefined(); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/dist-tags.ts b/e2e/cli/e2e-npm-commons/dist-tags.ts new file mode 100644 index 000000000..323939ada --- /dev/null +++ b/e2e/cli/e2e-npm-commons/dist-tags.ts @@ -0,0 +1,92 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + npmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runDistTag(npm) { + describe('dist-tag a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumbUp(npm, tempFolder, registry); + await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); + const resp2 = await npm( + { cwd: tempFolder }, + 'dist-tag', + 'ls', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); + }); + + test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumbUp(npm, tempFolder, registry); + await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); + const resp2 = await npm( + { cwd: tempFolder }, + 'dist-tag', + 'rm', + `${pkgName}@1.1.0`, + 'beta', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); + }); + + test.each([['@verdaccio/five']])( + 'should add tag to package and version with dist-tags for %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumbUp(npm, tempFolder, registry); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + const resp2 = await npm( + { cwd: tempFolder }, + 'dist-tag', + 'add', + `${pkgName}@1.1.0`, + 'alfa', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/index.ts b/e2e/cli/e2e-npm-commons/index.ts new file mode 100644 index 000000000..8bd4f181d --- /dev/null +++ b/e2e/cli/e2e-npm-commons/index.ts @@ -0,0 +1,10 @@ +export { runAudit } from './audit'; +export { runDeprecate } from './deprecate'; +export { runInstall } from './install'; +export { runInfo } from './info'; +export { runPing } from './ping'; +export { runPublish } from './publish'; +export { runSearch } from './search'; +export { runStar } from './star'; +export { runUnpublish } from './unpublish'; +export { runDistTag } from './dist-tags'; diff --git a/e2e/cli/e2e-npm-commons/info.ts b/e2e/cli/e2e-npm-commons/info.ts new file mode 100644 index 000000000..de1dd64a4 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/info.ts @@ -0,0 +1,32 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; + +export function runInfo(npm) { + describe('install a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should run npm info json body', async () => { + const resp = await npm( + {}, + 'info', + 'verdaccio', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.name).toEqual('verdaccio'); + expect(parsedBody.dependencies).toBeDefined(); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/install.ts b/e2e/cli/e2e-npm-commons/install.ts new file mode 100644 index 000000000..cbaebe4ff --- /dev/null +++ b/e2e/cli/e2e-npm-commons/install.ts @@ -0,0 +1,39 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +export function runInstall(npm) { + describe('install a project packages', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should run npm install json body', async () => { + const { tempFolder } = await prepareGenericEmptyProject( + 'something', + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl(), + { react: '18.2.0' } + ); + const resp = await npm( + { cwd: tempFolder }, + 'install', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.added).toBeDefined(); + expect(parsedBody.audit).toBeDefined(); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/package.json b/e2e/cli/e2e-npm-commons/package.json new file mode 100644 index 000000000..8f3bb695f --- /dev/null +++ b/e2e/cli/e2e-npm-commons/package.json @@ -0,0 +1,11 @@ +{ + "private": true, + "name": "@verdaccio/e2e-cli-npm-common", + "version": "1.0.0", + "dependencies": { + "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0" + }, + "scripts": { + "test": "echo no test" + } +} diff --git a/e2e/cli/e2e-npm-commons/ping.ts b/e2e/cli/e2e-npm-commons/ping.ts new file mode 100644 index 000000000..d68092ffb --- /dev/null +++ b/e2e/cli/e2e-npm-commons/ping.ts @@ -0,0 +1,25 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; + +export function runPing(npm) { + describe('ping registry', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should ping registry', async () => { + const resp = await npm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/publish.ts b/e2e/cli/e2e-npm-commons/publish.ts new file mode 100644 index 000000000..17a7554ff --- /dev/null +++ b/e2e/cli/e2e-npm-commons/publish.ts @@ -0,0 +1,42 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +export function runPublish(npm) { + describe('publish a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( + 'should publish a package %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + const resp = await npm( + { cwd: tempFolder }, + 'publish', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.name).toEqual(pkgName); + expect(parsedBody.files).toBeDefined(); + expect(parsedBody.files).toBeDefined(); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/search.ts b/e2e/cli/e2e-npm-commons/search.ts new file mode 100644 index 000000000..08390b7a2 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/search.ts @@ -0,0 +1,34 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; + +export function runSearch(npm) { + describe('search a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should search a package', async () => { + const resp = await npm( + {}, + 'search', + '@verdaccio/cli', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + const pkgFind = parsedBody.find((item) => { + return item.name === '@verdaccio/cli'; + }); + expect(pkgFind.name).toEqual('@verdaccio/cli'); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/star.ts b/e2e/cli/e2e-npm-commons/star.ts new file mode 100644 index 000000000..fa830b408 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/star.ts @@ -0,0 +1,90 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + npmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runStar(npm) { + describe('star a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + + await npmUtils.publish(npm, tempFolder, pkgName, registry); + const resp = await npm( + { cwd: tempFolder }, + 'star', + pkgName, + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp.stdout).toEqual(`★ ${pkgName}`); + }); + + test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + + await npmUtils.publish(npm, tempFolder, pkgName, registry); + const resp = await npm( + { cwd: tempFolder }, + 'star', + pkgName, + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp.stdout).toEqual(`★ ${pkgName}`); + + const resp1 = await npm( + { cwd: tempFolder }, + 'unstar', + pkgName, + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp1.stdout).toEqual(`☆ ${pkgName}`); + }); + + test('should list stars of a user %s', async () => { + const pkgName = '@verdaccio/stars'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); + const resp = await npm( + { cwd: tempFolder }, + 'stars', + ...addRegistry(registry.getRegistryUrl()) + ); + // side effects: this result is affected the the package published in the previous step + expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm-commons/tsconfig.json b/e2e/cli/e2e-npm-commons/tsconfig.json new file mode 100644 index 000000000..85f4ceca6 --- /dev/null +++ b/e2e/cli/e2e-npm-commons/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.reference.json", + "references": [ + { + "path": "../cli-commons" + } + ] +} diff --git a/e2e/cli/e2e-npm-commons/unpublish.ts b/e2e/cli/e2e-npm-commons/unpublish.ts new file mode 100644 index 000000000..32f6a93cf --- /dev/null +++ b/e2e/cli/e2e-npm-commons/unpublish.ts @@ -0,0 +1,86 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + npmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runUnpublish(npm) { + describe('unpublish a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@verdaccio/test1', 'super-package-do-not-exist-spam']])( + 'should unpublish a full package %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-beta', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(npm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(npm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(npm, tempFolder, pkgName, registry, ['major']); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + + const resp2 = await npm( + { cwd: tempFolder }, + 'unpublish', + pkgName, + '--force', + '--loglevel=info', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('- @verdaccio/test1'); + } + ); + + test.each([['@verdaccio/test1', 'super-package-do-not-exist-spam']])( + 'should unpublish a package %s version', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-beta', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(npm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(npm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(npm, tempFolder, pkgName, registry, ['major']); + await npmUtils.publish(npm, tempFolder, pkgName, registry); + + const resp2 = await npm( + { cwd: tempFolder }, + 'unpublish', + `${pkgName}@1.0.0-beta`, + '--force', + '--loglevel=info', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('- @verdaccio/test1@1.0.0-beta'); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-npm10/audit.spec.ts b/e2e/cli/e2e-npm10/audit.spec.ts index ad1e34dae..f54f74666 100644 --- a/e2e/cli/e2e-npm10/audit.spec.ts +++ b/e2e/cli/e2e-npm10/audit.spec.ts @@ -1,45 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runAudit } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('audit a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', '@verdaccio/cli']])( - 'should audit a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { jquery: '3.6.1' } - ); - // install is required to create package lock file - await npm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); - const resp = await npm( - { cwd: tempFolder }, - 'audit', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.metadata).toBeDefined(); - expect(parsedBody.auditReportVersion).toBeDefined(); - expect(parsedBody.vulnerabilities).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runAudit(npm); }); diff --git a/e2e/cli/e2e-npm10/deprecate.spec.ts b/e2e/cli/e2e-npm10/deprecate.spec.ts index 6aaef6ce0..8ff989f1d 100644 --- a/e2e/cli/e2e-npm10/deprecate.spec.ts +++ b/e2e/cli/e2e-npm10/deprecate.spec.ts @@ -1,116 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDeprecate } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('deprecate a package', () => { - let registry; - - async function deprecate(tempFolder, packageVersion, registry, message) { - await npm( - { cwd: tempFolder }, - 'deprecate', - packageVersion, - message, - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - } - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/deprecated-1']])( - 'should deprecate a single package %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.name).toEqual(pkgName); - expect(infoBody.deprecated).toEqual(message); - } - ); - - test.each([['@verdaccio/deprecated-2']])('should un-deprecate a package %s', async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.deprecated).toEqual(message); - // empty string is same as undeprecate - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); - const infoBody2 = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody2.deprecated).toBeUndefined(); - }); - - test.each([['@verdaccio/deprecated-3']])( - 'should deprecate a multiple packages %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - // publish 1.0.0 - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.1.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.2.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.3.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // // deprecate all version - await deprecate(tempFolder, pkgName, registry, message); - // verify is deprecated - for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@${v}`, registry); - expect(infoResp.deprecated).toEqual(message); - } - // publish normal version - // publish 1.4.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@1.4.0`, registry); - // must be not deprecated - expect(infoResp.deprecated).toBeUndefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runDeprecate(npm); }); diff --git a/e2e/cli/e2e-npm10/dist-tags.spec.ts b/e2e/cli/e2e-npm10/dist-tags.spec.ts index 007d7370a..7a55089be 100644 --- a/e2e/cli/e2e-npm10/dist-tags.spec.ts +++ b/e2e/cli/e2e-npm10/dist-tags.spec.ts @@ -1,92 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDistTag } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'ls', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); - }); - - test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'rm', - `${pkgName}@1.1.0`, - 'beta', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); - }); - - test.each([['@verdaccio/five']])( - 'should add tag to package and version with dist-tags for %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'add', - `${pkgName}@1.1.0`, - 'alfa', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('dist-tags a package', () => { + runDistTag(npm); }); diff --git a/e2e/cli/e2e-npm10/info.spec.ts b/e2e/cli/e2e-npm10/info.spec.ts index 2964174c1..d110bebfb 100644 --- a/e2e/cli/e2e-npm10/info.spec.ts +++ b/e2e/cli/e2e-npm10/info.spec.ts @@ -1,32 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runInfo } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm info json body', async () => { - const resp = await npm( - {}, - 'info', - 'verdaccio', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual('verdaccio'); - expect(parsedBody.dependencies).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); +describe('info a package', () => { + runInfo(npm); }); diff --git a/e2e/cli/e2e-npm10/install.spec.ts b/e2e/cli/e2e-npm10/install.spec.ts index badcc90dc..8737ecc42 100644 --- a/e2e/cli/e2e-npm10/install.spec.ts +++ b/e2e/cli/e2e-npm10/install.spec.ts @@ -1,39 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runInstall } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('install a project packages', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm install json body', async () => { - const { tempFolder } = await prepareGenericEmptyProject( - 'something', - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { react: '18.2.0' } - ); - const resp = await npm( - { cwd: tempFolder }, - 'install', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.added).toBeDefined(); - expect(parsedBody.audit).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); + runInstall(npm); }); diff --git a/e2e/cli/e2e-npm10/package.json b/e2e/cli/e2e-npm10/package.json index 5079eb75a..ad3270b9c 100644 --- a/e2e/cli/e2e-npm10/package.json +++ b/e2e/cli/e2e-npm10/package.json @@ -4,7 +4,8 @@ "version": "1.0.1", "dependencies": { "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", - "npm": "10.8.2" + "@verdaccio/e2e-cli-npm-common": "workspace:*", + "npm": "10.9.0" }, "scripts": { "test": "vitest run --testTimeout 50000" diff --git a/e2e/cli/e2e-npm10/ping.spec.ts b/e2e/cli/e2e-npm10/ping.spec.ts index 7690fa9d6..8dc511bda 100644 --- a/e2e/cli/e2e-npm10/ping.spec.ts +++ b/e2e/cli/e2e-npm10/ping.spec.ts @@ -1,25 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runPing } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('ping registry', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should ping registry', async () => { - const resp = await npm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); - }); - - afterAll(async () => { - registry.stop(); - }); + runPing(npm); }); diff --git a/e2e/cli/e2e-npm10/publish.spec.ts b/e2e/cli/e2e-npm10/publish.spec.ts index 0d354056f..d5efcc78e 100644 --- a/e2e/cli/e2e-npm10/publish.spec.ts +++ b/e2e/cli/e2e-npm10/publish.spec.ts @@ -1,42 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runPublish } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( - 'should publish a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - const resp = await npm( - { cwd: tempFolder }, - 'publish', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual(pkgName); - expect(parsedBody.files).toBeDefined(); - expect(parsedBody.files).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('publish a package', () => { + runPublish(npm); }); diff --git a/e2e/cli/e2e-npm10/search.spec.ts b/e2e/cli/e2e-npm10/search.spec.ts index 000adf39e..1f76a0956 100644 --- a/e2e/cli/e2e-npm10/search.spec.ts +++ b/e2e/cli/e2e-npm10/search.spec.ts @@ -1,34 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runSearch } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('search a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should search a package', async () => { - const resp = await npm( - {}, - 'search', - '@verdaccio/cli', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - const pkgFind = parsedBody.find((item) => { - return item.name === '@verdaccio/cli'; - }); - expect(pkgFind.name).toEqual('@verdaccio/cli'); - }); - - afterAll(async () => { - registry.stop(); - }); + runSearch(npm); }); diff --git a/e2e/cli/e2e-npm10/star.spec.ts b/e2e/cli/e2e-npm10/star.spec.ts index 0400ed8e9..4d3bda09e 100644 --- a/e2e/cli/e2e-npm10/star.spec.ts +++ b/e2e/cli/e2e-npm10/star.spec.ts @@ -1,86 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runStar } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('star a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - }); - - test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - - const resp1 = await npm( - { cwd: tempFolder }, - 'unstar', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp1.stdout).toEqual(`☆ ${pkgName}`); - }); - - test('should list stars of a user %s', async () => { - const pkgName = '@verdaccio/stars'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); - const resp = await npm({ cwd: tempFolder }, 'stars', ...addRegistry(registry.getRegistryUrl())); - // side effects: this result is affected the the package published in the previous step - expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); - }); - - afterAll(async () => { - registry.stop(); - }); + runStar(npm); }); diff --git a/e2e/cli/e2e-npm10/unpublish.spec.ts b/e2e/cli/e2e-npm10/unpublish.spec.ts new file mode 100644 index 000000000..901867976 --- /dev/null +++ b/e2e/cli/e2e-npm10/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-npm-common'; + +import { npm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(npm); +}); diff --git a/e2e/cli/e2e-npm6/deprecate.spec.ts b/e2e/cli/e2e-npm6/deprecate.spec.ts index 6aaef6ce0..8ff989f1d 100644 --- a/e2e/cli/e2e-npm6/deprecate.spec.ts +++ b/e2e/cli/e2e-npm6/deprecate.spec.ts @@ -1,116 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDeprecate } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('deprecate a package', () => { - let registry; - - async function deprecate(tempFolder, packageVersion, registry, message) { - await npm( - { cwd: tempFolder }, - 'deprecate', - packageVersion, - message, - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - } - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/deprecated-1']])( - 'should deprecate a single package %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.name).toEqual(pkgName); - expect(infoBody.deprecated).toEqual(message); - } - ); - - test.each([['@verdaccio/deprecated-2']])('should un-deprecate a package %s', async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.deprecated).toEqual(message); - // empty string is same as undeprecate - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); - const infoBody2 = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody2.deprecated).toBeUndefined(); - }); - - test.each([['@verdaccio/deprecated-3']])( - 'should deprecate a multiple packages %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - // publish 1.0.0 - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.1.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.2.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.3.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // // deprecate all version - await deprecate(tempFolder, pkgName, registry, message); - // verify is deprecated - for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@${v}`, registry); - expect(infoResp.deprecated).toEqual(message); - } - // publish normal version - // publish 1.4.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@1.4.0`, registry); - // must be not deprecated - expect(infoResp.deprecated).toBeUndefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runDeprecate(npm); }); diff --git a/e2e/cli/e2e-npm6/dist-tags.spec.ts b/e2e/cli/e2e-npm6/dist-tags.spec.ts index 007d7370a..7a55089be 100644 --- a/e2e/cli/e2e-npm6/dist-tags.spec.ts +++ b/e2e/cli/e2e-npm6/dist-tags.spec.ts @@ -1,92 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDistTag } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'ls', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); - }); - - test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'rm', - `${pkgName}@1.1.0`, - 'beta', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); - }); - - test.each([['@verdaccio/five']])( - 'should add tag to package and version with dist-tags for %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'add', - `${pkgName}@1.1.0`, - 'alfa', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('dist-tags a package', () => { + runDistTag(npm); }); diff --git a/e2e/cli/e2e-npm6/info.spec.ts b/e2e/cli/e2e-npm6/info.spec.ts index 2964174c1..d110bebfb 100644 --- a/e2e/cli/e2e-npm6/info.spec.ts +++ b/e2e/cli/e2e-npm6/info.spec.ts @@ -1,32 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runInfo } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm info json body', async () => { - const resp = await npm( - {}, - 'info', - 'verdaccio', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual('verdaccio'); - expect(parsedBody.dependencies).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); +describe('info a package', () => { + runInfo(npm); }); diff --git a/e2e/cli/e2e-npm6/install.spec.ts b/e2e/cli/e2e-npm6/install.spec.ts index badcc90dc..8737ecc42 100644 --- a/e2e/cli/e2e-npm6/install.spec.ts +++ b/e2e/cli/e2e-npm6/install.spec.ts @@ -1,39 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runInstall } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('install a project packages', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm install json body', async () => { - const { tempFolder } = await prepareGenericEmptyProject( - 'something', - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { react: '18.2.0' } - ); - const resp = await npm( - { cwd: tempFolder }, - 'install', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.added).toBeDefined(); - expect(parsedBody.audit).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); + runInstall(npm); }); diff --git a/e2e/cli/e2e-npm6/package.json b/e2e/cli/e2e-npm6/package.json index ce05acefb..4a06cdc97 100644 --- a/e2e/cli/e2e-npm6/package.json +++ b/e2e/cli/e2e-npm6/package.json @@ -4,7 +4,8 @@ "version": "1.0.2-next-8.0", "dependencies": { "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", - "npm": "9.9.3" + "@verdaccio/e2e-cli-npm-common": "workspace:*", + "npm": "6.14.18" }, "scripts": { "test": "vitest run --testTimeout 20000" diff --git a/e2e/cli/e2e-npm6/ping.spec.ts b/e2e/cli/e2e-npm6/ping.spec.ts index 7690fa9d6..8dc511bda 100644 --- a/e2e/cli/e2e-npm6/ping.spec.ts +++ b/e2e/cli/e2e-npm6/ping.spec.ts @@ -1,25 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runPing } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('ping registry', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should ping registry', async () => { - const resp = await npm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); - }); - - afterAll(async () => { - registry.stop(); - }); + runPing(npm); }); diff --git a/e2e/cli/e2e-npm6/publish.spec.ts b/e2e/cli/e2e-npm6/publish.spec.ts index f91a387d4..d5efcc78e 100644 --- a/e2e/cli/e2e-npm6/publish.spec.ts +++ b/e2e/cli/e2e-npm6/publish.spec.ts @@ -1,43 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runPublish } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( - 'should publish a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - const resp = await npm( - { cwd: tempFolder }, - 'publish', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual(pkgName); - expect(parsedBody.files).toBeDefined(); - expect(parsedBody.files).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runPublish(npm); }); diff --git a/e2e/cli/e2e-npm6/search.spec.ts b/e2e/cli/e2e-npm6/search.spec.ts index 000adf39e..1f76a0956 100644 --- a/e2e/cli/e2e-npm6/search.spec.ts +++ b/e2e/cli/e2e-npm6/search.spec.ts @@ -1,34 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runSearch } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('search a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should search a package', async () => { - const resp = await npm( - {}, - 'search', - '@verdaccio/cli', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - const pkgFind = parsedBody.find((item) => { - return item.name === '@verdaccio/cli'; - }); - expect(pkgFind.name).toEqual('@verdaccio/cli'); - }); - - afterAll(async () => { - registry.stop(); - }); + runSearch(npm); }); diff --git a/e2e/cli/e2e-npm6/star.spec.ts b/e2e/cli/e2e-npm6/star.spec.ts index 0400ed8e9..4d3bda09e 100644 --- a/e2e/cli/e2e-npm6/star.spec.ts +++ b/e2e/cli/e2e-npm6/star.spec.ts @@ -1,86 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runStar } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('star a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - }); - - test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - - const resp1 = await npm( - { cwd: tempFolder }, - 'unstar', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp1.stdout).toEqual(`☆ ${pkgName}`); - }); - - test('should list stars of a user %s', async () => { - const pkgName = '@verdaccio/stars'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); - const resp = await npm({ cwd: tempFolder }, 'stars', ...addRegistry(registry.getRegistryUrl())); - // side effects: this result is affected the the package published in the previous step - expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); - }); - - afterAll(async () => { - registry.stop(); - }); + runStar(npm); }); diff --git a/e2e/cli/e2e-npm6/unpublish.spec.ts b/e2e/cli/e2e-npm6/unpublish.spec.ts new file mode 100644 index 000000000..901867976 --- /dev/null +++ b/e2e/cli/e2e-npm6/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-npm-common'; + +import { npm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(npm); +}); diff --git a/e2e/cli/e2e-npm7/audit.spec.ts b/e2e/cli/e2e-npm7/audit.spec.ts index ad1e34dae..f54f74666 100644 --- a/e2e/cli/e2e-npm7/audit.spec.ts +++ b/e2e/cli/e2e-npm7/audit.spec.ts @@ -1,45 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runAudit } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('audit a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', '@verdaccio/cli']])( - 'should audit a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { jquery: '3.6.1' } - ); - // install is required to create package lock file - await npm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); - const resp = await npm( - { cwd: tempFolder }, - 'audit', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.metadata).toBeDefined(); - expect(parsedBody.auditReportVersion).toBeDefined(); - expect(parsedBody.vulnerabilities).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runAudit(npm); }); diff --git a/e2e/cli/e2e-npm7/deprecate.spec.ts b/e2e/cli/e2e-npm7/deprecate.spec.ts index 6aaef6ce0..8ff989f1d 100644 --- a/e2e/cli/e2e-npm7/deprecate.spec.ts +++ b/e2e/cli/e2e-npm7/deprecate.spec.ts @@ -1,116 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDeprecate } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('deprecate a package', () => { - let registry; - - async function deprecate(tempFolder, packageVersion, registry, message) { - await npm( - { cwd: tempFolder }, - 'deprecate', - packageVersion, - message, - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - } - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/deprecated-1']])( - 'should deprecate a single package %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.name).toEqual(pkgName); - expect(infoBody.deprecated).toEqual(message); - } - ); - - test.each([['@verdaccio/deprecated-2']])('should un-deprecate a package %s', async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.deprecated).toEqual(message); - // empty string is same as undeprecate - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); - const infoBody2 = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody2.deprecated).toBeUndefined(); - }); - - test.each([['@verdaccio/deprecated-3']])( - 'should deprecate a multiple packages %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - // publish 1.0.0 - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.1.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.2.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.3.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // // deprecate all version - await deprecate(tempFolder, pkgName, registry, message); - // verify is deprecated - for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@${v}`, registry); - expect(infoResp.deprecated).toEqual(message); - } - // publish normal version - // publish 1.4.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@1.4.0`, registry); - // must be not deprecated - expect(infoResp.deprecated).toBeUndefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runDeprecate(npm); }); diff --git a/e2e/cli/e2e-npm7/dist-tags.spec.ts b/e2e/cli/e2e-npm7/dist-tags.spec.ts index 007d7370a..7a55089be 100644 --- a/e2e/cli/e2e-npm7/dist-tags.spec.ts +++ b/e2e/cli/e2e-npm7/dist-tags.spec.ts @@ -1,92 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDistTag } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'ls', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); - }); - - test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'rm', - `${pkgName}@1.1.0`, - 'beta', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); - }); - - test.each([['@verdaccio/five']])( - 'should add tag to package and version with dist-tags for %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'add', - `${pkgName}@1.1.0`, - 'alfa', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('dist-tags a package', () => { + runDistTag(npm); }); diff --git a/e2e/cli/e2e-npm7/info.spec.ts b/e2e/cli/e2e-npm7/info.spec.ts index 2964174c1..d110bebfb 100644 --- a/e2e/cli/e2e-npm7/info.spec.ts +++ b/e2e/cli/e2e-npm7/info.spec.ts @@ -1,32 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runInfo } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm info json body', async () => { - const resp = await npm( - {}, - 'info', - 'verdaccio', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual('verdaccio'); - expect(parsedBody.dependencies).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); +describe('info a package', () => { + runInfo(npm); }); diff --git a/e2e/cli/e2e-npm7/install.spec.ts b/e2e/cli/e2e-npm7/install.spec.ts index badcc90dc..8737ecc42 100644 --- a/e2e/cli/e2e-npm7/install.spec.ts +++ b/e2e/cli/e2e-npm7/install.spec.ts @@ -1,39 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runInstall } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('install a project packages', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm install json body', async () => { - const { tempFolder } = await prepareGenericEmptyProject( - 'something', - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { react: '18.2.0' } - ); - const resp = await npm( - { cwd: tempFolder }, - 'install', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.added).toBeDefined(); - expect(parsedBody.audit).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); + runInstall(npm); }); diff --git a/e2e/cli/e2e-npm7/package.json b/e2e/cli/e2e-npm7/package.json index 8882fcd60..3551433c9 100644 --- a/e2e/cli/e2e-npm7/package.json +++ b/e2e/cli/e2e-npm7/package.json @@ -4,7 +4,8 @@ "version": "1.0.2-next-8.0", "dependencies": { "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", - "npm": "9.9.3" + "@verdaccio/e2e-cli-npm-common": "workspace:*", + "npm": "7.24.2" }, "scripts": { "test": "vitest run --testTimeout 50000" diff --git a/e2e/cli/e2e-npm7/ping.spec.ts b/e2e/cli/e2e-npm7/ping.spec.ts index 7690fa9d6..8dc511bda 100644 --- a/e2e/cli/e2e-npm7/ping.spec.ts +++ b/e2e/cli/e2e-npm7/ping.spec.ts @@ -1,25 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runPing } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('ping registry', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should ping registry', async () => { - const resp = await npm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); - }); - - afterAll(async () => { - registry.stop(); - }); + runPing(npm); }); diff --git a/e2e/cli/e2e-npm7/publish.spec.ts b/e2e/cli/e2e-npm7/publish.spec.ts index 0d354056f..d5efcc78e 100644 --- a/e2e/cli/e2e-npm7/publish.spec.ts +++ b/e2e/cli/e2e-npm7/publish.spec.ts @@ -1,42 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runPublish } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( - 'should publish a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - const resp = await npm( - { cwd: tempFolder }, - 'publish', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual(pkgName); - expect(parsedBody.files).toBeDefined(); - expect(parsedBody.files).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('publish a package', () => { + runPublish(npm); }); diff --git a/e2e/cli/e2e-npm7/search.spec.ts b/e2e/cli/e2e-npm7/search.spec.ts index 000adf39e..1f76a0956 100644 --- a/e2e/cli/e2e-npm7/search.spec.ts +++ b/e2e/cli/e2e-npm7/search.spec.ts @@ -1,34 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runSearch } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('search a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should search a package', async () => { - const resp = await npm( - {}, - 'search', - '@verdaccio/cli', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - const pkgFind = parsedBody.find((item) => { - return item.name === '@verdaccio/cli'; - }); - expect(pkgFind.name).toEqual('@verdaccio/cli'); - }); - - afterAll(async () => { - registry.stop(); - }); + runSearch(npm); }); diff --git a/e2e/cli/e2e-npm7/star.spec.ts b/e2e/cli/e2e-npm7/star.spec.ts index 0400ed8e9..4d3bda09e 100644 --- a/e2e/cli/e2e-npm7/star.spec.ts +++ b/e2e/cli/e2e-npm7/star.spec.ts @@ -1,86 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runStar } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('star a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - }); - - test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - - const resp1 = await npm( - { cwd: tempFolder }, - 'unstar', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp1.stdout).toEqual(`☆ ${pkgName}`); - }); - - test('should list stars of a user %s', async () => { - const pkgName = '@verdaccio/stars'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); - const resp = await npm({ cwd: tempFolder }, 'stars', ...addRegistry(registry.getRegistryUrl())); - // side effects: this result is affected the the package published in the previous step - expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); - }); - - afterAll(async () => { - registry.stop(); - }); + runStar(npm); }); diff --git a/e2e/cli/e2e-npm7/unpublish.spec.ts b/e2e/cli/e2e-npm7/unpublish.spec.ts new file mode 100644 index 000000000..901867976 --- /dev/null +++ b/e2e/cli/e2e-npm7/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-npm-common'; + +import { npm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(npm); +}); diff --git a/e2e/cli/e2e-npm8/audit.spec.ts b/e2e/cli/e2e-npm8/audit.spec.ts index ad1e34dae..f54f74666 100644 --- a/e2e/cli/e2e-npm8/audit.spec.ts +++ b/e2e/cli/e2e-npm8/audit.spec.ts @@ -1,45 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runAudit } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('audit a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', '@verdaccio/cli']])( - 'should audit a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { jquery: '3.6.1' } - ); - // install is required to create package lock file - await npm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); - const resp = await npm( - { cwd: tempFolder }, - 'audit', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.metadata).toBeDefined(); - expect(parsedBody.auditReportVersion).toBeDefined(); - expect(parsedBody.vulnerabilities).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runAudit(npm); }); diff --git a/e2e/cli/e2e-npm8/deprecate.spec.ts b/e2e/cli/e2e-npm8/deprecate.spec.ts index 6aaef6ce0..8ff989f1d 100644 --- a/e2e/cli/e2e-npm8/deprecate.spec.ts +++ b/e2e/cli/e2e-npm8/deprecate.spec.ts @@ -1,116 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDeprecate } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('deprecate a package', () => { - let registry; - - async function deprecate(tempFolder, packageVersion, registry, message) { - await npm( - { cwd: tempFolder }, - 'deprecate', - packageVersion, - message, - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - } - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/deprecated-1']])( - 'should deprecate a single package %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.name).toEqual(pkgName); - expect(infoBody.deprecated).toEqual(message); - } - ); - - test.each([['@verdaccio/deprecated-2']])('should un-deprecate a package %s', async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.deprecated).toEqual(message); - // empty string is same as undeprecate - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); - const infoBody2 = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody2.deprecated).toBeUndefined(); - }); - - test.each([['@verdaccio/deprecated-3']])( - 'should deprecate a multiple packages %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - // publish 1.0.0 - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.1.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.2.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.3.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // // deprecate all version - await deprecate(tempFolder, pkgName, registry, message); - // verify is deprecated - for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@${v}`, registry); - expect(infoResp.deprecated).toEqual(message); - } - // publish normal version - // publish 1.4.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@1.4.0`, registry); - // must be not deprecated - expect(infoResp.deprecated).toBeUndefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runDeprecate(npm); }); diff --git a/e2e/cli/e2e-npm8/dist-tags.spec.ts b/e2e/cli/e2e-npm8/dist-tags.spec.ts index 007d7370a..7a55089be 100644 --- a/e2e/cli/e2e-npm8/dist-tags.spec.ts +++ b/e2e/cli/e2e-npm8/dist-tags.spec.ts @@ -1,92 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDistTag } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'ls', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); - }); - - test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'rm', - `${pkgName}@1.1.0`, - 'beta', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); - }); - - test.each([['@verdaccio/five']])( - 'should add tag to package and version with dist-tags for %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'add', - `${pkgName}@1.1.0`, - 'alfa', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('dist-tags a package', () => { + runDistTag(npm); }); diff --git a/e2e/cli/e2e-npm8/info.spec.ts b/e2e/cli/e2e-npm8/info.spec.ts index 2964174c1..d110bebfb 100644 --- a/e2e/cli/e2e-npm8/info.spec.ts +++ b/e2e/cli/e2e-npm8/info.spec.ts @@ -1,32 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runInfo } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm info json body', async () => { - const resp = await npm( - {}, - 'info', - 'verdaccio', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual('verdaccio'); - expect(parsedBody.dependencies).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); +describe('info a package', () => { + runInfo(npm); }); diff --git a/e2e/cli/e2e-npm8/install.spec.ts b/e2e/cli/e2e-npm8/install.spec.ts index badcc90dc..8737ecc42 100644 --- a/e2e/cli/e2e-npm8/install.spec.ts +++ b/e2e/cli/e2e-npm8/install.spec.ts @@ -1,39 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runInstall } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('install a project packages', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm install json body', async () => { - const { tempFolder } = await prepareGenericEmptyProject( - 'something', - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { react: '18.2.0' } - ); - const resp = await npm( - { cwd: tempFolder }, - 'install', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.added).toBeDefined(); - expect(parsedBody.audit).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); + runInstall(npm); }); diff --git a/e2e/cli/e2e-npm8/package.json b/e2e/cli/e2e-npm8/package.json index 7fcee3cf3..8fdd7484a 100644 --- a/e2e/cli/e2e-npm8/package.json +++ b/e2e/cli/e2e-npm8/package.json @@ -4,7 +4,8 @@ "version": "1.0.2-next-8.0", "dependencies": { "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", - "npm": "9.9.3" + "@verdaccio/e2e-cli-npm-common": "workspace:*", + "npm": "8.19.4" }, "scripts": { "test": "vitest run --testTimeout 50000" diff --git a/e2e/cli/e2e-npm8/ping.spec.ts b/e2e/cli/e2e-npm8/ping.spec.ts index 7690fa9d6..8dc511bda 100644 --- a/e2e/cli/e2e-npm8/ping.spec.ts +++ b/e2e/cli/e2e-npm8/ping.spec.ts @@ -1,25 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runPing } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('ping registry', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should ping registry', async () => { - const resp = await npm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); - }); - - afterAll(async () => { - registry.stop(); - }); + runPing(npm); }); diff --git a/e2e/cli/e2e-npm8/publish.spec.ts b/e2e/cli/e2e-npm8/publish.spec.ts index 0d354056f..d5efcc78e 100644 --- a/e2e/cli/e2e-npm8/publish.spec.ts +++ b/e2e/cli/e2e-npm8/publish.spec.ts @@ -1,42 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runPublish } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( - 'should publish a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - const resp = await npm( - { cwd: tempFolder }, - 'publish', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual(pkgName); - expect(parsedBody.files).toBeDefined(); - expect(parsedBody.files).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('publish a package', () => { + runPublish(npm); }); diff --git a/e2e/cli/e2e-npm8/search.spec.ts b/e2e/cli/e2e-npm8/search.spec.ts index 000adf39e..1f76a0956 100644 --- a/e2e/cli/e2e-npm8/search.spec.ts +++ b/e2e/cli/e2e-npm8/search.spec.ts @@ -1,34 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runSearch } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('search a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should search a package', async () => { - const resp = await npm( - {}, - 'search', - '@verdaccio/cli', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - const pkgFind = parsedBody.find((item) => { - return item.name === '@verdaccio/cli'; - }); - expect(pkgFind.name).toEqual('@verdaccio/cli'); - }); - - afterAll(async () => { - registry.stop(); - }); + runSearch(npm); }); diff --git a/e2e/cli/e2e-npm8/star.spec.ts b/e2e/cli/e2e-npm8/star.spec.ts index 0400ed8e9..4d3bda09e 100644 --- a/e2e/cli/e2e-npm8/star.spec.ts +++ b/e2e/cli/e2e-npm8/star.spec.ts @@ -1,86 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runStar } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('star a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - }); - - test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - - const resp1 = await npm( - { cwd: tempFolder }, - 'unstar', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp1.stdout).toEqual(`☆ ${pkgName}`); - }); - - test('should list stars of a user %s', async () => { - const pkgName = '@verdaccio/stars'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); - const resp = await npm({ cwd: tempFolder }, 'stars', ...addRegistry(registry.getRegistryUrl())); - // side effects: this result is affected the the package published in the previous step - expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); - }); - - afterAll(async () => { - registry.stop(); - }); + runStar(npm); }); diff --git a/e2e/cli/e2e-npm8/unpublish.spec.ts b/e2e/cli/e2e-npm8/unpublish.spec.ts new file mode 100644 index 000000000..901867976 --- /dev/null +++ b/e2e/cli/e2e-npm8/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-npm-common'; + +import { npm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(npm); +}); diff --git a/e2e/cli/e2e-npm9/audit.spec.ts b/e2e/cli/e2e-npm9/audit.spec.ts index ad1e34dae..f54f74666 100644 --- a/e2e/cli/e2e-npm9/audit.spec.ts +++ b/e2e/cli/e2e-npm9/audit.spec.ts @@ -1,45 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runAudit } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('audit a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', '@verdaccio/cli']])( - 'should audit a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { jquery: '3.6.1' } - ); - // install is required to create package lock file - await npm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); - const resp = await npm( - { cwd: tempFolder }, - 'audit', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.metadata).toBeDefined(); - expect(parsedBody.auditReportVersion).toBeDefined(); - expect(parsedBody.vulnerabilities).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runAudit(npm); }); diff --git a/e2e/cli/e2e-npm9/deprecate.spec.ts b/e2e/cli/e2e-npm9/deprecate.spec.ts index 6aaef6ce0..8ff989f1d 100644 --- a/e2e/cli/e2e-npm9/deprecate.spec.ts +++ b/e2e/cli/e2e-npm9/deprecate.spec.ts @@ -1,116 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDeprecate } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('deprecate a package', () => { - let registry; - - async function deprecate(tempFolder, packageVersion, registry, message) { - await npm( - { cwd: tempFolder }, - 'deprecate', - packageVersion, - message, - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - } - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/deprecated-1']])( - 'should deprecate a single package %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.name).toEqual(pkgName); - expect(infoBody.deprecated).toEqual(message); - } - ); - - test.each([['@verdaccio/deprecated-2']])('should un-deprecate a package %s', async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody.deprecated).toEqual(message); - // empty string is same as undeprecate - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); - const infoBody2 = await npmUtils.getInfoVersions(npm, `${pkgName}`, registry); - expect(infoBody2.deprecated).toBeUndefined(); - }); - - test.each([['@verdaccio/deprecated-3']])( - 'should deprecate a multiple packages %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - // publish 1.0.0 - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.1.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.2.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // publish 1.3.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - // // deprecate all version - await deprecate(tempFolder, pkgName, registry, message); - // verify is deprecated - for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@${v}`, registry); - expect(infoResp.deprecated).toEqual(message); - } - // publish normal version - // publish 1.4.0 - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const infoResp = await npmUtils.getInfoVersions(npm, `${pkgName}@1.4.0`, registry); - // must be not deprecated - expect(infoResp.deprecated).toBeUndefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runDeprecate(npm); }); diff --git a/e2e/cli/e2e-npm9/dist-tags.spec.ts b/e2e/cli/e2e-npm9/dist-tags.spec.ts index 007d7370a..7a55089be 100644 --- a/e2e/cli/e2e-npm9/dist-tags.spec.ts +++ b/e2e/cli/e2e-npm9/dist-tags.spec.ts @@ -1,92 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDistTag } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'ls', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); - }); - - test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'rm', - `${pkgName}@1.1.0`, - 'beta', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); - }); - - test.each([['@verdaccio/five']])( - 'should add tag to package and version with dist-tags for %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npmUtils.bumbUp(npm, tempFolder, registry); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp2 = await npm( - { cwd: tempFolder }, - 'dist-tag', - 'add', - `${pkgName}@1.1.0`, - 'alfa', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('dist-tags a package', () => { + runDistTag(npm); }); diff --git a/e2e/cli/e2e-npm9/info.spec.ts b/e2e/cli/e2e-npm9/info.spec.ts index 2964174c1..d110bebfb 100644 --- a/e2e/cli/e2e-npm9/info.spec.ts +++ b/e2e/cli/e2e-npm9/info.spec.ts @@ -1,32 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runInfo } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm info json body', async () => { - const resp = await npm( - {}, - 'info', - 'verdaccio', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual('verdaccio'); - expect(parsedBody.dependencies).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); +describe('info a package', () => { + runInfo(npm); }); diff --git a/e2e/cli/e2e-npm9/install.spec.ts b/e2e/cli/e2e-npm9/install.spec.ts index badcc90dc..8737ecc42 100644 --- a/e2e/cli/e2e-npm9/install.spec.ts +++ b/e2e/cli/e2e-npm9/install.spec.ts @@ -1,39 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runInstall } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('install a project packages', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm install json body', async () => { - const { tempFolder } = await prepareGenericEmptyProject( - 'something', - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { react: '18.2.0' } - ); - const resp = await npm( - { cwd: tempFolder }, - 'install', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.added).toBeDefined(); - expect(parsedBody.audit).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); + runInstall(npm); }); diff --git a/e2e/cli/e2e-npm9/package.json b/e2e/cli/e2e-npm9/package.json index 75f1dc897..e5b9aa08e 100644 --- a/e2e/cli/e2e-npm9/package.json +++ b/e2e/cli/e2e-npm9/package.json @@ -4,6 +4,7 @@ "version": "1.0.2-next-8.0", "dependencies": { "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", + "@verdaccio/e2e-cli-npm-common": "workspace:*", "npm": "9.9.3" }, "scripts": { diff --git a/e2e/cli/e2e-npm9/ping.spec.ts b/e2e/cli/e2e-npm9/ping.spec.ts index 7690fa9d6..8dc511bda 100644 --- a/e2e/cli/e2e-npm9/ping.spec.ts +++ b/e2e/cli/e2e-npm9/ping.spec.ts @@ -1,25 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runPing } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('ping registry', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should ping registry', async () => { - const resp = await npm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); - }); - - afterAll(async () => { - registry.stop(); - }); + runPing(npm); }); diff --git a/e2e/cli/e2e-npm9/publish.spec.ts b/e2e/cli/e2e-npm9/publish.spec.ts index 0d354056f..d5efcc78e 100644 --- a/e2e/cli/e2e-npm9/publish.spec.ts +++ b/e2e/cli/e2e-npm9/publish.spec.ts @@ -1,42 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runPublish } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( - 'should publish a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - const resp = await npm( - { cwd: tempFolder }, - 'publish', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual(pkgName); - expect(parsedBody.files).toBeDefined(); - expect(parsedBody.files).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('publish a package', () => { + runPublish(npm); }); diff --git a/e2e/cli/e2e-npm9/search.spec.ts b/e2e/cli/e2e-npm9/search.spec.ts index 000adf39e..1f76a0956 100644 --- a/e2e/cli/e2e-npm9/search.spec.ts +++ b/e2e/cli/e2e-npm9/search.spec.ts @@ -1,34 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runSearch } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('search a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should search a package', async () => { - const resp = await npm( - {}, - 'search', - '@verdaccio/cli', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - const pkgFind = parsedBody.find((item) => { - return item.name === '@verdaccio/cli'; - }); - expect(pkgFind.name).toEqual('@verdaccio/cli'); - }); - - afterAll(async () => { - registry.stop(); - }); + runSearch(npm); }); diff --git a/e2e/cli/e2e-npm9/star.spec.ts b/e2e/cli/e2e-npm9/star.spec.ts index 0400ed8e9..4d3bda09e 100644 --- a/e2e/cli/e2e-npm9/star.spec.ts +++ b/e2e/cli/e2e-npm9/star.spec.ts @@ -1,86 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - npmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runStar } from '@verdaccio/e2e-cli-npm-common'; import { npm } from './utils'; describe('star a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - }); - - test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await npmUtils.publish(npm, tempFolder, pkgName, registry); - const resp = await npm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - - const resp1 = await npm( - { cwd: tempFolder }, - 'unstar', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp1.stdout).toEqual(`☆ ${pkgName}`); - }); - - test('should list stars of a user %s', async () => { - const pkgName = '@verdaccio/stars'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await npmUtils.publish(npm, tempFolder, pkgName, registry); - await npm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); - const resp = await npm({ cwd: tempFolder }, 'stars', ...addRegistry(registry.getRegistryUrl())); - // side effects: this result is affected the the package published in the previous step - expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); - }); - - afterAll(async () => { - registry.stop(); - }); + runStar(npm); }); diff --git a/e2e/cli/e2e-npm9/unpublish.spec.ts b/e2e/cli/e2e-npm9/unpublish.spec.ts new file mode 100644 index 000000000..901867976 --- /dev/null +++ b/e2e/cli/e2e-npm9/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-npm-common'; + +import { npm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(npm); +}); diff --git a/e2e/cli/e2e-pnpm-commons/.babelrc b/e2e/cli/e2e-pnpm-commons/.babelrc new file mode 100644 index 000000000..851856e59 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "../../../.babelrc" +} diff --git a/e2e/cli/e2e-pnpm-commons/.eslintrc b/e2e/cli/e2e-pnpm-commons/.eslintrc new file mode 100644 index 000000000..eb2ac4c85 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/.eslintrc @@ -0,0 +1,7 @@ +{ + "rules": { + "no-console": 0, + "@typescript-eslint/no-var-requires": 0, + "@typescript-eslint/explicit-member-accessibility": 0 + } +} diff --git a/e2e/cli/e2e-pnpm-commons/CHANGELOG.md b/e2e/cli/e2e-pnpm-commons/CHANGELOG.md new file mode 100644 index 000000000..4ac7ce32b --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/CHANGELOG.md @@ -0,0 +1,8 @@ +# @verdaccio/e2e-cli-pnpm9 + +## 1.0.2-next-8.0 + +### Patch Changes + +- Updated dependencies + - @verdaccio/test-cli-commons@2.0.0-next-8.0 diff --git a/e2e/cli/e2e-pnpm-commons/audit.ts b/e2e/cli/e2e-pnpm-commons/audit.ts new file mode 100644 index 000000000..67ddab9db --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/audit.ts @@ -0,0 +1,46 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +export function runAudit(pnpm) { + describe('audit a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['verdaccio-memory', '@verdaccio/cli']])( + 'should audit a package %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl(), + { jquery: '3.6.1' } + ); + // install is required to create package lock file + await pnpm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); + const resp = await pnpm( + { cwd: tempFolder }, + 'audit', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.metadata).toBeDefined(); + expect(parsedBody.actions).toBeDefined(); + expect(parsedBody.advisories).toBeDefined(); + expect(parsedBody.muted).toBeDefined(); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/deprecate.ts b/e2e/cli/e2e-pnpm-commons/deprecate.ts new file mode 100644 index 000000000..488813ebd --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/deprecate.ts @@ -0,0 +1,119 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + pnpmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runDeprecate(pnpm) { + describe('deprecate a package', () => { + let registry; + + async function deprecate(tempFolder, packageVersion, registry, message) { + await pnpm( + { cwd: tempFolder }, + 'deprecate', + packageVersion, + message, + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + } + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@verdaccio/deprecated-1']])( + 'should deprecate a single package %s', + async (pkgName) => { + const message = 'some message'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + // deprecate one version + await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); + // verify is deprecated + const infoBody = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); + expect(infoBody.name).toEqual(pkgName); + expect(infoBody.deprecated).toEqual(message); + } + ); + + test.each([['@verdaccio/deprecated-2']])( + 'should un-deprecate a package %s', + async (pkgName) => { + const message = 'some message'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + // deprecate one version + await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); + // verify is deprecated + const infoBody = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); + expect(infoBody.deprecated).toEqual(message); + // empty string is same as undeprecate + await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); + const infoBody2 = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); + expect(infoBody2.deprecated).toBeUndefined(); + } + ); + + test.each([['@verdaccio/deprecated-3']])( + 'should deprecate a multiple packages %s', + async (pkgName) => { + const message = 'some message'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + // publish 1.0.0 + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + // publish 1.1.0 + await pnpmUtils.bumbUp(pnpm, tempFolder, registry); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + // publish 1.2.0 + await pnpmUtils.bumbUp(pnpm, tempFolder, registry); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + // publish 1.3.0 + await pnpmUtils.bumbUp(pnpm, tempFolder, registry); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + // // deprecate all version + await deprecate(tempFolder, pkgName, registry, message); + // verify is deprecated + for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { + const infoResp = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}@${v}`, registry); + expect(infoResp.deprecated).toEqual(message); + } + // publish normal version + // publish 1.4.0 + await pnpmUtils.bumbUp(pnpm, tempFolder, registry); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + const infoResp = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}@1.4.0`, registry); + // must be not deprecated + expect(infoResp.deprecated).toBeUndefined(); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/dist-tags.ts b/e2e/cli/e2e-pnpm-commons/dist-tags.ts new file mode 100644 index 000000000..50da5f22e --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/dist-tags.ts @@ -0,0 +1,92 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + pnpmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runDistTag(pnpm) { + describe('publish a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + await pnpmUtils.bumbUp(pnpm, tempFolder, registry); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry, ['--tag', 'beta']); + const resp2 = await pnpm( + { cwd: tempFolder }, + 'dist-tag', + 'ls', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); + }); + + test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + await pnpmUtils.bumbUp(pnpm, tempFolder, registry); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry, ['--tag', 'beta']); + const resp2 = await pnpm( + { cwd: tempFolder }, + 'dist-tag', + 'rm', + `${pkgName}@1.1.0`, + 'beta', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); + }); + + test.each([['@verdaccio/five']])( + 'should add tag to package and version with dist-tags for %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + await pnpmUtils.bumbUp(pnpm, tempFolder, registry); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + const resp2 = await pnpm( + { cwd: tempFolder }, + 'dist-tag', + 'add', + `${pkgName}@1.1.0`, + 'alfa', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/index.ts b/e2e/cli/e2e-pnpm-commons/index.ts new file mode 100644 index 000000000..8bd4f181d --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/index.ts @@ -0,0 +1,10 @@ +export { runAudit } from './audit'; +export { runDeprecate } from './deprecate'; +export { runInstall } from './install'; +export { runInfo } from './info'; +export { runPing } from './ping'; +export { runPublish } from './publish'; +export { runSearch } from './search'; +export { runStar } from './star'; +export { runUnpublish } from './unpublish'; +export { runDistTag } from './dist-tags'; diff --git a/e2e/cli/e2e-pnpm-commons/info.ts b/e2e/cli/e2e-pnpm-commons/info.ts new file mode 100644 index 000000000..e9bf344e7 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/info.ts @@ -0,0 +1,32 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; + +export function runInfo(pnpm) { + describe('info a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should run pnpm info json body', async () => { + const resp = await pnpm( + {}, + 'info', + 'verdaccio', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.name).toEqual('verdaccio'); + expect(parsedBody.dependencies).toBeDefined(); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/install.ts b/e2e/cli/e2e-pnpm-commons/install.ts new file mode 100644 index 000000000..1dacfe033 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/install.ts @@ -0,0 +1,37 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +export function runInstall(pnpm) { + describe('install a project packages', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should run npm install json body', async () => { + const { tempFolder } = await prepareGenericEmptyProject( + 'something', + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl(), + { react: '18.2.0' } + ); + const resp = await pnpm( + { cwd: tempFolder }, + 'install', + '--reporter=default', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp.stdout).toMatch(/react/); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/package.json b/e2e/cli/e2e-pnpm-commons/package.json new file mode 100644 index 000000000..509077658 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "name": "@verdaccio/e2e-cli-pnpm-common", + "version": "1.0.2-next-8.0", + "dependencies": { + "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", + "pnpm": "9.0.0-alpha.10" + }, + "main": "index.ts", + "scripts": { + "test": "vitest run --testTimeout 50000" + } +} diff --git a/e2e/cli/e2e-pnpm-commons/ping.ts b/e2e/cli/e2e-pnpm-commons/ping.ts new file mode 100644 index 000000000..a628f0b16 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/ping.ts @@ -0,0 +1,25 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; + +export function runPing(pnpm) { + describe('ping registry', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should ping registry', async () => { + const resp = await pnpm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/publish.ts b/e2e/cli/e2e-pnpm-commons/publish.ts new file mode 100644 index 000000000..e33fd7f81 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/publish.ts @@ -0,0 +1,42 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +export function runPublish(pnpm) { + describe('publish a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( + 'should publish a package %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + const resp = await pnpm( + { cwd: tempFolder }, + 'publish', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.name).toEqual(pkgName); + expect(parsedBody.files).toBeDefined(); + expect(parsedBody.files).toBeDefined(); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/search.ts b/e2e/cli/e2e-pnpm-commons/search.ts new file mode 100644 index 000000000..64079ed07 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/search.ts @@ -0,0 +1,34 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; + +export function runSearch(pnpm) { + describe('search a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should search a package', async () => { + const resp = await pnpm( + {}, + 'search', + '@verdaccio/cli', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + const parsedBody = JSON.parse(resp.stdout as string); + const pkgFind = parsedBody.find((item) => { + return item.name === '@verdaccio/cli'; + }); + expect(pkgFind.name).toEqual('@verdaccio/cli'); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/star.ts b/e2e/cli/e2e-pnpm-commons/star.ts new file mode 100644 index 000000000..bc984b9ed --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/star.ts @@ -0,0 +1,90 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + pnpmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runStar(pnpm) { + describe('star a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + const resp = await pnpm( + { cwd: tempFolder }, + 'star', + pkgName, + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp.stdout).toEqual(`★ ${pkgName}`); + }); + + test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + const resp = await pnpm( + { cwd: tempFolder }, + 'star', + pkgName, + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp.stdout).toEqual(`★ ${pkgName}`); + + const resp1 = await pnpm( + { cwd: tempFolder }, + 'unstar', + pkgName, + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp1.stdout).toEqual(`☆ ${pkgName}`); + }); + + test('should list stars of a user %s', async () => { + const pkgName = '@verdaccio/stars'; + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); + await pnpm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); + const resp = await pnpm( + { cwd: tempFolder }, + 'stars', + ...addRegistry(registry.getRegistryUrl()) + ); + // side effects: this result is affected the the package published in the previous step + expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); + }); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm-commons/tsconfig.json b/e2e/cli/e2e-pnpm-commons/tsconfig.json new file mode 100644 index 000000000..85f4ceca6 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.reference.json", + "references": [ + { + "path": "../cli-commons" + } + ] +} diff --git a/e2e/cli/e2e-pnpm-commons/unpublish.ts b/e2e/cli/e2e-pnpm-commons/unpublish.ts new file mode 100644 index 000000000..fd433d182 --- /dev/null +++ b/e2e/cli/e2e-pnpm-commons/unpublish.ts @@ -0,0 +1,86 @@ +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; + +import { + addRegistry, + initialSetup, + npmUtils, + prepareGenericEmptyProject, +} from '@verdaccio/test-cli-commons'; + +export function runUnpublish(pnpm) { + describe('unpublish a package', () => { + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test.each([['@verdaccio/test1', 'super-package-do-not-exist-spam']])( + 'should unpublish a full package %s', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-beta', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(pnpm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(pnpm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(pnpm, tempFolder, pkgName, registry, ['major']); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + + const resp2 = await pnpm( + { cwd: tempFolder }, + 'unpublish', + pkgName, + '--force', + '--loglevel=info', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('- @verdaccio/test1'); + } + ); + + test.each([['@verdaccio/test1', 'super-package-do-not-exist-spam']])( + 'should unpublish a package %s version', + async (pkgName) => { + const { tempFolder } = await prepareGenericEmptyProject( + pkgName, + '1.0.0-beta', + registry.port, + registry.getToken(), + registry.getRegistryUrl() + ); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(pnpm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(pnpm, tempFolder, pkgName, registry, ['minor']); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + await npmUtils.bumpUpPackage(pnpm, tempFolder, pkgName, registry, ['major']); + await npmUtils.publish(pnpm, tempFolder, pkgName, registry); + + const resp2 = await pnpm( + { cwd: tempFolder }, + 'unpublish', + `${pkgName}@1.0.0-beta`, + '--force', + '--loglevel=info', + '--json', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp2.stdout).toEqual('- @verdaccio/test1@1.0.0-beta'); + } + ); + + afterAll(async () => { + registry.stop(); + }); + }); +} diff --git a/e2e/cli/e2e-pnpm10/.babelrc b/e2e/cli/e2e-pnpm10/.babelrc new file mode 100644 index 000000000..851856e59 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "../../../.babelrc" +} diff --git a/e2e/cli/e2e-pnpm10/.eslintrc b/e2e/cli/e2e-pnpm10/.eslintrc new file mode 100644 index 000000000..eb2ac4c85 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/.eslintrc @@ -0,0 +1,7 @@ +{ + "rules": { + "no-console": 0, + "@typescript-eslint/no-var-requires": 0, + "@typescript-eslint/explicit-member-accessibility": 0 + } +} diff --git a/e2e/cli/e2e-pnpm10/CHANGELOG.md b/e2e/cli/e2e-pnpm10/CHANGELOG.md new file mode 100644 index 000000000..4ac7ce32b --- /dev/null +++ b/e2e/cli/e2e-pnpm10/CHANGELOG.md @@ -0,0 +1,8 @@ +# @verdaccio/e2e-cli-pnpm9 + +## 1.0.2-next-8.0 + +### Patch Changes + +- Updated dependencies + - @verdaccio/test-cli-commons@2.0.0-next-8.0 diff --git a/e2e/cli/e2e-pnpm10/audit.spec.ts b/e2e/cli/e2e-pnpm10/audit.spec.ts new file mode 100644 index 000000000..2b748b924 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/audit.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runAudit } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('audit a package', () => { + runAudit(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/deprecate.spec.ts b/e2e/cli/e2e-pnpm10/deprecate.spec.ts new file mode 100644 index 000000000..2d3f152da --- /dev/null +++ b/e2e/cli/e2e-pnpm10/deprecate.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runDeprecate } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('deprecate a package', () => { + runDeprecate(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/dist-tags.spec.ts b/e2e/cli/e2e-pnpm10/dist-tags.spec.ts new file mode 100644 index 000000000..a1fadc287 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/dist-tags.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runDistTag } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('dist-tags a package', () => { + runDistTag(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/info.spec.ts b/e2e/cli/e2e-pnpm10/info.spec.ts new file mode 100644 index 000000000..e60ae1730 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/info.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runInfo } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('info a package', () => { + runInfo(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/install.spec.ts b/e2e/cli/e2e-pnpm10/install.spec.ts new file mode 100644 index 000000000..7cd30d1dc --- /dev/null +++ b/e2e/cli/e2e-pnpm10/install.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runInstall } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('install a project packages', () => { + runInstall(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/package.json b/e2e/cli/e2e-pnpm10/package.json new file mode 100644 index 000000000..e7384b512 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "name": "@verdaccio/e2e-cli-pnpm10", + "version": "1.0.0", + "dependencies": { + "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", + "@verdaccio/e2e-cli-pnpm-common": "workspace:*", + "pnpm": "10.0.0-alpha.2" + }, + "scripts": { + "test": "vitest run --testTimeout 50000" + } +} diff --git a/e2e/cli/e2e-pnpm10/ping.spec.ts b/e2e/cli/e2e-pnpm10/ping.spec.ts new file mode 100644 index 000000000..0a9b8b601 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/ping.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runPing } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('ping registry', () => { + runPing(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/publish.spec.ts b/e2e/cli/e2e-pnpm10/publish.spec.ts new file mode 100644 index 000000000..bbf2b52c4 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/publish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runPublish } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('publish a package', () => { + runPublish(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/search.spec.ts b/e2e/cli/e2e-pnpm10/search.spec.ts new file mode 100644 index 000000000..dee496292 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/search.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runSearch } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('search a package', () => { + runSearch(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/star.spec.ts b/e2e/cli/e2e-pnpm10/star.spec.ts new file mode 100644 index 000000000..f21a53bbd --- /dev/null +++ b/e2e/cli/e2e-pnpm10/star.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runStar } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('star a package', () => { + runStar(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/tsconfig.json b/e2e/cli/e2e-pnpm10/tsconfig.json new file mode 100644 index 000000000..85f4ceca6 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.reference.json", + "references": [ + { + "path": "../cli-commons" + } + ] +} diff --git a/e2e/cli/e2e-pnpm10/unpublish.spec.ts b/e2e/cli/e2e-pnpm10/unpublish.spec.ts new file mode 100644 index 000000000..c71e2d28d --- /dev/null +++ b/e2e/cli/e2e-pnpm10/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm10/utils.ts b/e2e/cli/e2e-pnpm10/utils.ts new file mode 100644 index 000000000..6906c13d2 --- /dev/null +++ b/e2e/cli/e2e-pnpm10/utils.ts @@ -0,0 +1,12 @@ +import { SpawnOptions } from 'child_process'; +import { join } from 'path'; + +import { exec } from '@verdaccio/test-cli-commons'; + +function getCommand() { + return join(__dirname, './node_modules/.bin/pnpm'); +} + +export function pnpm(options: SpawnOptions, ...args: string[]) { + return exec(options, getCommand(), args); +} diff --git a/e2e/cli/e2e-pnpm8/audit.spec.ts b/e2e/cli/e2e-pnpm8/audit.spec.ts index c9503211f..2b748b924 100644 --- a/e2e/cli/e2e-pnpm8/audit.spec.ts +++ b/e2e/cli/e2e-pnpm8/audit.spec.ts @@ -1,46 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runAudit } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', '@verdaccio/cli']])( - 'should audit a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { jquery: '3.6.1' } - ); - // install is required to create package lock file - await pnpm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); - const resp = await pnpm( - { cwd: tempFolder }, - 'audit', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.metadata).toBeDefined(); - expect(parsedBody.actions).toBeDefined(); - expect(parsedBody.advisories).toBeDefined(); - expect(parsedBody.muted).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('audit a package', () => { + runAudit(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/deprecate.spec.ts b/e2e/cli/e2e-pnpm8/deprecate.spec.ts index b8c07579c..2d3f152da 100644 --- a/e2e/cli/e2e-pnpm8/deprecate.spec.ts +++ b/e2e/cli/e2e-pnpm8/deprecate.spec.ts @@ -1,116 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - pnpmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDeprecate } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('deprecate a package', () => { - let registry; - - async function deprecate(tempFolder, packageVersion, registry, message) { - await pnpm( - { cwd: tempFolder }, - 'deprecate', - packageVersion, - message, - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - } - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/deprecated-1']])( - 'should deprecate a single package %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); - expect(infoBody.name).toEqual(pkgName); - expect(infoBody.deprecated).toEqual(message); - } - ); - - test.each([['@verdaccio/deprecated-2']])('should un-deprecate a package %s', async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); - expect(infoBody.deprecated).toEqual(message); - // empty string is same as undeprecate - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); - const infoBody2 = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); - expect(infoBody2.deprecated).toBeUndefined(); - }); - - test.each([['@verdaccio/deprecated-3']])( - 'should deprecate a multiple packages %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - // publish 1.0.0 - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // publish 1.1.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // publish 1.2.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // publish 1.3.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // // deprecate all version - await deprecate(tempFolder, pkgName, registry, message); - // verify is deprecated - for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { - const infoResp = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}@${v}`, registry); - expect(infoResp.deprecated).toEqual(message); - } - // publish normal version - // publish 1.4.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const infoResp = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}@1.4.0`, registry); - // must be not deprecated - expect(infoResp.deprecated).toBeUndefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runDeprecate(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/dist-tags.spec.ts b/e2e/cli/e2e-pnpm8/dist-tags.spec.ts index b84f9798a..a1fadc287 100644 --- a/e2e/cli/e2e-pnpm8/dist-tags.spec.ts +++ b/e2e/cli/e2e-pnpm8/dist-tags.spec.ts @@ -1,92 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - pnpmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDistTag } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await pnpm( - { cwd: tempFolder }, - 'dist-tag', - 'ls', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); - }); - - test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await pnpm( - { cwd: tempFolder }, - 'dist-tag', - 'rm', - `${pkgName}@1.1.0`, - 'beta', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); - }); - - test.each([['@verdaccio/five']])( - 'should add tag to package and version with dist-tags for %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const resp2 = await pnpm( - { cwd: tempFolder }, - 'dist-tag', - 'add', - `${pkgName}@1.1.0`, - 'alfa', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('dist-tags a package', () => { + runDistTag(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/info.spec.ts b/e2e/cli/e2e-pnpm8/info.spec.ts index 009846c5b..e60ae1730 100644 --- a/e2e/cli/e2e-pnpm8/info.spec.ts +++ b/e2e/cli/e2e-pnpm8/info.spec.ts @@ -1,32 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runInfo } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run pnpm info json body', async () => { - const resp = await pnpm( - {}, - 'info', - 'verdaccio', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual('verdaccio'); - expect(parsedBody.dependencies).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); +describe('info a package', () => { + runInfo(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/install.spec.ts b/e2e/cli/e2e-pnpm8/install.spec.ts index 5445b92ab..7cd30d1dc 100644 --- a/e2e/cli/e2e-pnpm8/install.spec.ts +++ b/e2e/cli/e2e-pnpm8/install.spec.ts @@ -1,37 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runInstall } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('install a project packages', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm install json body', async () => { - const { tempFolder } = await prepareGenericEmptyProject( - 'something', - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { react: '18.2.0' } - ); - const resp = await pnpm( - { cwd: tempFolder }, - 'install', - '--reporter=default', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toMatch(/react/); - }); - - afterAll(async () => { - registry.stop(); - }); + runInstall(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/package.json b/e2e/cli/e2e-pnpm8/package.json index 7df7be7c8..46391d5ea 100644 --- a/e2e/cli/e2e-pnpm8/package.json +++ b/e2e/cli/e2e-pnpm8/package.json @@ -4,7 +4,8 @@ "version": "1.0.2-next-8.0", "dependencies": { "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", - "pnpm": "8.15.5" + "@verdaccio/e2e-cli-pnpm-common": "workspace:*", + "pnpm": "8.15.9" }, "scripts": { "test": "vitest run --testTimeout 50000" diff --git a/e2e/cli/e2e-pnpm8/ping.spec.ts b/e2e/cli/e2e-pnpm8/ping.spec.ts index dcacb459e..0a9b8b601 100644 --- a/e2e/cli/e2e-pnpm8/ping.spec.ts +++ b/e2e/cli/e2e-pnpm8/ping.spec.ts @@ -1,25 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runPing } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('ping registry', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should ping registry', async () => { - const resp = await pnpm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); - }); - - afterAll(async () => { - registry.stop(); - }); + runPing(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/publish.spec.ts b/e2e/cli/e2e-pnpm8/publish.spec.ts index cf21b5305..bbf2b52c4 100644 --- a/e2e/cli/e2e-pnpm8/publish.spec.ts +++ b/e2e/cli/e2e-pnpm8/publish.spec.ts @@ -1,42 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runPublish } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( - 'should publish a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - const resp = await pnpm( - { cwd: tempFolder }, - 'publish', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual(pkgName); - expect(parsedBody.files).toBeDefined(); - expect(parsedBody.files).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('publish a package', () => { + runPublish(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/search.spec.ts b/e2e/cli/e2e-pnpm8/search.spec.ts index 8bb52d8cc..dee496292 100644 --- a/e2e/cli/e2e-pnpm8/search.spec.ts +++ b/e2e/cli/e2e-pnpm8/search.spec.ts @@ -1,34 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runSearch } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('search a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should search a package', async () => { - const resp = await pnpm( - {}, - 'search', - '@verdaccio/cli', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - const pkgFind = parsedBody.find((item) => { - return item.name === '@verdaccio/cli'; - }); - expect(pkgFind.name).toEqual('@verdaccio/cli'); - }); - - afterAll(async () => { - registry.stop(); - }); + runSearch(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/star.spec.ts b/e2e/cli/e2e-pnpm8/star.spec.ts index d13915430..f21a53bbd 100644 --- a/e2e/cli/e2e-pnpm8/star.spec.ts +++ b/e2e/cli/e2e-pnpm8/star.spec.ts @@ -1,90 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - pnpmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runStar } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('star a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const resp = await pnpm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - }); - - test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const resp = await pnpm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - - const resp1 = await pnpm( - { cwd: tempFolder }, - 'unstar', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp1.stdout).toEqual(`☆ ${pkgName}`); - }); - - test('should list stars of a user %s', async () => { - const pkgName = '@verdaccio/stars'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); - const resp = await pnpm( - { cwd: tempFolder }, - 'stars', - ...addRegistry(registry.getRegistryUrl()) - ); - // side effects: this result is affected the the package published in the previous step - expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); - }); - - afterAll(async () => { - registry.stop(); - }); + runStar(pnpm); }); diff --git a/e2e/cli/e2e-pnpm8/unpublish.spec.ts b/e2e/cli/e2e-pnpm8/unpublish.spec.ts new file mode 100644 index 000000000..c71e2d28d --- /dev/null +++ b/e2e/cli/e2e-pnpm8/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(pnpm); +}); diff --git a/e2e/cli/e2e-pnpm9/audit.spec.ts b/e2e/cli/e2e-pnpm9/audit.spec.ts index c9503211f..2b748b924 100644 --- a/e2e/cli/e2e-pnpm9/audit.spec.ts +++ b/e2e/cli/e2e-pnpm9/audit.spec.ts @@ -1,46 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runAudit } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', '@verdaccio/cli']])( - 'should audit a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { jquery: '3.6.1' } - ); - // install is required to create package lock file - await pnpm({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); - const resp = await pnpm( - { cwd: tempFolder }, - 'audit', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.metadata).toBeDefined(); - expect(parsedBody.actions).toBeDefined(); - expect(parsedBody.advisories).toBeDefined(); - expect(parsedBody.muted).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('audit a package', () => { + runAudit(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/deprecate.spec.ts b/e2e/cli/e2e-pnpm9/deprecate.spec.ts index b8c07579c..2d3f152da 100644 --- a/e2e/cli/e2e-pnpm9/deprecate.spec.ts +++ b/e2e/cli/e2e-pnpm9/deprecate.spec.ts @@ -1,116 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - pnpmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDeprecate } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('deprecate a package', () => { - let registry; - - async function deprecate(tempFolder, packageVersion, registry, message) { - await pnpm( - { cwd: tempFolder }, - 'deprecate', - packageVersion, - message, - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - } - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/deprecated-1']])( - 'should deprecate a single package %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); - expect(infoBody.name).toEqual(pkgName); - expect(infoBody.deprecated).toEqual(message); - } - ); - - test.each([['@verdaccio/deprecated-2']])('should un-deprecate a package %s', async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // deprecate one version - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, message); - // verify is deprecated - const infoBody = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); - expect(infoBody.deprecated).toEqual(message); - // empty string is same as undeprecate - await deprecate(tempFolder, `${pkgName}@1.0.0`, registry, ''); - const infoBody2 = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}`, registry); - expect(infoBody2.deprecated).toBeUndefined(); - }); - - test.each([['@verdaccio/deprecated-3']])( - 'should deprecate a multiple packages %s', - async (pkgName) => { - const message = 'some message'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - // publish 1.0.0 - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // publish 1.1.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // publish 1.2.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // publish 1.3.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - // // deprecate all version - await deprecate(tempFolder, pkgName, registry, message); - // verify is deprecated - for (let v of ['1.0.0', '1.1.0', '1.2.0', '1.3.0']) { - const infoResp = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}@${v}`, registry); - expect(infoResp.deprecated).toEqual(message); - } - // publish normal version - // publish 1.4.0 - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const infoResp = await pnpmUtils.getInfoVersions(pnpm, `${pkgName}@1.4.0`, registry); - // must be not deprecated - expect(infoResp.deprecated).toBeUndefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); + runDeprecate(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/dist-tags.spec.ts b/e2e/cli/e2e-pnpm9/dist-tags.spec.ts index b84f9798a..a1fadc287 100644 --- a/e2e/cli/e2e-pnpm9/dist-tags.spec.ts +++ b/e2e/cli/e2e-pnpm9/dist-tags.spec.ts @@ -1,92 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - pnpmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runDistTag } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('publish a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@foo/foo', 'foo']])('should list dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await pnpm( - { cwd: tempFolder }, - 'dist-tag', - 'ls', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('beta: 1.1.0latest: 1.0.0'); - }); - - test.each([['@verdaccio/bar']])('should remove tag with dist-tags for %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry, ['--tag', 'beta']); - const resp2 = await pnpm( - { cwd: tempFolder }, - 'dist-tag', - 'rm', - `${pkgName}@1.1.0`, - 'beta', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual('-beta: @verdaccio/bar@1.1.0'); - }); - - test.each([['@verdaccio/five']])( - 'should add tag to package and version with dist-tags for %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpmUtils.bumbUp(pnpm, tempFolder, registry); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const resp2 = await pnpm( - { cwd: tempFolder }, - 'dist-tag', - 'add', - `${pkgName}@1.1.0`, - 'alfa', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp2.stdout).toEqual(`+alfa: ${pkgName}@1.1.0`); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('dist-tags a package', () => { + runDistTag(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/info.spec.ts b/e2e/cli/e2e-pnpm9/info.spec.ts index 009846c5b..e60ae1730 100644 --- a/e2e/cli/e2e-pnpm9/info.spec.ts +++ b/e2e/cli/e2e-pnpm9/info.spec.ts @@ -1,32 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runInfo } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run pnpm info json body', async () => { - const resp = await pnpm( - {}, - 'info', - 'verdaccio', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual('verdaccio'); - expect(parsedBody.dependencies).toBeDefined(); - }); - - afterAll(async () => { - registry.stop(); - }); +describe('info a package', () => { + runInfo(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/install.spec.ts b/e2e/cli/e2e-pnpm9/install.spec.ts index 5445b92ab..7cd30d1dc 100644 --- a/e2e/cli/e2e-pnpm9/install.spec.ts +++ b/e2e/cli/e2e-pnpm9/install.spec.ts @@ -1,37 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runInstall } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('install a project packages', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should run npm install json body', async () => { - const { tempFolder } = await prepareGenericEmptyProject( - 'something', - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl(), - { react: '18.2.0' } - ); - const resp = await pnpm( - { cwd: tempFolder }, - 'install', - '--reporter=default', - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toMatch(/react/); - }); - - afterAll(async () => { - registry.stop(); - }); + runInstall(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/package.json b/e2e/cli/e2e-pnpm9/package.json index ea0ebd781..335029297 100644 --- a/e2e/cli/e2e-pnpm9/package.json +++ b/e2e/cli/e2e-pnpm9/package.json @@ -4,7 +4,8 @@ "version": "1.0.2-next-8.0", "dependencies": { "@verdaccio/test-cli-commons": "workspace:2.0.0-next-8.0", - "pnpm": "9.0.0-alpha.10" + "@verdaccio/e2e-cli-pnpm-common": "workspace:*", + "pnpm": "9.13.2" }, "scripts": { "test": "vitest run --testTimeout 50000" diff --git a/e2e/cli/e2e-pnpm9/ping.spec.ts b/e2e/cli/e2e-pnpm9/ping.spec.ts index dcacb459e..0a9b8b601 100644 --- a/e2e/cli/e2e-pnpm9/ping.spec.ts +++ b/e2e/cli/e2e-pnpm9/ping.spec.ts @@ -1,25 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runPing } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('ping registry', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should ping registry', async () => { - const resp = await pnpm({}, 'ping', '--json', ...addRegistry(registry.getRegistryUrl())); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.registry).toEqual(registry.getRegistryUrl() + '/'); - }); - - afterAll(async () => { - registry.stop(); - }); + runPing(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/publish.spec.ts b/e2e/cli/e2e-pnpm9/publish.spec.ts index cf21b5305..bbf2b52c4 100644 --- a/e2e/cli/e2e-pnpm9/publish.spec.ts +++ b/e2e/cli/e2e-pnpm9/publish.spec.ts @@ -1,42 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +import { runPublish } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; -describe('install a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['verdaccio-memory', 'verdaccio', '@verdaccio/foo', '@verdaccio/some-foo']])( - 'should publish a package %s', - async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - const resp = await pnpm( - { cwd: tempFolder }, - 'publish', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - expect(parsedBody.name).toEqual(pkgName); - expect(parsedBody.files).toBeDefined(); - expect(parsedBody.files).toBeDefined(); - } - ); - - afterAll(async () => { - registry.stop(); - }); +describe('publish a package', () => { + runPublish(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/search.spec.ts b/e2e/cli/e2e-pnpm9/search.spec.ts index 8bb52d8cc..dee496292 100644 --- a/e2e/cli/e2e-pnpm9/search.spec.ts +++ b/e2e/cli/e2e-pnpm9/search.spec.ts @@ -1,34 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { addRegistry, initialSetup } from '@verdaccio/test-cli-commons'; +import { runSearch } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('search a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test('should search a package', async () => { - const resp = await pnpm( - {}, - 'search', - '@verdaccio/cli', - '--json', - ...addRegistry(registry.getRegistryUrl()) - ); - const parsedBody = JSON.parse(resp.stdout as string); - const pkgFind = parsedBody.find((item) => { - return item.name === '@verdaccio/cli'; - }); - expect(pkgFind.name).toEqual('@verdaccio/cli'); - }); - - afterAll(async () => { - registry.stop(); - }); + runSearch(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/star.spec.ts b/e2e/cli/e2e-pnpm9/star.spec.ts index d13915430..f21a53bbd 100644 --- a/e2e/cli/e2e-pnpm9/star.spec.ts +++ b/e2e/cli/e2e-pnpm9/star.spec.ts @@ -1,90 +1,9 @@ -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { describe } from 'vitest'; -import { - addRegistry, - initialSetup, - pnpmUtils, - prepareGenericEmptyProject, -} from '@verdaccio/test-cli-commons'; +import { runStar } from '@verdaccio/e2e-cli-pnpm-common'; import { pnpm } from './utils'; describe('star a package', () => { - let registry; - - beforeAll(async () => { - const setup = await initialSetup(); - registry = setup.registry; - await registry.init(); - }); - - test.each([['@verdaccio/foo']])('should star a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const resp = await pnpm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - }); - - test.each([['@verdaccio/bar']])('should unstar a package %s', async (pkgName) => { - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - const resp = await pnpm( - { cwd: tempFolder }, - 'star', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp.stdout).toEqual(`★ ${pkgName}`); - - const resp1 = await pnpm( - { cwd: tempFolder }, - 'unstar', - pkgName, - ...addRegistry(registry.getRegistryUrl()) - ); - expect(resp1.stdout).toEqual(`☆ ${pkgName}`); - }); - - test('should list stars of a user %s', async () => { - const pkgName = '@verdaccio/stars'; - const { tempFolder } = await prepareGenericEmptyProject( - pkgName, - '1.0.0-patch', - registry.port, - registry.getToken(), - registry.getRegistryUrl() - ); - await pnpmUtils.publish(pnpm, tempFolder, pkgName, registry); - await pnpm({ cwd: tempFolder }, 'star', pkgName, ...addRegistry(registry.getRegistryUrl())); - const resp = await pnpm( - { cwd: tempFolder }, - 'stars', - ...addRegistry(registry.getRegistryUrl()) - ); - // side effects: this result is affected the the package published in the previous step - expect(resp.stdout).toEqual(`@verdaccio/foo@verdaccio/stars`); - }); - - afterAll(async () => { - registry.stop(); - }); + runStar(pnpm); }); diff --git a/e2e/cli/e2e-pnpm9/unpublish.spec.ts b/e2e/cli/e2e-pnpm9/unpublish.spec.ts new file mode 100644 index 000000000..c71e2d28d --- /dev/null +++ b/e2e/cli/e2e-pnpm9/unpublish.spec.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest'; + +import { runUnpublish } from '@verdaccio/e2e-cli-pnpm-common'; + +import { pnpm } from './utils'; + +describe('unpublish a package', () => { + runUnpublish(pnpm); +}); diff --git a/packages/api/src/package.ts b/packages/api/src/package.ts index 979732fb2..5da65e500 100644 --- a/packages/api/src/package.ts +++ b/packages/api/src/package.ts @@ -24,13 +24,24 @@ export default function (route: Router, auth: Auth, storage: Storage, logger: Lo _res: $ResponseExtend, next: $NextFunctionVer ): Promise { - debug('init package by version'); + debug('get package by version'); const name = req.params.package; let version = req.params.version; const write = req.query.write === 'true'; const username = req?.remote_user?.name; const abbreviated = stringUtils.getByQualityPriorityValue(req.get('Accept')) === Storage.ABBREVIATED_HEADER; + if (debug.enabled) { + debug('is write %o', write); + debug('is abbreviated %o', abbreviated); + debug('package %o', name); + debug('version %o', version); + debug('username %o', username); + debug('remote address %o', req.socket.remoteAddress); + debug('host %o', req.host); + debug('protocol %o', req.protocol); + debug('url %o', req.url); + } const requestOptions = { protocol: req.protocol, headers: req.headers as any, @@ -50,8 +61,10 @@ export default function (route: Router, auth: Auth, storage: Storage, logger: Lo requestOptions, }); if (abbreviated) { + debug('abbreviated response'); _res.setHeader(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_INSTALL_CHARSET); } else { + debug('full response'); _res.setHeader(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON); } @@ -69,6 +82,7 @@ export default function (route: Router, auth: Auth, storage: Storage, logger: Lo const { package: pkgName, filename } = req.params; const abort = new AbortController(); try { + debug('downloading tarball %o', filename); const stream = (await storage.getTarball(pkgName, filename, { signal: abort.signal, // TODO: review why this param @@ -76,10 +90,12 @@ export default function (route: Router, auth: Auth, storage: Storage, logger: Lo })) as any; stream.on('content-length', (size) => { + debug('tarball size %o', size); res.header(HEADER_TYPE.CONTENT_LENGTH, size); }); stream.once('error', (err) => { + debug('error on download tarball %o', err); res.locals.report_error(err); next(err); }); @@ -92,7 +108,6 @@ export default function (route: Router, auth: Auth, storage: Storage, logger: Lo res.header(HEADERS.CONTENT_TYPE, HEADERS.OCTET_STREAM); stream.pipe(res); } catch (err: any) { - // console.log('catch API error request', err); res.locals.report_error(err); next(err); } diff --git a/packages/api/src/publish.ts b/packages/api/src/publish.ts index d6196ff44..e7cb7bdd3 100644 --- a/packages/api/src/publish.ts +++ b/packages/api/src/publish.ts @@ -73,7 +73,7 @@ const debug = buildDebug('verdaccio:api:publish'); * npm http fetch GET 200 http://localhost:4873/custom-name?write=true 1601ms * Remove the tarball * npm http fetch DELETE 201 http://localhost:4873/custom-name/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms - * + * * 3. Star a package * * Permissions: staring a package depends of the publish and unpublish permissions, there is no @@ -94,7 +94,7 @@ const debug = buildDebug('verdaccio:api:publish'); * 4. Change owners of a package * * Similar to staring a package, changing owners (maintainers) of a package uses the publish - * endpoint. + * endpoint. * * The body includes a list of the new owners with the following format * @@ -124,7 +124,7 @@ export default function publish( can('publish'), media(mime.getType('json')), expectJson, - publishPackage(storage, logger) + publishPackage(storage, logger, 'publish one version') ); router.put( @@ -132,15 +132,24 @@ export default function publish( can('unpublish'), media(mime.getType('json')), expectJson, - publishPackage(storage, logger) + publishPackage(storage, logger, 'publish with revision') ); /** * Un-publishing an entire package. * - * This scenario happens when the first call detect there is only one version remaining - * in the metadata, then the client decides to DELETE the resource + * This scenario happens when any of these scenarios happens: + * - the first call detect there is only one version remaining + * - no version is specified in the unpublish call + * - all versions are removed npm unpublish package@* + * - there is no versions on the metadata + + * then the client decides to DELETE the resource + * Example: + * Get fresh manifest (write=true is a flag to get the latest revision) * npm http fetch GET 304 http://localhost:4873/package-name?write=true 1076ms (from cache) + * Send request to delete the package, this includes the revision number that must match + * and the package name, it will delete the entire package and all tarballs (or tarball depends the scenario) * npm http fetch DELETE 201 http://localhost:4873/package-name/-rev/18-d8ebe3020bd4ac9c 22ms */ router.delete( @@ -200,15 +209,21 @@ export default function publish( ); } -export function publishPackage(storage: Storage, logger: Logger): any { +export function publishPackage(storage: Storage, logger: Logger, origin: string): any { return async function ( req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer ): Promise { + debug(origin); const ac = new AbortController(); const packageName = req.params.package; const { revision } = req.params; + debug('publishing package %s', packageName); + debug('revision %s', revision); + if (debug.enabled) { + debug('body %o', req.body); + } const metadata = req.body; const username = req?.remote_user?.name; @@ -231,6 +246,7 @@ export function publishPackage(storage: Storage, logger: Logger): any { }, uplinksLook: false, }); + debug('package %s published', packageName); res.status(HTTP_STATUS.CREATED); diff --git a/packages/api/test/integration/package.spec.ts b/packages/api/test/integration/package.spec.ts index d189fd32f..76f58b1d1 100644 --- a/packages/api/test/integration/package.spec.ts +++ b/packages/api/test/integration/package.spec.ts @@ -97,8 +97,8 @@ describe('package', () => { expect(response.body.time).toBeDefined(); expect(response.body.modified).toBeDefined(); expect(response.body[DIST_TAGS]).toEqual({ latest: '1.0.0' }); - expect(response.body.readme).not.toBeDefined(); - expect(response.body._rev).not.toBeDefined(); + expect(response.body.readme).toBeDefined(); + expect(response.body._rev).toBeDefined(); expect(response.body.users).not.toBeDefined(); } ); diff --git a/packages/core/core/src/schemes/unpublish-manifest.ts b/packages/core/core/src/schemes/unpublish-manifest.ts new file mode 100644 index 000000000..ca9dda565 --- /dev/null +++ b/packages/core/core/src/schemes/unpublish-manifest.ts @@ -0,0 +1,69 @@ +import Ajv, { JSONSchemaType } from 'ajv'; + +const ajv = new Ajv(); + +interface Manifest { + name: string; + versions: Record; + _rev: string; + _id: string; + time: { + created: string; + modified: string; + [key: string]: string; // Allows pattern properties such as version numbers + }; + readme: string; + 'dist-tags': { + latest: string; + [key: string]: unknown; // Allows additional properties + }; +} + +// @ts-ignore +const schema: JSONSchemaType = { + type: 'object', + properties: { + name: { type: 'string' }, + versions: { type: 'object', minProperties: 1 }, + _rev: { type: 'string' }, + _id: { type: 'string' }, + time: { + type: 'object', + properties: { + created: { type: 'string' }, + modified: { type: 'string' }, + }, + patternProperties: { + '^[0-9]+\\.[0-9]+\\.[0-9]+-\\d+$': { type: 'string' }, + }, + additionalProperties: true, + }, + readme: { type: 'string' }, + 'dist-tags': { + type: 'object', + properties: { + latest: { type: 'string' }, + }, + required: ['latest'], + additionalProperties: true, + }, + }, + required: ['name', 'versions', 'dist-tags', '_rev', '_id', 'readme', 'time'], + additionalProperties: true, +}; + +// validate is a type guard for MyData - type is inferred from schema type +const validate = ajv.compile(schema); + +/** + * Validate if a manifest has the correct structure when a new package + * is being created. The properties name, versions and _attachments must contain 1 element. + * @param data a manifest object + * @returns boolean + */ +export function validateUnPublishSingleVersion(manifest: any) { + if (!manifest) { + return false; + } + return validate(manifest); +} diff --git a/packages/core/core/src/validation-utils.ts b/packages/core/core/src/validation-utils.ts index 3a61bddd4..a277870c6 100644 --- a/packages/core/core/src/validation-utils.ts +++ b/packages/core/core/src/validation-utils.ts @@ -5,6 +5,7 @@ import { Manifest } from '@verdaccio/types'; import { DEFAULT_PASSWORD_VALIDATION, DIST_TAGS, MAINTAINERS } from './constants'; export { validatePublishSingleVersion } from './schemes/publish-manifest'; +export { validateUnPublishSingleVersion } from './schemes/unpublish-manifest'; export function isPackageNameScoped(name: string): boolean { return name.startsWith('@'); diff --git a/packages/core/core/test/publish-manifest.spec.ts b/packages/core/core/test/publish-manifest.spec.ts new file mode 100644 index 000000000..25b1ad433 --- /dev/null +++ b/packages/core/core/test/publish-manifest.spec.ts @@ -0,0 +1,61 @@ +import { describe, expect, test } from 'vitest'; + +import { validatePublishSingleVersion } from '../src/schemes/publish-manifest'; + +describe('validatePublishSingleVersion', () => { + describe('valid cases', () => { + test('should validate a manifest when name and versions are present, even with extra properties', () => { + const manifest = { + name: 'foo-pkg', + _attachments: { '2': {} }, + versions: { '1': {} }, + something: 'else', + }; + expect(validatePublishSingleVersion(manifest)).toBe(true); + }); + }); + + describe('invalid cases', () => { + test('should invalidate a manifest when name is missing', () => { + const manifest = { + _attachments: { '2': {} }, + versions: { '1': {} }, + }; + expect(validatePublishSingleVersion(manifest)).toBe(false); + }); + + test('should invalidate a manifest when _attachments is missing', () => { + const manifest = { + name: 'foo-pkg', + versions: { '1': {} }, + }; + expect(validatePublishSingleVersion(manifest)).toBe(false); + }); + + test('should invalidate a manifest when versions is missing', () => { + const manifest = { + name: 'foo-pkg', + _attachments: { '1': {} }, + }; + expect(validatePublishSingleVersion(manifest)).toBe(false); + }); + + test('should invalidate a manifest when versions contains more than one entry', () => { + const manifest = { + name: 'foo-pkg', + versions: { '1': {}, '2': {} }, + _attachments: { '1': {} }, + }; + expect(validatePublishSingleVersion(manifest)).toBe(false); + }); + + test('should invalidate a manifest when _attachments contains more than one entry', () => { + const manifest = { + name: 'foo-pkg', + _attachments: { '1': {}, '2': {} }, + versions: { '1': {} }, + }; + expect(validatePublishSingleVersion(manifest)).toBe(false); + }); + }); +}); diff --git a/packages/core/core/test/unpublish-manifest.spec.ts b/packages/core/core/test/unpublish-manifest.spec.ts new file mode 100644 index 000000000..8fe7e3ac4 --- /dev/null +++ b/packages/core/core/test/unpublish-manifest.spec.ts @@ -0,0 +1,71 @@ +import { describe, expect, it } from 'vitest'; + +import { validateUnPublishSingleVersion } from '../src/schemes/unpublish-manifest'; + +describe('validatePublishSingleVersion', () => { + it('should validate a valid manifest correctly', () => { + const validManifest = { + name: '@juanpicado/test2', + versions: { + '3.0.2-0': { + name: '@juanpicado/test2', + }, + }, + _rev: '9-17c706cc377dc959', + _id: '@juanpicado/test2', + time: { + created: '2024-11-02T14:33:06.170Z', + modified: '2024-11-02T14:33:22.919Z', + '3.0.2-0': '2024-11-02T14:33:06.208Z', + '3.0.3-0': '2024-11-02T14:33:19.520Z', + }, + readme: 'ERROR: No README data found!', + 'dist-tags': { + latest: '3.0.3-0', + }, + }; + + const result = validateUnPublishSingleVersion(validManifest); + expect(result).toBe(true); + }); + + it('should invalidate a manifest missing required properties', () => { + const invalidManifest = { + name: '@juanpicado/test2', + versions: { + '3.0.2-0': { + name: '@juanpicado/test2', + }, + }, + }; + + const result = validateUnPublishSingleVersion(invalidManifest); + expect(result).toBe(false); + }); + + it('should invalidate a manifest with empty versions object', () => { + const invalidManifest = { + name: '@juanpicado/test2', + versions: {}, + _rev: '9-17c706cc377dc959', + _id: '@juanpicado/test2', + time: { + created: '2024-11-02T14:33:06.170Z', + modified: '2024-11-02T14:33:22.919Z', + '3.0.2-0': '2024-11-02T14:33:06.208Z', + }, + readme: 'ERROR: No README data found!', + 'dist-tags': { + latest: '3.0.3-0', + }, + }; + + const result = validateUnPublishSingleVersion(invalidManifest); + expect(result).toBe(false); + }); + + it('should invalidate a null manifest', () => { + const result = validateUnPublishSingleVersion(null); + expect(result).toBe(false); + }); +}); diff --git a/packages/core/core/test/validation-utilts.spec.ts b/packages/core/core/test/validation-utilts.spec.ts index 81d323a26..fe09f7d7e 100644 --- a/packages/core/core/test/validation-utilts.spec.ts +++ b/packages/core/core/test/validation-utilts.spec.ts @@ -1,7 +1,6 @@ import { describe, expect, test } from 'vitest'; import { DEFAULT_PASSWORD_VALIDATION, DIST_TAGS } from '../src/constants'; -import { validatePublishSingleVersion } from '../src/schemes/publish-manifest'; import { isObject, normalizeMetadata, @@ -118,65 +117,6 @@ describe('validateName', () => { }); }); -describe('validatePublishSingleVersion', () => { - test('should be valid', () => { - expect( - validatePublishSingleVersion({ - name: 'foo-pkg', - _attachments: { '2': {} }, - versions: { '1': {} }, - }) - ).toBeTruthy(); - }); - - test('should be invalid if name is missing', () => { - expect( - validatePublishSingleVersion({ - _attachments: { '2': {} }, - versions: { '1': {} }, - }) - ).toBeFalsy(); - }); - - test('should be invalid if _attachments is missing', () => { - expect( - validatePublishSingleVersion({ - name: 'foo-pkg', - versions: { '1': {} }, - }) - ).toBeFalsy(); - }); - - test('should be invalid if versions is missing', () => { - expect( - validatePublishSingleVersion({ - name: 'foo-pkg', - _attachments: { '1': {} }, - }) - ).toBeFalsy(); - }); - - test('should be invalid if versions is more than 1', () => { - expect( - validatePublishSingleVersion({ - name: 'foo-pkg', - versions: { '1': {}, '2': {} }, - _attachments: { '1': {} }, - }) - ).toBeFalsy(); - }); - - test('should be invalid if _attachments is more than 1', () => { - expect( - validatePublishSingleVersion({ - name: 'foo-pkg', - _attachments: { '1': {}, '2': {} }, - versions: { '1': {} }, - }) - ).toBeFalsy(); - }); -}); - describe('validatePassword', () => { test('should validate password according the length', () => { expect(validatePassword('12345', DEFAULT_PASSWORD_VALIDATION)).toBeTruthy(); diff --git a/packages/core/types/src/manifest.ts b/packages/core/types/src/manifest.ts index 03721f464..658062d11 100644 --- a/packages/core/types/src/manifest.ts +++ b/packages/core/types/src/manifest.ts @@ -255,6 +255,11 @@ export type AbbreviatedManifest = Pick versions: AbbreviatedVersions; }; +/** + * + */ +export type UnPublishManifest = Omit; + export interface PublishManifest { /** * The `_attachments` object has different usages: diff --git a/packages/store/src/storage.ts b/packages/store/src/storage.ts index 14b4a710f..3ef71bde8 100644 --- a/packages/store/src/storage.ts +++ b/packages/store/src/storage.ts @@ -56,6 +56,7 @@ import { StringValue, Token, TokenFilter, + UnPublishManifest, Version, } from '@verdaccio/types'; import { createTarballHash, isObject, normalizeContributors } from '@verdaccio/utils'; @@ -452,7 +453,7 @@ class Storage { } // we have version, so we need to return specific version - const [convertedManifest] = await this.getPackageNext(options); + const [convertedManifest] = await this.getPackage(options); const version: Version | undefined = getVersion(convertedManifest.versions, queryVersion); @@ -499,7 +500,7 @@ class Storage { public async getPackageManifest(options: IGetPackageOptionsNext): Promise { // convert dist remotes to local bars - const [manifest] = await this.getPackageNext(options); + const [manifest] = await this.getPackage(options); // If change access is requested (?write=true), then check if logged in user is allowed to change package if (options.byPassCache === true) { @@ -560,6 +561,11 @@ class Storage { modified: manifest.time.modified, // NOTE: special case for pnpm https://github.com/pnpm/rfcs/pull/2 time: manifest.time, + _id: manifest._id, + readme: manifest.readme, + // TODO: not sure if this is used in some way + readmeFilename: '', + _rev: manifest._rev, }; return convertedManifest; @@ -575,11 +581,13 @@ class Storage { ): Promise { // if no version we return the whole manifest if (_.isNil(options.version) === false) { + debug('get package by version %o', options.version); return this.getPackageByVersion(options); } else { + debug('get full package manifest'); const manifest = await this.getPackageManifest(options); if (options.abbreviated === true) { - debug('abbreviated manifest'); + debug('get abbreviated manifest'); return this.convertAbbreviatedManifest(manifest); } return manifest; @@ -910,11 +918,12 @@ class Storage { } public async updateManifest( - manifest: Manifest | StarManifestBody | OwnerManifestBody, + manifest: Manifest | StarManifestBody | OwnerManifestBody | UnPublishManifest, options: UpdateManifestOptions ): Promise { debug('update manifest %o for user %o', manifest._id, options.requestOptions.username); if (isDeprecatedManifest(manifest as Manifest)) { + debug('update manifest deprecate'); // if the manifest is deprecated, we need to update the package.json await this.deprecate(manifest as Manifest, { ...options, @@ -923,6 +932,7 @@ class Storage { isPublishablePackage(manifest as Manifest) === false && validatioUtils.isObject((manifest as StarManifestBody).users) ) { + debug('update manifest star'); // if user request to apply a star to the manifest await this.star(manifest as StarManifestBody, { ...options, @@ -932,6 +942,7 @@ class Storage { isPublishablePackage(manifest as Manifest) === false && Array.isArray((manifest as OwnerManifestBody).maintainers) ) { + debug('update manifest owners'); // if user request to change owners of package await this.changeOwners(manifest as OwnerManifestBody, { ...options, @@ -940,6 +951,7 @@ class Storage { } else if (validatioUtils.validatePublishSingleVersion(manifest)) { // if continue, the version to be published does not exist // we create a new package + debug('publish a new version'); const [mergedManifest, version, message] = await this.publishANewVersion( manifest as Manifest, { @@ -955,6 +967,12 @@ class Storage { this.logger.error({ error: error.message }, 'notify batch service has failed: @{error}'); } return message; + } else if (validatioUtils.validateUnPublishSingleVersion(manifest)) { + debug('unpublish a version'); + + await this.unPublishAPackage(manifest as UnPublishManifest, { + ...options, + }); } else { debug('invalid body format'); this.logger.warn( @@ -1018,6 +1036,22 @@ class Storage { return API_MESSAGE.PKG_CHANGED; } + private async unPublishAPackage(manifest: UnPublishManifest, options: UpdateManifestOptions) { + const { requestOptions, name } = options; + debug('unpublish a package of %o', name); + + const localPackage = await this.getPackageManifest({ + name, + requestOptions, + uplinksLook: false, + }); + if (localPackage._rev === manifest._rev) { + await this.changePackage(name, manifest as Manifest, options.revision as string); + } + + return API_MESSAGE.PKG_CHANGED; + } + private async changeOwners( manifest: OwnerManifestBody, options: UpdateManifestOptions @@ -1054,7 +1088,7 @@ class Storage { * @param name * @returns */ - private async getPackagelocalByNameNext(name: string): Promise { + private async getPackagelocalByName(name: string): Promise { try { return await this.getPackageLocalMetadata(name); } catch (err: any) { @@ -1116,6 +1150,7 @@ class Storage { // versions is need it for holding the version in the local storage as file // _attachments and validation are required otherwise cannot continue. if (isEmpty(_attachments)) { + debug('attachments are empty, cannot continue'); throw errorUtils.getBadRequest(API_ERROR.UNSUPORTED_REGISTRY_CALL); } @@ -1128,7 +1163,7 @@ class Storage { try { // we check if package exist already locally - const localManifest = await this.getPackagelocalByNameNext(name); + const localManifest = await this.getPackagelocalByName(name); // if continue, the version to be published does not exist if (localManifest?.versions[versionToPublish] != null) { debug('%s version %s already exists (locally)', name, versionToPublish); @@ -1217,12 +1252,6 @@ class Storage { return; } - private getProxyList() { - const uplinksList = Object.keys(this.uplinks); - - return uplinksList; - } - /** * Wrap uploadTarballAsStream into a promise. * @param name package name @@ -1472,8 +1501,10 @@ class Storage { } const currentTime = new Date().toISOString(); + const defaultManifest = generatePackageTemplate(name); const packageData: Manifest = { - ...generatePackageTemplate(name), + ...defaultManifest, + _rev: generateRevision(defaultManifest._rev), time: { created: currentTime, modified: currentTime, @@ -1608,7 +1639,7 @@ class Storage { * @return {*} {Promise<[Manifest, any[]]>} * @memberof AbstractStorage */ - private async getPackageNext(options: IGetPackageOptionsNext): Promise<[Manifest, any[]]> { + private async getPackage(options: IGetPackageOptionsNext): Promise<[Manifest, any[]]> { const { name } = options; debug('get package for %o', name); let data: Manifest | null = null; @@ -1855,7 +1886,7 @@ class Storage { return [filteredManifest, filterPluginErrors]; } - private _createNewPackageNext(name: string): Manifest { + private _createNewPackage(name: string): Manifest { return normalizePackage(generatePackageTemplate(name)); } @@ -1901,7 +1932,7 @@ class Storage { return normalizePackage(result); } catch (err: any) { if (err.code === STORAGE.NO_SUCH_FILE_ERROR || err.code === HTTP_STATUS.NOT_FOUND) { - return this._createNewPackageNext(pkgName); + return this._createNewPackage(pkgName); } else { this.logger.error( { err: err, file: STORAGE.PACKAGE_FILE_NAME }, @@ -1918,7 +1949,7 @@ class Storage { The steps are the following. 1. Get the latest version of the package from the cache. - 2. If does not exist will return a + 2. If does not exist will return a @param name @param remoteManifest diff --git a/packages/store/test/fixtures/config/unpublishPackage.yaml b/packages/store/test/fixtures/config/unpublishPackage.yaml new file mode 100644 index 000000000..71e941bf3 --- /dev/null +++ b/packages/store/test/fixtures/config/unpublishPackage.yaml @@ -0,0 +1,13 @@ +uplinks: + ver: + url: https://registry.verdaccio.org/ +packages: + '@*/*': + access: $all + publish: $all + proxy: ver + '*': + access: $all + publish: $all + proxy: ver +log: { type: stdout, format: pretty, level: info } diff --git a/packages/store/test/storage.spec.ts b/packages/store/test/storage.spec.ts index 659490f2d..5db9eac53 100644 --- a/packages/store/test/storage.spec.ts +++ b/packages/store/test/storage.spec.ts @@ -23,6 +23,7 @@ import { generateLocalPackageMetadata, generatePackageMetadata, generateRemotePackageMetadata, + generateUnPublishPackageMetadata, getDeprecatedPackageMetadata, } from '@verdaccio/test-helper'; import { @@ -391,6 +392,92 @@ describe('storage', () => { expect(manifest.readme).toEqual('# test'); }); }); + describe('unpublishing', () => { + test('unpublish a private package', async () => { + const mockDate = '2018-01-14T11:17:40.712Z'; + MockDate.set(mockDate); + const pkgName = 'upstream'; + const requestOptions = { + host: 'localhost', + protocol: 'http', + headers: {}, + }; + const config = new Config( + configExample( + { + ...getDefaultConfig(), + storage: generateRandomStorage(), + }, + './fixtures/config/unpublishPackage.yaml', + __dirname + ) + ); + const storage = new Storage(config, logger); + await storage.init(config); + // publish 1.0.0 + await storage.updateManifest(generatePackageMetadata(pkgName, '1.0.0'), { + signal: new AbortController().signal, + name: pkgName, + uplinksLook: true, + revision: '1', + requestOptions, + }); + // publish 1.0.1 + await storage.updateManifest(generatePackageMetadata(pkgName, '1.0.1'), { + signal: new AbortController().signal, + name: pkgName, + uplinksLook: true, + revision: '1', + requestOptions, + }); + // publish 2.0.0 + await storage.updateManifest(generatePackageMetadata(pkgName, '2.0.0'), { + signal: new AbortController().signal, + name: pkgName, + uplinksLook: true, + revision: '1', + requestOptions, + }); + // emulate write=true before unpublish + const manifestWrite = (await storage.getPackageByOptions({ + name: pkgName, + uplinksLook: true, + requestOptions, + })) as Manifest; + // unpublish 1.0.0 (only include versions still available) + const unPublishManifest = { + ...generateUnPublishPackageMetadata( + pkgName, + ['2.0.0', '1.0.1'], + { latest: '2.0.0' }, + manifestWrite._rev + ), + }; + unPublishManifest.time = manifestWrite.time; + // we send the unpublish request + await storage.updateManifest(unPublishManifest, { + signal: new AbortController().signal, + name: pkgName, + uplinksLook: true, + revision: '1', + requestOptions, + }); + + // get the final manifest + const manifestFinal = (await storage.getPackageByOptions({ + name: pkgName, + // we don't need to look uplinks for this test + uplinksLook: false, + requestOptions, + })) as Manifest; + + expect(Object.keys(manifestFinal.versions)).toEqual( + expect.arrayContaining(['1.0.1', '2.0.0']) + ); + + expect(manifestFinal).toHaveProperty('_rev'); + }); + }); describe('deprecate', () => { test.each([['foo'], ['@scope/foo']])('deprecate package %s', async (pkgName) => { const mockDate = '2018-01-14T11:17:40.712Z'; @@ -1686,7 +1773,47 @@ describe('storage', () => { host: req.get('host') as string, }, }) - ).resolves.toEqual(expect.objectContaining({ name: 'foo' })); + ).resolves.toEqual( + expect.objectContaining({ + name: 'foo', + versions: expect.objectContaining({ + '1.0.0': expect.objectContaining({ + name: expect.any(String), + version: expect.any(String), + description: expect.any(String), + main: expect.any(String), + scripts: expect.any(Object), + keywords: expect.any(Array), + author: expect.objectContaining({ + name: expect.any(String), + email: expect.any(String), + }), + license: expect.any(String), + dependencies: expect.any(Object), + readmeFilename: expect.any(String), + _id: expect.any(String), + _npmVersion: expect.any(String), + _npmUser: expect.objectContaining({ + name: expect.any(String), + }), + dist: expect.objectContaining({ + integrity: expect.any(String), + shasum: expect.any(String), + tarball: expect.any(String), + }), + contributors: expect.any(Array), + }), + }), + time: expect.any(Object), + users: expect.any(Object), + 'dist-tags': expect.any(Object), + maintainers: expect.any(Array), + _rev: expect.any(String), + _id: expect.any(String), + readme: expect.any(String), + _attachments: expect.any(Object), + }) + ); }); test('should get 201 and merge from uplink with version', async () => { @@ -1930,11 +2057,7 @@ describe('storage', () => { expect(manifest.time).toBeDefined(); // fields must not have // @ts-expect-error - expect(manifest.readme).not.toBeDefined(); - // @ts-expect-error expect(manifest._attachments).not.toBeDefined(); - // @ts-expect-error - expect(manifest._rev).not.toBeDefined(); }); }); }); diff --git a/packages/tools/helpers/src/generateUnPublishPackageMetadata.ts b/packages/tools/helpers/src/generateUnPublishPackageMetadata.ts new file mode 100644 index 000000000..03994c406 --- /dev/null +++ b/packages/tools/helpers/src/generateUnPublishPackageMetadata.ts @@ -0,0 +1,89 @@ +import { UnPublishManifest } from '@verdaccio/types'; + +export function generateUnPublishPackageMetadata( + pkgName: string, + versions: string[] = ['1.0.0'], + distTags, + rev: string +): UnPublishManifest { + const versionsData = versions.reduce((acc, version) => { + acc[version] = { + name: pkgName, + version: version, + main: 'index.js', + scripts: { + test: 'echo "Error: no test specified" && exit 1', + }, + author: { + name: 'Verdaccio Maintainers', + email: 'verdaccio.npm@gmail.com', + }, + repository: { + type: 'git', + url: 'https://github.com/verdaccio/verdaccio.git', + }, + homepage: 'https://verdaccio.org', + funding: { + type: 'opencollective', + url: 'https://opencollective.com/verdaccio', + }, + keywords: [], + license: 'ISC', + dependencies: { + '@verdaccio/logger-7': '^6.0.0-6-next.3', + }, + bugs: { + url: 'https://github.com/verdaccio/verdaccio/issues', + }, + devDependencies: {}, + _id: `${pkgName}@${version}`, + _nodeVersion: '20.10.0', + _npmVersion: '10.9.0', + dist: { + integrity: + 'sha512-qc+palHxTF5tUhtAHGikwmv7EqhybOZ3cHUvGQZ9H2a8C7VXQ0e4ZVYS7qpNvYmG3m3khfMzsmx/R96BcxaPfw==', + shasum: '4ece00c13d4a99722275afb6270d44ca158aaaa0', + tarball: `http://localhost:8000/${pkgName}/-/${pkgName}-${version}.tgz`, + fileCount: 3, + unpackedSize: 6488666, + }, + contributors: [], + maintainers: [ + { + name: 'test', + email: '', + }, + ], + }; + return acc; + }, {}); + + const timeData = versions.reduce( + (acc, version) => { + const now = new Date().toISOString(); + acc[version] = now; + return acc; + }, + {} as Record + ); + + return { + _id: pkgName, + name: pkgName, + 'dist-tags': { ...distTags }, + versions: versionsData, + time: { + created: new Date().toISOString(), + modified: new Date().toISOString(), + ...timeData, + }, + maintainers: [ + { + name: 'test', + email: '', + }, + ], + readme: 'ERROR: No README data found!', + _rev: rev, + }; +} diff --git a/packages/tools/helpers/src/index.ts b/packages/tools/helpers/src/index.ts index be4c1a562..befb0bc1a 100644 --- a/packages/tools/helpers/src/index.ts +++ b/packages/tools/helpers/src/index.ts @@ -6,3 +6,4 @@ export { addNewVersion } from './addNewVersion'; export { generatePublishNewVersionManifest } from './generatePublishNewVersionManifest'; export { initializeServer } from './initializeServer'; export { publishVersion } from './actions'; +export { generateUnPublishPackageMetadata } from './generateUnPublishPackageMetadata'; diff --git a/packages/tools/helpers/tests/generateUnPublishPackageMetadata.ts.spec.ts b/packages/tools/helpers/tests/generateUnPublishPackageMetadata.ts.spec.ts new file mode 100644 index 000000000..11c0f96e2 --- /dev/null +++ b/packages/tools/helpers/tests/generateUnPublishPackageMetadata.ts.spec.ts @@ -0,0 +1,98 @@ +import { describe, expect, it } from 'vitest'; + +// Update the import path accordingly +import { UnPublishManifest } from '@verdaccio/types'; + +import { generateUnPublishPackageMetadata } from '../src/generateUnPublishPackageMetadata'; + +describe('generateUnPublishPackageMetadata', () => { + it('should generate metadata for a single version', () => { + const pkgName = 'test-package'; + const versions = ['1.0.0']; + const distTags = { latest: '1.0.0' }; + const rev = '1-abc'; + + const result: UnPublishManifest = generateUnPublishPackageMetadata( + pkgName, + versions, + distTags, + rev + ); + + expect(result._id).toBe(pkgName); + expect(result.name).toBe(pkgName); + expect(result['dist-tags']).toEqual(distTags); + expect(result.versions['1.0.0']).toBeDefined(); + expect(result.versions['1.0.0'].name).toBe(pkgName); + expect(result.versions['1.0.0'].version).toBe('1.0.0'); + expect(result._rev).toBe(rev); + expect(result.time?.created).toBeDefined(); + expect(result.time?.modified).toBeDefined(); + expect(result.time?.['1.0.0']).toBeDefined(); + }); + + it('should generate metadata for multiple versions', () => { + const pkgName = 'test-package'; + const versions = ['1.0.0', '2.0.0']; + const distTags = { latest: '2.0.0' }; + const rev = '1-xyz'; + + const result: UnPublishManifest = generateUnPublishPackageMetadata( + pkgName, + versions, + distTags, + rev + ); + + expect(result._id).toBe(pkgName); + expect(result.name).toBe(pkgName); + expect(result['dist-tags']).toEqual(distTags); + expect(result.versions['1.0.0']).toBeDefined(); + expect(result.versions['1.0.0'].version).toBe('1.0.0'); + expect(result.versions['2.0.0']).toBeDefined(); + expect(result.versions['2.0.0'].version).toBe('2.0.0'); + expect(result._rev).toBe(rev); + expect(result.time?.['1.0.0']).toBeDefined(); + expect(result.time?.['2.0.0']).toBeDefined(); + }); + + it('should include default metadata fields', () => { + const pkgName = 'default-test'; + const versions = ['1.0.0']; + const distTags = { latest: '1.0.0' }; + const rev = '1-def'; + + const result: UnPublishManifest = generateUnPublishPackageMetadata( + pkgName, + versions, + distTags, + rev + ); + + const versionData = result.versions['1.0.0']; + expect(versionData).toMatchObject({ + name: pkgName, + version: '1.0.0', + main: 'index.js', + scripts: { + test: 'echo "Error: no test specified" && exit 1', + }, + author: { + name: 'Verdaccio Maintainers', + email: 'verdaccio.npm@gmail.com', + }, + repository: { + type: 'git', + url: 'https://github.com/verdaccio/verdaccio.git', + }, + homepage: 'https://verdaccio.org', + funding: { + type: 'opencollective', + url: 'https://opencollective.com/verdaccio', + }, + license: 'ISC', + }); + expect(versionData.dist).toBeDefined(); + expect(versionData.maintainers).toContainEqual({ name: 'test', email: '' }); + }); +}); diff --git a/packages/tools/helpers/tests/getDeprecatedPackageMetadata.spec.ts b/packages/tools/helpers/tests/getDeprecatedPackageMetadata.spec.ts new file mode 100644 index 000000000..1a634714b --- /dev/null +++ b/packages/tools/helpers/tests/getDeprecatedPackageMetadata.spec.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from 'vitest'; + +import { Manifest } from '@verdaccio/types'; + +import { getDeprecatedPackageMetadata } from '../src/getDeprecatedPackageMetadata'; +import { DistTags } from '../src/types'; + +describe('getDeprecatedPackageMetadata', () => { + const pkgName = 'test-package'; + const version = '2.0.0'; + const distTags: DistTags = { latest: '2.0.0' }; + const deprecatedMessage = 'This package version is deprecated'; + const rev = 'rev-bar'; + + it('should generate a deprecated package manifest with default values', () => { + const result: Manifest = getDeprecatedPackageMetadata(pkgName); + + expect(result.name).toBe(pkgName); + expect(result.versions['1.0.0'].deprecated).toBe('default deprecated message'); + expect(result._rev).toBe('rev-foo'); + expect(result._attachments).toEqual({}); + }); + + it('should generate a deprecated package manifest with specified version, distTags, and deprecated message', () => { + const result: Manifest = getDeprecatedPackageMetadata( + pkgName, + version, + distTags, + deprecatedMessage, + rev + ); + + expect(result.name).toBe(pkgName); + expect(result.versions[version]).toBeDefined(); + expect(result.versions[version].deprecated).toBe(deprecatedMessage); + expect(result['dist-tags']).toEqual(distTags); + expect(result._rev).toBe(rev); + expect(result._attachments).toEqual({}); + }); +}); diff --git a/packages/tools/helpers/tests/utils.spec.ts b/packages/tools/helpers/tests/utils.spec.ts new file mode 100644 index 000000000..a3609ac45 --- /dev/null +++ b/packages/tools/helpers/tests/utils.spec.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; + +import { getTarball } from '../src/utils'; + +describe('getTarball', () => { + it('should return the name when there is no "/" in the input string', () => { + const input = 'simple-name'; + const result = getTarball(input); + + expect(result).toBe('simple-name'); + }); + + it('should return the second part of the name when there is a "/" in the input string', () => { + const input = 'scope/package-name'; + const result = getTarball(input); + + expect(result).toBe('package-name'); + }); +}); diff --git a/packages/tools/local-publish/src/index.ts b/packages/tools/local-publish/src/index.ts index 76ce167d9..9203faecd 100644 --- a/packages/tools/local-publish/src/index.ts +++ b/packages/tools/local-publish/src/index.ts @@ -46,7 +46,7 @@ fileUtils }) .then((app: any) => { app.listen(4873, () => { - console.log('running verdaccio@5 server'); + console.log('running verdaccio server'); }); }) .catch(console.error); diff --git a/packages/verdaccio/test/disabled_test/uplinks/cache.ts b/packages/verdaccio/test/disabled_test/uplinks/cache.ts index 663893d98..4de1c5a66 100644 --- a/packages/verdaccio/test/disabled_test/uplinks/cache.ts +++ b/packages/verdaccio/test/disabled_test/uplinks/cache.ts @@ -19,8 +19,6 @@ const PKG_GH1312 = 'pkg-gh1312'; function isCached(pkgName, tarballName) { const pathCached = path.join(__dirname, STORAGE, pkgName, tarballName); - console.log('isCached =>', pathCached); - return fs.existsSync(pathCached); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46579fec7..855275627 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -384,44 +384,65 @@ importers: specifier: workspace:8.0.0-next-8.4 version: link:../../../packages/verdaccio - e2e/cli/e2e-npm10: + e2e/cli/e2e-npm-commons: dependencies: '@verdaccio/test-cli-commons': specifier: workspace:2.0.0-next-8.0 version: link:../cli-commons + + e2e/cli/e2e-npm10: + dependencies: + '@verdaccio/e2e-cli-npm-common': + specifier: workspace:* + version: link:../e2e-npm-commons + '@verdaccio/test-cli-commons': + specifier: workspace:2.0.0-next-8.0 + version: link:../cli-commons npm: - specifier: 10.8.2 - version: 10.8.2 + specifier: 10.9.0 + version: 10.9.0 e2e/cli/e2e-npm6: dependencies: + '@verdaccio/e2e-cli-npm-common': + specifier: workspace:* + version: link:../e2e-npm-commons '@verdaccio/test-cli-commons': specifier: workspace:2.0.0-next-8.0 version: link:../cli-commons npm: - specifier: 9.9.3 - version: 9.9.3 + specifier: 6.14.18 + version: 6.14.18 e2e/cli/e2e-npm7: dependencies: + '@verdaccio/e2e-cli-npm-common': + specifier: workspace:* + version: link:../e2e-npm-commons '@verdaccio/test-cli-commons': specifier: workspace:2.0.0-next-8.0 version: link:../cli-commons npm: - specifier: 9.9.3 - version: 9.9.3 + specifier: 7.24.2 + version: 7.24.2 e2e/cli/e2e-npm8: dependencies: + '@verdaccio/e2e-cli-npm-common': + specifier: workspace:* + version: link:../e2e-npm-commons '@verdaccio/test-cli-commons': specifier: workspace:2.0.0-next-8.0 version: link:../cli-commons npm: - specifier: 9.9.3 - version: 9.9.3 + specifier: 8.19.4 + version: 8.19.4 e2e/cli/e2e-npm9: dependencies: + '@verdaccio/e2e-cli-npm-common': + specifier: workspace:* + version: link:../e2e-npm-commons '@verdaccio/test-cli-commons': specifier: workspace:2.0.0-next-8.0 version: link:../cli-commons @@ -429,16 +450,7 @@ importers: specifier: 9.9.3 version: 9.9.3 - e2e/cli/e2e-pnpm8: - dependencies: - '@verdaccio/test-cli-commons': - specifier: workspace:2.0.0-next-8.0 - version: link:../cli-commons - pnpm: - specifier: 8.15.5 - version: 8.15.5 - - e2e/cli/e2e-pnpm9: + e2e/cli/e2e-pnpm-commons: dependencies: '@verdaccio/test-cli-commons': specifier: workspace:2.0.0-next-8.0 @@ -447,6 +459,42 @@ importers: specifier: 9.0.0-alpha.10 version: 9.0.0-alpha.10 + e2e/cli/e2e-pnpm10: + dependencies: + '@verdaccio/e2e-cli-pnpm-common': + specifier: workspace:* + version: link:../e2e-pnpm-commons + '@verdaccio/test-cli-commons': + specifier: workspace:2.0.0-next-8.0 + version: link:../cli-commons + pnpm: + specifier: 10.0.0-alpha.2 + version: 10.0.0-alpha.2 + + e2e/cli/e2e-pnpm8: + dependencies: + '@verdaccio/e2e-cli-pnpm-common': + specifier: workspace:* + version: link:../e2e-pnpm-commons + '@verdaccio/test-cli-commons': + specifier: workspace:2.0.0-next-8.0 + version: link:../cli-commons + pnpm: + specifier: 8.15.9 + version: 8.15.9 + + e2e/cli/e2e-pnpm9: + dependencies: + '@verdaccio/e2e-cli-pnpm-common': + specifier: workspace:* + version: link:../e2e-pnpm-commons + '@verdaccio/test-cli-commons': + specifier: workspace:2.0.0-next-8.0 + version: link:../cli-commons + pnpm: + specifier: 9.13.2 + version: 9.13.2 + e2e/cli/e2e-yarn1: dependencies: '@verdaccio/test-cli-commons': @@ -23416,8 +23464,8 @@ packages: engines: {node: '>=6.0.0'} dev: false - /npm@10.8.2: - resolution: {integrity: sha512-x/AIjFIKRllrhcb48dqUNAAZl0ig9+qMuN91RpZo3Cb2+zuibfh+KISl6+kVVyktDz230JKc208UkQwwMqyB+w==} + /npm@10.9.0: + resolution: {integrity: sha512-ZanDioFylI9helNhl2LNd+ErmVD+H5I53ry41ixlLyCBgkuYb+58CvbAp99hW+zr5L9W4X7CchSoeqKdngOLSw==} engines: {node: ^18.17.0 || >=20.5.0} hasBin: true dev: false @@ -23491,6 +23539,293 @@ packages: - which - write-file-atomic + /npm@6.14.18: + resolution: {integrity: sha512-p3SjqSchSuNQUqbJBgwdv0L3O6bKkaSfQrQzJsskNpNKLg0g37c5xTXFV0SqTlX9GWvoGxBELVJMRWq0J8oaLA==} + engines: {node: 6 >=6.2.0 || 8 || >=9.3.0} + hasBin: true + dev: false + bundledDependencies: + - abbrev + - ansicolors + - ansistyles + - aproba + - archy + - bin-links + - bluebird + - byte-size + - cacache + - call-limit + - chownr + - ci-info + - cli-columns + - cli-table3 + - cmd-shim + - columnify + - config-chain + - debuglog + - detect-indent + - detect-newline + - dezalgo + - editor + - figgy-pudding + - find-npm-prefix + - fs-vacuum + - fs-write-stream-atomic + - gentle-fs + - glob + - graceful-fs + - has-unicode + - hosted-git-info + - iferr + - imurmurhash + - infer-owner + - inflight + - inherits + - ini + - init-package-json + - is-cidr + - json-parse-better-errors + - JSONStream + - lazy-property + - libcipm + - libnpm + - libnpmaccess + - libnpmhook + - libnpmorg + - libnpmsearch + - libnpmteam + - libnpx + - lock-verify + - lockfile + - lodash._baseindexof + - lodash._baseuniq + - lodash._bindcallback + - lodash._cacheindexof + - lodash._createcache + - lodash._getnative + - lodash.clonedeep + - lodash.restparam + - lodash.union + - lodash.uniq + - lodash.without + - lru-cache + - meant + - mississippi + - mkdirp + - move-concurrently + - node-gyp + - nopt + - normalize-package-data + - npm-audit-report + - npm-cache-filename + - npm-install-checks + - npm-lifecycle + - npm-package-arg + - npm-packlist + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - once + - opener + - osenv + - pacote + - path-is-inside + - promise-inflight + - qrcode-terminal + - query-string + - qw + - read-cmd-shim + - read-installed + - read-package-json + - read-package-tree + - read + - readable-stream + - readdir-scoped-modules + - request + - retry + - rimraf + - safe-buffer + - semver + - sha + - slide + - sorted-object + - sorted-union-stream + - ssri + - stringify-package + - tar + - text-table + - tiny-relative-date + - uid-number + - umask + - unique-filename + - unpipe + - update-notifier + - uuid + - validate-npm-package-license + - validate-npm-package-name + - which + - worker-farm + - write-file-atomic + + /npm@7.24.2: + resolution: {integrity: sha512-120p116CE8VMMZ+hk8IAb1inCPk4Dj3VZw29/n2g6UI77urJKVYb7FZUDW8hY+EBnfsjI/2yrobBgFyzo7YpVQ==} + engines: {node: '>=10'} + hasBin: true + dev: false + bundledDependencies: + - '@isaacs/string-locale-compare' + - '@npmcli/arborist' + - '@npmcli/ci-detect' + - '@npmcli/config' + - '@npmcli/map-workspaces' + - '@npmcli/package-json' + - '@npmcli/run-script' + - abbrev + - ansicolors + - ansistyles + - archy + - cacache + - chalk + - chownr + - cli-columns + - cli-table3 + - columnify + - fastest-levenshtein + - glob + - graceful-fs + - hosted-git-info + - ini + - init-package-json + - is-cidr + - json-parse-even-better-errors + - libnpmaccess + - libnpmdiff + - libnpmexec + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - minipass + - minipass-pipeline + - mkdirp + - mkdirp-infer-owner + - ms + - node-gyp + - nopt + - npm-audit-report + - npm-install-checks + - npm-package-arg + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - opener + - pacote + - parse-conflict-json + - qrcode-terminal + - read + - read-package-json + - read-package-json-fast + - readdir-scoped-modules + - rimraf + - semver + - ssri + - tar + - text-table + - tiny-relative-date + - treeverse + - validate-npm-package-name + - which + - write-file-atomic + + /npm@8.19.4: + resolution: {integrity: sha512-3HANl8i9DKnUA89P4KEgVNN28EjSeDCmvEqbzOAuxCFDzdBZzjUl99zgnGpOUumvW5lvJo2HKcjrsc+tfyv1Hw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + dev: false + bundledDependencies: + - '@isaacs/string-locale-compare' + - '@npmcli/arborist' + - '@npmcli/ci-detect' + - '@npmcli/config' + - '@npmcli/fs' + - '@npmcli/map-workspaces' + - '@npmcli/package-json' + - '@npmcli/run-script' + - abbrev + - archy + - cacache + - chalk + - chownr + - cli-columns + - cli-table3 + - columnify + - fastest-levenshtein + - fs-minipass + - glob + - graceful-fs + - hosted-git-info + - ini + - init-package-json + - is-cidr + - json-parse-even-better-errors + - libnpmaccess + - libnpmdiff + - libnpmexec + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - minimatch + - minipass + - minipass-pipeline + - mkdirp + - mkdirp-infer-owner + - ms + - node-gyp + - nopt + - npm-audit-report + - npm-install-checks + - npm-package-arg + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - opener + - p-map + - pacote + - parse-conflict-json + - proc-log + - qrcode-terminal + - read + - read-package-json + - read-package-json-fast + - readdir-scoped-modules + - rimraf + - semver + - ssri + - tar + - text-table + - tiny-relative-date + - treeverse + - validate-npm-package-name + - which + - write-file-atomic + /npm@9.9.3: resolution: {integrity: sha512-Z1l+rcQ5kYb17F3hHtO601arEpvdRYnCLtg8xo3AGtyj3IthwaraEOexI9903uANkifFbqHC8hT53KIrozWg8A==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -24468,8 +24803,14 @@ packages: - typescript dev: true - /pnpm@8.15.5: - resolution: {integrity: sha512-sFGjLH5pWDO4SSbTspuMylclS1ifBknYmcbp0O22cLkex+KkNFm65zdZu1zmGcMmbxFr+THOItHvF1mn5Fqpbw==} + /pnpm@10.0.0-alpha.2: + resolution: {integrity: sha512-8YpZyjYRACMhr3aB5tSSNMs+zoSWsFgYvlsQgRaOwhuMPSjLtDUeL97GbKleZRb6rwi5W3VQE8iM9RdNUCmGXA==} + engines: {node: '>=18.12'} + hasBin: true + dev: false + + /pnpm@8.15.9: + resolution: {integrity: sha512-SZQ0ydj90aJ5Tr9FUrOyXApjOrzuW7Fee13pDzL0e1E6ypjNXP0AHDHw20VLw4BO3M1XhQHkyik6aBYWa72fgQ==} engines: {node: '>=16.14'} hasBin: true dev: false @@ -24480,6 +24821,12 @@ packages: hasBin: true dev: false + /pnpm@9.13.2: + resolution: {integrity: sha512-iMnDhkRQNQ5lozWHq4Aaz5RtfIFO0RNNpKkk9t9aISD9NrRqq2j3zR1BMUkRLVPH2zpBNmJM/QD/GEagxs70ig==} + engines: {node: '>=18.12'} + hasBin: true + dev: false + /polished@4.2.2: resolution: {integrity: sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==} engines: {node: '>=10'} diff --git a/renovate.json b/renovate.json index aed099796..584d918ed 100644 --- a/renovate.json +++ b/renovate.json @@ -11,7 +11,10 @@ "docker/login-action", "docker/build-push-action", "crazy-max/ghaction-docker-meta", - "pnpm" + "pnpm", + "yarn", + "npm", + "@yarnpkg/cli-dist" ], "baseBranches": ["master", "6.x", "7.x"], "semanticCommitType": "fix", @@ -158,13 +161,6 @@ "groupSlug": "all-test", "baseBranchList": ["master", "6.x", "7.x"] }, - { - "matchPackagePatterns": ["npm", "pnpm", "yarn", "@yarnpkg/*"], - "matchUpdateTypes": ["minor", "patch"], - "groupName": "all package managers", - "groupSlug": "all-pkg-managers", - "baseBranchList": ["master"] - }, { "matchPackagePatterns": ["@type/*", "typescript"], "matchUpdateTypes": ["minor", "patch", "major"], diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 000000000..a1278c15d --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + coverage: { + exclude: ['./build', 'test'], + }, + }, +});