diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0eb78ad4f..6b1dcf8dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1287,7 +1287,7 @@ importers: pnpm: next-7 dependencies: '@verdaccio/test-cli-commons': link:../cli-commons - pnpm: 7.11.1-0 + pnpm: 7.12.0-0 test/cli/e2e-yarn1: specifiers: @@ -6365,7 +6365,7 @@ packages: peerDependencies: react: '*' dependencies: - '@types/react': 17.0.49 + '@types/react': 17.0.50 prop-types: 15.8.1 react: 17.0.2 @@ -9043,13 +9043,6 @@ packages: '@types/scheduler': 0.16.2 csstype: 3.1.0 - /@types/react/17.0.49: - resolution: {integrity: sha512-CCBPMZaPhcKkYUTqFs/hOWqKjPxhTEmnZWjlHHgIMop67DsXywf9B5Os9Hz8KSacjNOgIdnZVJamwl232uxoPg==} - dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.2 - csstype: 3.1.0 - /@types/react/17.0.50: resolution: {integrity: sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==} dependencies: @@ -9193,6 +9186,10 @@ packages: peerDependencies: '@typescript-eslint/parser': ^5.0.0 eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@typescript-eslint/parser': 5.37.0_eslint@8.23.1+typescript@4.8.3 '@typescript-eslint/scope-manager': 5.37.0 @@ -9205,24 +9202,28 @@ packages: regexpp: 3.2.0 semver: 7.3.7 tsutils: 3.21.0_typescript@4.8.3 + typescript: 4.8.3 transitivePeerDependencies: - supports-color - - typescript /@typescript-eslint/parser/5.37.0_eslint@8.23.1+typescript@4.8.3: resolution: {integrity: sha512-01VzI/ipYKuaG5PkE5+qyJ6m02fVALmMPY3Qq5BHflDx3y4VobbLdHQkSMg9VPRS4KdNt4oYTMaomFoHonBGAw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@typescript-eslint/scope-manager': 5.37.0 '@typescript-eslint/types': 5.37.0 '@typescript-eslint/typescript-estree': 5.37.0_typescript@4.8.3 debug: 4.3.4 eslint: 8.23.1 + typescript: 4.8.3 transitivePeerDependencies: - supports-color - - typescript /@typescript-eslint/scope-manager/5.33.1: resolution: {integrity: sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==} @@ -9244,15 +9245,19 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@typescript-eslint/typescript-estree': 5.37.0_typescript@4.8.3 '@typescript-eslint/utils': 5.37.0_eslint@8.23.1+typescript@4.8.3 debug: 4.3.4 eslint: 8.23.1 tsutils: 3.21.0_typescript@4.8.3 + typescript: 4.8.3 transitivePeerDependencies: - supports-color - - typescript /@typescript-eslint/types/5.33.1: resolution: {integrity: sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==} @@ -9287,6 +9292,11 @@ packages: /@typescript-eslint/typescript-estree/5.37.0_typescript@4.8.3: resolution: {integrity: sha512-JkFoFIt/cx59iqEDSgIGnQpCTRv96MQnXCYvJi7QhBC24uyuzbD8wVbajMB1b9x4I0octYFJ3OwjAwNqk1AjDA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: '@typescript-eslint/types': 5.37.0 '@typescript-eslint/visitor-keys': 5.37.0 @@ -9295,9 +9305,9 @@ packages: is-glob: 4.0.3 semver: 7.3.7 tsutils: 3.21.0_typescript@4.8.3 + typescript: 4.8.3 transitivePeerDependencies: - supports-color - - typescript /@typescript-eslint/utils/5.33.1_eslint@8.23.1+typescript@4.8.3: resolution: {integrity: sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==} @@ -18100,6 +18110,9 @@ packages: engines: {node: 4.x || >=6.0.0} peerDependencies: encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true dependencies: whatwg-url: 5.0.0 @@ -19143,8 +19156,8 @@ packages: hasBin: true dev: false - /pnpm/7.11.1-0: - resolution: {integrity: sha512-u4oQSQKBSQwkNWGl0J6GXeaXXzGNi6NWbCT7p6zMuKHl8UAn4ByRVIOdfxhFzsMrIf0izjlfwry70C1Ic7SdQw==} + /pnpm/7.12.0-0: + resolution: {integrity: sha512-nNP2ttBuXwH82DBbZbDcc0vxAcTSkKzfT5HI4xY9u4iNs3CcY2h0+wgmftanfNa4Xs+UBwl6dgWBGjjMR3qLCg==} engines: {node: '>=14.6'} hasBin: true dev: false diff --git a/test/cli/README.md b/test/cli/README.md index 098d9d47f..48cc0f5ee 100644 --- a/test/cli/README.md +++ b/test/cli/README.md @@ -12,10 +12,49 @@ | publish | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | | info | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | audit | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| install | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ## How it works? -> TBA +Every package manager + version is a package in the monorepo. + +The package `@verdaccio/test-cli-commons` contains helpers used for each package manager. + +```ts +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; +``` + +The registry can be executed with the following commands, the port is automatically assigned. + +```ts +// setup +const setup = await initialSetup(); +registry = setup.registry; +await registry.init(); +// teardown +registry.stop(); +``` + +The full url can be get from `registry.getRegistryUrl()`. The yarn modern does not allows the `--registry` so need a more complex step, while others is just enough adding the following to every command. + +```ts +await yarn({ cwd: tempFolder }, 'install', ...addRegistry(registry.getRegistryUrl())); +``` + +The most of the command allow return output in JSON format which helps with the expects. + +```ts +const resp = await yarn( + { cwd: tempFolder }, + 'audit', + '--json', + ...addRegistry(registry.getRegistryUrl()) +); +const parsedBody = JSON.parse(resp.stdout as string); +expect(parsedBody.type).toEqual('auditSummary'); +``` + +Every command should test either console output or in special cases look up the storage manually. ### What should not included on these tests? diff --git a/test/cli/cli-commons/src/index.ts b/test/cli/cli-commons/src/index.ts index 106814341..a98328388 100644 --- a/test/cli/cli-commons/src/index.ts +++ b/test/cli/cli-commons/src/index.ts @@ -6,5 +6,6 @@ export { addRegistry, prepareYarnModernProject, prepareGenericEmptyProject, + nJSONParse, } from './utils'; export { exec, ExecOutput } from './process'; diff --git a/test/cli/cli-commons/src/utils.ts b/test/cli/cli-commons/src/utils.ts index 8f97e8cee..26dd9a249 100644 --- a/test/cli/cli-commons/src/utils.ts +++ b/test/cli/cli-commons/src/utils.ts @@ -105,3 +105,12 @@ export async function prepareGenericEmptyProject( await writeFile(join(tempFolder, '.npmrc'), getNPMrc(port, token, registryDomain)); return { tempFolder }; } + +export function nJSONParse(jsonString) { + const type = typeof jsonString; + if (type !== 'string') throw new Error(`Input have to be string but got ${type}`); + + const jsonRows = jsonString.split(/\n|\n\r/).filter(Boolean); + console.log('--jsonRows', jsonRows); + return jsonRows.map((jsonStringRow) => JSON.parse(jsonStringRow)); +} diff --git a/test/cli/e2e-npm6/install.spec.ts b/test/cli/e2e-npm6/install.spec.ts new file mode 100644 index 000000000..2ac82308c --- /dev/null +++ b/test/cli/e2e-npm6/install.spec.ts @@ -0,0 +1,38 @@ +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +import { npm } from './utils'; + +describe('install a project packages', () => { + jest.setTimeout(80000); + 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/test/cli/e2e-npm7/install.spec.ts b/test/cli/e2e-npm7/install.spec.ts new file mode 100644 index 000000000..2ac82308c --- /dev/null +++ b/test/cli/e2e-npm7/install.spec.ts @@ -0,0 +1,38 @@ +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +import { npm } from './utils'; + +describe('install a project packages', () => { + jest.setTimeout(80000); + 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/test/cli/e2e-npm8/install.spec.ts b/test/cli/e2e-npm8/install.spec.ts new file mode 100644 index 000000000..2b15921da --- /dev/null +++ b/test/cli/e2e-npm8/install.spec.ts @@ -0,0 +1,38 @@ +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +import { npm } from './utils'; + +describe('install a project packages', () => { + jest.setTimeout(100000); + 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/test/cli/e2e-pnpm6/install.spec.ts b/test/cli/e2e-pnpm6/install.spec.ts new file mode 100644 index 000000000..2ef73559b --- /dev/null +++ b/test/cli/e2e-pnpm6/install.spec.ts @@ -0,0 +1,36 @@ +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +import { pnpm } from './utils'; + +describe('install a project packages', () => { + jest.setTimeout(80000); + 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 18.2.0/); + }); + + afterAll(async () => { + registry.stop(); + }); +}); diff --git a/test/cli/e2e-pnpm7/install.spec.ts b/test/cli/e2e-pnpm7/install.spec.ts new file mode 100644 index 000000000..2ef73559b --- /dev/null +++ b/test/cli/e2e-pnpm7/install.spec.ts @@ -0,0 +1,36 @@ +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +import { pnpm } from './utils'; + +describe('install a project packages', () => { + jest.setTimeout(80000); + 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 18.2.0/); + }); + + afterAll(async () => { + registry.stop(); + }); +}); diff --git a/test/cli/e2e-yarn1/install.spec.ts b/test/cli/e2e-yarn1/install.spec.ts new file mode 100644 index 000000000..8d210342a --- /dev/null +++ b/test/cli/e2e-yarn1/install.spec.ts @@ -0,0 +1,35 @@ +import { addRegistry, initialSetup, prepareGenericEmptyProject } from '@verdaccio/test-cli-commons'; + +import { yarn } from './utils'; + +describe('install a project packages', () => { + jest.setTimeout(80000); + let registry; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + }); + + test('should run yarn install', async () => { + const { tempFolder } = await prepareGenericEmptyProject( + 'something', + '1.0.0-patch', + registry.port, + registry.getToken(), + registry.getRegistryUrl(), + { react: '18.2.0' } + ); + const resp = await yarn( + { cwd: tempFolder }, + 'install', + ...addRegistry(registry.getRegistryUrl()) + ); + expect(resp.stdout).toMatch(/success/); + }); + + afterAll(async () => { + registry.stop(); + }); +}); diff --git a/test/cli/e2e-yarn2/install.spec.ts b/test/cli/e2e-yarn2/install.spec.ts new file mode 100644 index 000000000..91486ee0b --- /dev/null +++ b/test/cli/e2e-yarn2/install.spec.ts @@ -0,0 +1,33 @@ +import { join } from 'path'; + +import { initialSetup, prepareYarnModernProject } from '@verdaccio/test-cli-commons'; + +import { getYarnCommand, yarn } from './utils'; + +describe('install a packages', () => { + jest.setTimeout(10000); + let registry; + let projectFolder; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + const { tempFolder } = await prepareYarnModernProject( + join(__dirname, './yarn-install'), + 'yarn-2', + registry.getRegistryUrl(), + getYarnCommand() + ); + projectFolder = tempFolder; + }); + + test('should run yarn install', async () => { + const resp = await yarn(projectFolder, 'install'); + expect(resp.stdout).toMatch(/Completed/); + }); + + afterAll(async () => { + registry.stop(); + }); +}); diff --git a/test/cli/e2e-yarn2/yarn-install/.yarnrc.yml b/test/cli/e2e-yarn2/yarn-install/.yarnrc.yml new file mode 100644 index 000000000..6aa2a1ed4 --- /dev/null +++ b/test/cli/e2e-yarn2/yarn-install/.yarnrc.yml @@ -0,0 +1,9 @@ +httpRetry: 10 +httpTimeout: 100000 +npmRegistryServer: ${registry} +yarnPath: .yarn/releases/yarn.js +# on CI modify the lock file is not allowed +# https://github.com/yarnpkg/berry/discussions/3486#discussioncomment-1379344 +enableImmutableInstalls: false +unsafeHttpWhitelist: + - localhost diff --git a/test/cli/e2e-yarn2/yarn-install/package.json b/test/cli/e2e-yarn2/yarn-install/package.json new file mode 100644 index 000000000..c426ae66e --- /dev/null +++ b/test/cli/e2e-yarn2/yarn-install/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo", + "version": "1.0.0", + "dependencies": { + "react": "18.2.0" + } +} diff --git a/test/cli/e2e-yarn2/yarn-install/yarn.lock b/test/cli/e2e-yarn2/yarn-install/yarn.lock new file mode 100644 index 000000000..e69de29bb diff --git a/test/cli/e2e-yarn3/install.spec.ts b/test/cli/e2e-yarn3/install.spec.ts new file mode 100644 index 000000000..91486ee0b --- /dev/null +++ b/test/cli/e2e-yarn3/install.spec.ts @@ -0,0 +1,33 @@ +import { join } from 'path'; + +import { initialSetup, prepareYarnModernProject } from '@verdaccio/test-cli-commons'; + +import { getYarnCommand, yarn } from './utils'; + +describe('install a packages', () => { + jest.setTimeout(10000); + let registry; + let projectFolder; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + const { tempFolder } = await prepareYarnModernProject( + join(__dirname, './yarn-install'), + 'yarn-2', + registry.getRegistryUrl(), + getYarnCommand() + ); + projectFolder = tempFolder; + }); + + test('should run yarn install', async () => { + const resp = await yarn(projectFolder, 'install'); + expect(resp.stdout).toMatch(/Completed/); + }); + + afterAll(async () => { + registry.stop(); + }); +}); diff --git a/test/cli/e2e-yarn3/yarn-install/.yarnrc.yml b/test/cli/e2e-yarn3/yarn-install/.yarnrc.yml new file mode 100644 index 000000000..6aa2a1ed4 --- /dev/null +++ b/test/cli/e2e-yarn3/yarn-install/.yarnrc.yml @@ -0,0 +1,9 @@ +httpRetry: 10 +httpTimeout: 100000 +npmRegistryServer: ${registry} +yarnPath: .yarn/releases/yarn.js +# on CI modify the lock file is not allowed +# https://github.com/yarnpkg/berry/discussions/3486#discussioncomment-1379344 +enableImmutableInstalls: false +unsafeHttpWhitelist: + - localhost diff --git a/test/cli/e2e-yarn3/yarn-install/package.json b/test/cli/e2e-yarn3/yarn-install/package.json new file mode 100644 index 000000000..c426ae66e --- /dev/null +++ b/test/cli/e2e-yarn3/yarn-install/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo", + "version": "1.0.0", + "dependencies": { + "react": "18.2.0" + } +} diff --git a/test/cli/e2e-yarn3/yarn-install/yarn.lock b/test/cli/e2e-yarn3/yarn-install/yarn.lock new file mode 100644 index 000000000..e69de29bb diff --git a/test/cli/e2e-yarn4/install.spec.ts b/test/cli/e2e-yarn4/install.spec.ts new file mode 100644 index 000000000..91486ee0b --- /dev/null +++ b/test/cli/e2e-yarn4/install.spec.ts @@ -0,0 +1,33 @@ +import { join } from 'path'; + +import { initialSetup, prepareYarnModernProject } from '@verdaccio/test-cli-commons'; + +import { getYarnCommand, yarn } from './utils'; + +describe('install a packages', () => { + jest.setTimeout(10000); + let registry; + let projectFolder; + + beforeAll(async () => { + const setup = await initialSetup(); + registry = setup.registry; + await registry.init(); + const { tempFolder } = await prepareYarnModernProject( + join(__dirname, './yarn-install'), + 'yarn-2', + registry.getRegistryUrl(), + getYarnCommand() + ); + projectFolder = tempFolder; + }); + + test('should run yarn install', async () => { + const resp = await yarn(projectFolder, 'install'); + expect(resp.stdout).toMatch(/Completed/); + }); + + afterAll(async () => { + registry.stop(); + }); +}); diff --git a/test/cli/e2e-yarn4/yarn-install/.yarnrc.yml b/test/cli/e2e-yarn4/yarn-install/.yarnrc.yml new file mode 100644 index 000000000..6aa2a1ed4 --- /dev/null +++ b/test/cli/e2e-yarn4/yarn-install/.yarnrc.yml @@ -0,0 +1,9 @@ +httpRetry: 10 +httpTimeout: 100000 +npmRegistryServer: ${registry} +yarnPath: .yarn/releases/yarn.js +# on CI modify the lock file is not allowed +# https://github.com/yarnpkg/berry/discussions/3486#discussioncomment-1379344 +enableImmutableInstalls: false +unsafeHttpWhitelist: + - localhost diff --git a/test/cli/e2e-yarn4/yarn-install/package.json b/test/cli/e2e-yarn4/yarn-install/package.json new file mode 100644 index 000000000..c426ae66e --- /dev/null +++ b/test/cli/e2e-yarn4/yarn-install/package.json @@ -0,0 +1,7 @@ +{ + "name": "foo", + "version": "1.0.0", + "dependencies": { + "react": "18.2.0" + } +} diff --git a/test/cli/e2e-yarn4/yarn-install/yarn.lock b/test/cli/e2e-yarn4/yarn-install/yarn.lock new file mode 100644 index 000000000..e69de29bb