diff --git a/.github/workflows/ci-e2e.yml b/.github/workflows/ci-e2e.yml index 5ecd6f5b4..d3600321b 100644 --- a/.github/workflows/ci-e2e.yml +++ b/.github/workflows/ci-e2e.yml @@ -1,13 +1,25 @@ -name: E2E CLI +name: CI E2E -on: [pull_request] +on: + push: + branches: + - 5.x + - 'changeset-release/5.x' + pull_request: + paths: + - .changeset/** + - .github/workflows/ci.yml + - 'packages/**' + - 'jest/**' + - 'package.json' + - 'pnpm-workspace.yaml' jobs: ci: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, windows-latest] node_version: [14] name: ${{ matrix.os }} / Node ${{ matrix.node_version }} @@ -16,12 +28,18 @@ jobs: steps: - uses: actions/checkout@v2.3.1 - name: Use Node ${{ matrix.node_version }} - uses: actions/setup-node@v2.1.5 + uses: actions/setup-node@v1 with: - node-version: ${{ matrix.node_version }} + node_version: ${{ matrix.node_version }} + - name: Install pnpm + run: npm i -g pnpm@latest - name: Install - run: yarn install + run: pnpm recursive install + - name: Clean + run: pnpm clean - name: Build - run: yarn code:build - - name: Test CLI - run: yarn test:e2e:cli + run: pnpm build + - name: Test + run: pnpm test:e2e:cli + env: + DEBUG: verdaccio:e2e* diff --git a/.gitignore b/.gitignore index c1e9c7ff1..4bcddb334 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ test-storage* node_modules package-lock.json yarn-error.log +yarn.lock # jest diff --git a/.npmrc b/.npmrc index a307393df..9320a72ea 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1,4 @@ always-auth = true recursive-install = true registry = https://registry.verdaccio.org/ +loglevel=warn diff --git a/.sonarcloud.properties b/.sonarcloud.properties deleted file mode 100644 index 8b1378917..000000000 --- a/.sonarcloud.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index f8dde3017..000000000 --- a/.yarnrc +++ /dev/null @@ -1,2 +0,0 @@ -save-prefix "" -registry "https://registry.verdaccio.org" diff --git a/package.json b/package.json index 94ef50b85..36ceacef6 100644 --- a/package.json +++ b/package.json @@ -111,12 +111,12 @@ "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"", "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,yml,yaml,md}\"", "lint": "eslint \"**/*.{js,jsx,ts,tsx}\"", - "test": "pnpm recursive test", + "test": "pnpm recursive test --filter ./packages", + "test:e2e:cli": "pnpm test --filter ...@verdaccio/e2e-cli", "start": "node packages/verdaccio/debug/bootstrap.js", "start:ts": "ts-node packages/verdaccio/src/start.ts", "debug": "node --inspect packages/verdaccio/debug/bootstrap.js", "debug:break": "node --inspect-brk packages/verdaccio/debug/bootstrap.js", - "test:e2e:cli": "cross-env NODE_ENV=test jest --config ./test/e2e-cli/jest.config.e2e.cli.js --passWithNoTests", "website:lint": "cd website && yarn lint", "website:develop": "cd website && yarn develop", "website:build": "cd website && yarn build", diff --git a/packages/api/package.json b/packages/api/package.json index 761e4486d..f5da6f4eb 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -25,12 +25,12 @@ "dependencies": { "@verdaccio/auth": "workspace:5.0.0-alpha.1", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", + "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/hooks": "workspace:5.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", "@verdaccio/middleware": "workspace:5.0.0-alpha.1", "@verdaccio/store": "workspace:5.0.0-alpha.1", "@verdaccio/utils": "workspace:5.0.0-alpha.1", - "@verdaccio/config": "workspace:5.0.0-alpha.1", "cookies": "0.8.0", "debug": "^4.1.1", "express": "4.17.1", diff --git a/packages/auth/package.json b/packages/auth/package.json index 371c8dde7..7ad0fa550 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -23,15 +23,15 @@ }, "license": "MIT", "dependencies": { + "@verdaccio/auth": "workspace:5.0.0-alpha.1", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", + "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/loaders": "workspace:5.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", - "@verdaccio/auth": "workspace:5.0.0-alpha.1", - "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/utils": "workspace:5.0.0-alpha.1", - "jsonwebtoken": "8.5.1", "debug": "^4.1.1", "express": "4.17.1", + "jsonwebtoken": "8.5.1", "lodash": "4.17.15" }, "devDependencies": { diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 07633971b..2028a8570 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -15,17 +15,17 @@ "license": "MIT", "homepage": "https://verdaccio.org", "dependencies": { - "debug": "^4.2.0", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", + "debug": "^4.2.0", "handlebars": "4.5.3", - "request": "2.87.0", - "node-fetch": "^2.6.1" + "node-fetch": "^2.6.1", + "request": "2.87.0" }, "devDependencies": { "@verdaccio/auth": "workspace:5.0.0-alpha.1", - "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", + "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/types": "workspace:10.0.0-alpha.1", "nock": "^13.0.4" }, diff --git a/packages/loaders/package.json b/packages/loaders/package.json index 8d682dd1d..a6993d264 100644 --- a/packages/loaders/package.json +++ b/packages/loaders/package.json @@ -14,13 +14,13 @@ }, "dependencies": { "@verdaccio/logger": "workspace:5.0.0-alpha.1", - "lodash": "4.17.15", - "debug": "^4.1.1" + "debug": "^4.1.1", + "lodash": "4.17.15" }, "devDependencies": { - "@verdaccio/mock": "workspace:5.0.0-alpha.1", - "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", + "@verdaccio/config": "workspace:5.0.0-alpha.1", + "@verdaccio/mock": "workspace:5.0.0-alpha.1", "@verdaccio/types": "workspace:10.0.0-alpha.1" }, "homepage": "https://verdaccio.org", diff --git a/packages/logger/package.json b/packages/logger/package.json index b1a44d327..0fa39edcc 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -24,8 +24,8 @@ }, "dependencies": { "@verdaccio/logger-prettify": "workspace:5.0.0-alpha.1", - "lodash": "~4.17.20", "debug": "^4.2.0", + "lodash": "~4.17.20", "pino": "^6.7.0" }, "devDependencies": { diff --git a/packages/middleware/package.json b/packages/middleware/package.json index 9aa42ac8d..31ab2becc 100644 --- a/packages/middleware/package.json +++ b/packages/middleware/package.json @@ -22,10 +22,10 @@ "build": "pnpm run build:js && pnpm run build:types" }, "dependencies": { + "@verdaccio/auth": "workspace:5.0.0-alpha.1", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", "@verdaccio/utils": "workspace:5.0.0-alpha.1", - "@verdaccio/auth": "workspace:5.0.0-alpha.1", "lodash": "4.17.15" } } diff --git a/packages/mock/LICENSE b/packages/mock/LICENSE new file mode 100644 index 000000000..a969d7d06 --- /dev/null +++ b/packages/mock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Verdaccio community + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/mock/package.json b/packages/mock/package.json index ecdc8ba46..c6ad6ef4f 100644 --- a/packages/mock/package.json +++ b/packages/mock/package.json @@ -24,13 +24,13 @@ }, "dependencies": { "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", - "@verdaccio/utils": "workspace:5.0.0-alpha.1", "@verdaccio/config": "workspace:5.0.0-alpha.1", + "@verdaccio/utils": "workspace:5.0.0-alpha.1", + "debug": "^4.2.0", "fs-extra": "^8.1.0", "lodash": "^4.17.20", "request": "2.87.0", - "supertest": "^4.0.2", - "debug": "^4.2.0" + "supertest": "^4.0.2" }, "devDependencies": { "@verdaccio/types": "workspace:10.0.0-alpha.1" diff --git a/packages/node-api/package.json b/packages/node-api/package.json index cf343eaea..113107b4a 100644 --- a/packages/node-api/package.json +++ b/packages/node-api/package.json @@ -24,12 +24,12 @@ "license": "MIT", "dependencies": { "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", + "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", "@verdaccio/server": "workspace:5.0.0-alpha.1", - "@verdaccio/config": "workspace:5.0.0-alpha.1", - "lodash": "^4.17.20", - "debug": "^4.2.0", "core-js": "^3.6.5", + "debug": "^4.2.0", + "lodash": "^4.17.20", "selfsigned": "1.10.7" }, "devDependencies": { diff --git a/packages/plugins/audit/package.json b/packages/plugins/audit/package.json index ef678ee8b..c83b8b220 100644 --- a/packages/plugins/audit/package.json +++ b/packages/plugins/audit/package.json @@ -28,8 +28,8 @@ }, "devDependencies": { "@verdaccio/types": "workspace:10.0.0-alpha.1", - "nock": "^12.0.3", "body-parser": "^1.19.0", + "nock": "^12.0.3", "supertest": "^4.0.2" }, "scripts": { diff --git a/packages/proxy/package.json b/packages/proxy/package.json index 5a23156f5..3bed3e3ac 100644 --- a/packages/proxy/package.json +++ b/packages/proxy/package.json @@ -24,8 +24,8 @@ }, "dependencies": { "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", - "@verdaccio/local-storage": "workspace:10.0.0-alpha.1", "@verdaccio/config": "workspace:5.0.0-alpha.1", + "@verdaccio/local-storage": "workspace:10.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", "@verdaccio/streams": "workspace:10.0.0-alpha.1", "@verdaccio/utils": "workspace:5.0.0-alpha.1", diff --git a/packages/server/package.json b/packages/server/package.json index 927550bcd..0229acbf8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -17,8 +17,8 @@ "dependencies": { "@verdaccio/api": "workspace:5.0.0-alpha.1", "@verdaccio/auth": "workspace:5.0.0-alpha.1", - "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", + "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/loaders": "workspace:5.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", "@verdaccio/middleware": "workspace:5.0.0-alpha.1", diff --git a/packages/verdaccio/package.json b/packages/verdaccio/package.json index a58b5445e..dcb7605cc 100644 --- a/packages/verdaccio/package.json +++ b/packages/verdaccio/package.json @@ -43,12 +43,13 @@ "@verdaccio/node-api": "workspace:5.0.0-alpha.1", "@verdaccio/ui-theme": "^1.14.0", "@verdaccio/utils": "workspace:5.0.0-alpha.1", + "verdaccio-audit": "10.0.0-alpha.1", "verdaccio-htpasswd": "10.0.0-alpha.1" }, "devDependencies": { "@verdaccio/auth": "workspace:5.0.0-alpha.1", - "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", + "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/store": "workspace:5.0.0-alpha.1" }, "keywords": [ diff --git a/packages/web/package.json b/packages/web/package.json index 8e9a4a769..ab1cd1dfb 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -6,13 +6,13 @@ "types": "build/index.d.ts", "license": "MIT", "dependencies": { - "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", "@verdaccio/auth": "workspace:5.0.0-alpha.1", + "@verdaccio/commons-api": "workspace:10.0.0-alpha.1", "@verdaccio/config": "workspace:5.0.0-alpha.1", "@verdaccio/loaders": "workspace:5.0.0-alpha.1", - "@verdaccio/readme": "workspace:10.0.0-alpha.1", "@verdaccio/logger": "workspace:5.0.0-alpha.1", "@verdaccio/middleware": "workspace:5.0.0-alpha.1", + "@verdaccio/readme": "workspace:10.0.0-alpha.1", "@verdaccio/store": "workspace:5.0.0-alpha.1", "@verdaccio/utils": "workspace:5.0.0-alpha.1", "body-parse": "0.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f662ec6d..615dc20f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -718,6 +718,7 @@ importers: '@verdaccio/node-api': 'link:../node-api' '@verdaccio/ui-theme': 1.14.0 '@verdaccio/utils': 'link:../utils' + verdaccio-audit: 'link:../plugins/audit' verdaccio-htpasswd: 'link:../core/htpasswd' devDependencies: '@verdaccio/auth': 'link:../auth' @@ -736,6 +737,7 @@ importers: '@verdaccio/store': 'workspace:5.0.0-alpha.1' '@verdaccio/ui-theme': ^1.14.0 '@verdaccio/utils': 'workspace:5.0.0-alpha.1' + verdaccio-audit: 10.0.0-alpha.1 verdaccio-htpasswd: 10.0.0-alpha.1 packages/web: dependencies: @@ -771,6 +773,24 @@ importers: debug: ^4.1.1 express: 4.17.1 lodash: ^4.17.20 + test/e2e-cli: + dependencies: + debug: 4.3.1 + npm: 7.0.15 + pnpm: 5.13.5 + request: 2.88.2 + yarn: 1.22.10 + devDependencies: + get-port: 5.1.1 + semver: 7.3.4 + specifiers: + debug: 4.3.1 + get-port: ^5.1.1 + npm: 7.0.15 + pnpm: 5.13.5 + request: ^2.88.2 + semver: ^7.3.4 + yarn: 1.22.10 website: dependencies: '@emotion/core': 10.0.28_react@16.13.1 @@ -9992,6 +10012,18 @@ packages: optional: true resolution: integrity: sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + /debug/4.3.1: + dependencies: + ms: 2.1.2 + engines: + node: '>=6.0' + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + resolution: + integrity: sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== /decamelize-keys/1.1.0: dependencies: decamelize: 1.2.0 @@ -13230,6 +13262,12 @@ packages: node: '>=4' resolution: integrity: sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= + /get-port/5.1.1: + dev: true + engines: + node: '>=8' + resolution: + integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== /get-proxy/2.1.0: dependencies: npm-conf: 1.1.3 @@ -17008,7 +17046,6 @@ packages: /lru-cache/6.0.0: dependencies: yallist: 4.0.0 - dev: false engines: node: '>=10' resolution: @@ -18059,6 +18096,81 @@ packages: hasBin: true resolution: integrity: sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo= + /npm/7.0.15: + bundledDependencies: + - '@npmcli/arborist' + - '@npmcli/ci-detect' + - '@npmcli/config' + - '@npmcli/run-script' + - abbrev + - ansicolors + - ansistyles + - aproba + - archy + - bin-links + - byte-size + - cacache + - chalk + - chownr + - cli-columns + - cli-table3 + - columnify + - editor + - glob + - graceful-fs + - hosted-git-info + - inherits + - ini + - init-package-json + - is-cidr + - leven + - libnpmaccess + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - mkdirp + - mkdirp-infer-owner + - ms + - node-gyp + - nopt + - normalize-package-data + - npm-audit-report + - 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 + - rimraf + - semver + - sorted-object + - ssri + - tar + - text-table + - tiny-relative-date + - uuid + - validate-npm-package-name + - which + - write-file-atomic + dev: false + engines: + node: '>=10' + hasBin: true + resolution: + integrity: sha512-vP4qQMsbfERokwYMDbSHqbtCFFNVMCvLHJXyzrDSka6Mz8GCQwj1Y/OjgF2nji80/yl+RQvMnOjVNgjWQf9NBw== /npmlog/4.1.2: dependencies: are-we-there-yet: 1.1.5 @@ -19092,6 +19204,13 @@ packages: node: '>=6' resolution: integrity: sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== + /pnpm/5.13.5: + dev: false + engines: + node: '>=10.16' + hasBin: true + resolution: + integrity: sha512-EJO8eYZyNpOvW+JhjBnLtxD2xcC6YlrzH8jxjETj8bevLATFa9vnGq614ada6o1XOIMq31JWtj1WyPJNogAzLA== /popper.js/1.16.1: deprecated: 'You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1' dev: false @@ -21256,6 +21375,15 @@ packages: hasBin: true resolution: integrity: sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + /semver/7.3.4: + dependencies: + lru-cache: 6.0.0 + dev: true + engines: + node: '>=10' + hasBin: true + resolution: + integrity: sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== /send/0.17.1: dependencies: debug: 2.6.9 @@ -22329,7 +22457,7 @@ packages: dependencies: component-emitter: 1.3.0 cookiejar: 2.1.2 - debug: 4.2.0 + debug: 4.3.1 fast-safe-stringify: 2.0.7 form-data: 2.5.1 formidable: 1.2.2 @@ -24275,7 +24403,6 @@ packages: resolution: integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== /yallist/4.0.0: - dev: false resolution: integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== /yaml-loader/0.6.0: @@ -24363,6 +24490,14 @@ packages: node: '>=8' resolution: integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + /yarn/1.22.10: + dev: false + engines: + node: '>=4.0.0' + hasBin: true + requiresBuild: true + resolution: + integrity: sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA== /yauzl/2.10.0: dependencies: buffer-crc32: 0.2.13 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2d3c2d299..9b874fae2 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,4 +3,4 @@ packages: - packages/core/* - packages/plugins/* - website - - '!**/test/**' + - test/e2e-cli diff --git a/test/e2e-cli/.babelrc b/test/e2e-cli/.babelrc new file mode 100644 index 000000000..633f93f42 --- /dev/null +++ b/test/e2e-cli/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "../../.babelrc" +} diff --git a/test/e2e-cli/LICENSE b/test/e2e-cli/LICENSE new file mode 100644 index 000000000..a23b4d909 --- /dev/null +++ b/test/e2e-cli/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Verdaccio + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/test/e2e-cli/README.md b/test/e2e-cli/README.md new file mode 100644 index 000000000..102b81897 --- /dev/null +++ b/test/e2e-cli/README.md @@ -0,0 +1,48 @@ +# E2E Testing + +## What is included on these test? + +- Default configuration only +- Basic commands eg (`install / add`, `info`, `publish`). +- Test with 3 package managers (`yarn classic`, `pnpm` and `npm@7`) + +## How it works? + +On run test suites, there is a global setup where will install the local source code of verdaccio in a temporary folder. +Each suite will install. + +1. `spawn` a registry on port `6001` using `_bootstrap_verdaccio.yaml` which block any local package being + fetched from remote upstream. +2. Publish local project to the spawned registry (with global `pnpm`) + +> The published `verdaccio` should be fetch by each suite to ensure reliability of each test. + +## How to write test? + +Each of the suite must use a package manager command _(eg: `npm install`)_ and validate the output according what the +user see, either verifying the outcome in JSON form, run a command _(`eg: jest ..`)_ and the expected result. + +Each Test should start with the initial setup, this step does the following + +- `beforeAll`: Install verdaccio to the suite context that returns a `Setup` object. +- `afterAll`: Stop the child process that runs verdaccio. + +```js +beforeAll(async () => { + setup = await initialSetup(tempRootFolder, port); + console.log('--setup', setup.install); +}); +``` + +stop the process is the final step that should occur in every suite. + +```js +afterAll(async () => { + setup.child.kill(); +}); +``` + +### What should not included on these tests? + +- Anything is unrelated with client commands usage, eg: (auth permissions, third party integrations, + hooks, plugins) diff --git a/test/e2e-cli/config/_bootstrap_verdaccio.yaml b/test/e2e-cli/config/_bootstrap_verdaccio.yaml index dddb383bc..d049b5759 100644 --- a/test/e2e-cli/config/_bootstrap_verdaccio.yaml +++ b/test/e2e-cli/config/_bootstrap_verdaccio.yaml @@ -12,22 +12,42 @@ web: uplinks: npmjs: url: https://registry.verdaccio.org/ - -logs: { type: stdout, format: json, level: http } + max_fails: 30 + fail_timeout: 10m + timeout: 60s + cache: true + maxage: 30m + agent_options: + keepAlive: true + maxSockets: 40 + maxFreeSockets: 10 +logs: + - { type: stdout, format: pretty, level: warn } packages: - '@*/*': - access: $all + ## ui-theme still lives outside of the core project + '@verdaccio/ui-theme': + access: $anonymous publish: $anonymous - unpublish: $authenticated proxy: npmjs + '@verdaccio/*': + access: $anonymous + publish: $anonymous + '@*/*': + access: $anonymous + publish: $anonymous + unpublish: $anonymous + proxy: npmjs + 'verdaccio-*': + access: $anonymous + publish: $anonymous 'verdaccio': - access: $all + access: $anonymous publish: $anonymous '**': - access: $all + access: $anonymous publish: $anonymous - unpublish: $authenticated + unpublish: $anonymous proxy: npmjs _debug: true diff --git a/test/e2e-cli/config/default.yaml b/test/e2e-cli/config/default.yaml index 524212496..18453210d 100644 --- a/test/e2e-cli/config/default.yaml +++ b/test/e2e-cli/config/default.yaml @@ -1,8 +1,8 @@ storage: ./storage -#store: -# memory: -# limit: 1000 +store: + memory: + limit: 1000 auth: htpasswd: @@ -15,7 +15,7 @@ web: uplinks: local: - url: http://localhost:4873 + url: http://localhost:6001 logs: { type: stdout, format: json, level: http } diff --git a/test/e2e-cli/jest.config.e2e.cli.js b/test/e2e-cli/jest.config.e2e.cli.js index aa679f747..083703fa4 100644 --- a/test/e2e-cli/jest.config.e2e.cli.js +++ b/test/e2e-cli/jest.config.e2e.cli.js @@ -1,6 +1,7 @@ const { defaults } = require('jest-config'); +const config = require('../../jest/config'); -module.exports = { +module.exports = Object.assign({}, config, { name: 'verdaccio-e2e-cli-jest', verbose: true, collectCoverage: false, @@ -8,5 +9,6 @@ module.exports = { testEnvironment: './env_babel.js', globalSetup: './env_setup.js', globalTeardown: './env_teardown.js', - testRegex: '(/test/e2e.*\\.spec)\\.ts', -}; + // testRegex: '(/test/e2e.*\\.spec)\\.ts', + testRegex: '(/test_bk/*.*.spec)\\.ts', +}); diff --git a/test/e2e-cli/package.json b/test/e2e-cli/package.json new file mode 100644 index 000000000..4888cdefe --- /dev/null +++ b/test/e2e-cli/package.json @@ -0,0 +1,19 @@ +{ + "name": "@verdaccio/e2e-cli", + "private": true, + "version": "1.0.0", + "dependencies": { + "debug": "4.3.1", + "npm": "7.0.15", + "pnpm": "5.13.5", + "request": "^2.88.2", + "yarn": "1.22.10" + }, + "devDependencies": { + "get-port": "^5.1.1", + "semver": "^7.3.4" + }, + "scripts": { + "test": "jest --config jest.config.e2e.cli.js" + } +} diff --git a/test/e2e-cli/setup/setup.ts b/test/e2e-cli/setup/setup.ts index 3b9dabaeb..8c4ce2053 100644 --- a/test/e2e-cli/setup/setup.ts +++ b/test/e2e-cli/setup/setup.ts @@ -2,29 +2,64 @@ import fs from 'fs'; import path from 'path'; import os from 'os'; import { spawn } from 'child_process'; +import buildDebug from 'debug'; import { yellow } from 'kleur'; -import { npm } from '../utils/process'; +import { pnpmGlobal } from '../utils/process'; import * as __global from '../utils/global.js'; +const debug = buildDebug('verdaccio:e2e:setup'); + +export const SETUP_VERDACCIO_PORT = `6001`; + module.exports = async () => { const tempRoot = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'verdaccio-cli-e2e-')); + debug('dirname folder %o', __dirname); + debug('temporary folder %o', tempRoot); + // @ts-ignore __global.addItem('dir-root', tempRoot); - console.log(yellow(`Add temp root folder: ${tempRoot}`)); + debug(yellow(`Add temp root folder: ${tempRoot}`)); + const destinationConfigFile = path.join(tempRoot, 'verdaccio.yaml'); + debug('destination config file %o', destinationConfigFile); fs.copyFileSync( path.join(__dirname, '../config/_bootstrap_verdaccio.yaml'), - path.join(tempRoot, 'verdaccio.yaml') + destinationConfigFile ); // @ts-ignore global.__namespace = __global; - console.log(`current directory: ${process.cwd()}`); - // @ts-ignore - global.registryProcess = spawn( - 'node', - [require.resolve('verdaccio/bin/verdaccio'), '-c', './verdaccio.yaml'], - // @ts-ignore - { cwd: tempRoot, silence: true } + debug(`current directory %o`, process.cwd()); + const verdaccioPath = path.normalize( + path.join(process.cwd(), '../../packages/verdaccio/debug/bootstrap.js') ); - + debug(process.env.DEBUG); + debug('verdaccio path %o', verdaccioPath); + const childProcess = spawn( + 'node', + [verdaccioPath, '-c', './verdaccio.yaml', '-l', SETUP_VERDACCIO_PORT], + // @ts-ignore + { + cwd: tempRoot, + env: { + ...process.env, + }, + stdio: 'ignore', + } + ); + // @ts-ignore + global.registryProcess = childProcess; // publish current build version on local registry - await npm('publish', '--registry', 'http://localhost:4873'); + const rootFolder = path.normalize(path.join(process.cwd(), '../../')); + // install the local changes to verdaccio + // the published package will be installed from every suite + await pnpmGlobal( + rootFolder, + 'publish', + '--filter', + ' ./packages', + '--access', + 'public', + '--git-checks', + 'false', + '--registry', + `http://localhost:${SETUP_VERDACCIO_PORT}` + ); }; diff --git a/test/e2e-cli/setup/teardown.ts b/test/e2e-cli/setup/teardown.ts index 88e15cced..11a4e41ef 100644 --- a/test/e2e-cli/setup/teardown.ts +++ b/test/e2e-cli/setup/teardown.ts @@ -1,4 +1,9 @@ +import buildDebug from 'debug'; + +const debug = buildDebug('verdaccio:e2e:teardown'); + module.exports = async function () { + debug('e2e teardown kill server'); // @ts-ignore global.registryProcess.kill(); }; diff --git a/test/e2e-cli/setup/test_environment.ts b/test/e2e-cli/setup/test_environment.ts index afa5dbe3f..c201f01ca 100644 --- a/test/e2e-cli/setup/test_environment.ts +++ b/test/e2e-cli/setup/test_environment.ts @@ -1,24 +1,33 @@ import os from 'os'; import path from 'path'; +import buildDebug from 'debug'; import NodeEnvironment from 'jest-environment-node'; const fs = require('fs'); + const __global = require('../utils/global'); +const debug = buildDebug('verdaccio:e2e:env'); + class E2ECliTestEnvironment extends NodeEnvironment { constructor(config) { super(config); } async setup() { + // create an unique suite location peer test to avoid conflicts const tempRoot = fs.mkdtempSync( path.join(fs.realpathSync(os.tmpdir()), 'verdaccio-suite-test-') ); - __global.addItem('dir-root', tempRoot); + debug('suite temporary folder %o', tempRoot); + __global.addItem('dir-suite-root', tempRoot); + // @ts-ignore this.global.__namespace = __global; - console.log(`current directory: ${process.cwd()}`); + debug(`current directory: ${process.cwd()}`); } - async teardown() {} + async teardown() { + // TODO: clean folder + } runScript(script): any { return super.runScript(script); diff --git a/test/e2e-cli/test/core/info.spec.ts b/test/e2e-cli/test/core/info.spec.ts deleted file mode 100644 index 910a8520d..000000000 --- a/test/e2e-cli/test/core/info.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import path from 'path'; -import { runVerdaccio } from '../../utils/process'; -import { installVerdaccio } from '../__partials/npm_commands'; - -describe('verdaccio info', () => { - jest.setTimeout(90000); - // @ts-ignore - const tempRootFolder = global.__namespace.getItem('dir-root'); - const verdaccioInstall = path.join(tempRootFolder, 'verdaccio-root-info'); - let registryProcess; - - beforeAll(async () => { - await installVerdaccio(verdaccioInstall); - }); - - test('should run verdaccio info command', async () => { - const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { - paths: [verdaccioInstall], - }); - const hasMatch = await runVerdaccio( - pathVerdaccioModule, - verdaccioInstall, - ['--info'], - /Environment/ - ); - - expect(hasMatch.ok).toBeTruthy(); - }); - - afterAll(() => { - registryProcess.kill(); - }); -}); diff --git a/test/e2e-cli/test/core/listen.spec.ts b/test/e2e-cli/test/core/listen.spec.ts deleted file mode 100644 index eecd2ab51..000000000 --- a/test/e2e-cli/test/core/listen.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import path from 'path'; -import fs from 'fs'; -import { installVerdaccio } from '../__partials/npm_commands'; -import { spawnRegistry } from '../../utils/registry'; -import { callRegistry } from '../../utils/web'; - -describe('npm install', () => { - jest.setTimeout(90000); - const port = '9012'; - - // @ts-ignore - const tempRootFolder = global.__namespace.getItem('dir-root'); - const verdaccioInstall = path.join(tempRootFolder, 'verdaccio-root-install'); - let registryProcess; - const configPath = path.join(tempRootFolder, 'verdaccio.yaml'); - - beforeAll(async () => { - await installVerdaccio(verdaccioInstall); - fs.copyFileSync(path.join(__dirname, '../../config/default.yaml'), configPath); - }); - - test('should match the listing port and load metadata', async () => { - const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { - paths: [verdaccioInstall], - }); - - registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { - cwd: verdaccioInstall, - silent: true, - }); - - const body = await callRegistry(`http://localhost:${port}/verdaccio`); - const parsedBody = JSON.parse(body); - - expect(parsedBody.name).toEqual('verdaccio'); - }); - - afterAll(async () => { - registryProcess.kill(); - }); -}); diff --git a/test/e2e-cli/test/install/install.spec.ts b/test/e2e-cli/test/install/install.spec.ts deleted file mode 100644 index 577bce520..000000000 --- a/test/e2e-cli/test/install/install.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import path from 'path'; -import fs from 'fs'; -import * as __global from '../../utils/global'; -import { spawnRegistry } from '../../utils/registry'; -import { execAndWaitForOutputToMatch } from '../../utils/process'; -import { installVerdaccio } from '../__partials/npm_commands'; -import { expectFileToExist } from '../../utils/expect'; - -describe('npm install', () => { - jest.setTimeout(90000); - const port = '9011'; - - // @ts-ignore - const tempRootFolder = global.__namespace.getItem('dir-root'); - const verdaccioInstall = path.join(tempRootFolder, 'verdaccio-root-install'); - let registryProcess; - - beforeAll(async () => { - await installVerdaccio(verdaccioInstall); - - const configPath = path.join(tempRootFolder, 'verdaccio.yaml'); - fs.copyFileSync(path.join(__dirname, '../../config/default.yaml'), configPath); - // @ts-ignore - global.__namespace = __global; - const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { - paths: [verdaccioInstall], - }); - registryProcess = await spawnRegistry(pathVerdaccioModule, ['-c', configPath, '-l', port], { - cwd: verdaccioInstall, - silent: true, - }); - }); - - test('should match on npm info verdaccio', async () => { - // FIXME: not the best match, looking for a better way to match the terminal output - const output = await execAndWaitForOutputToMatch( - 'npm', - ['info', 'verdaccio', '--registry'], - /A lightweight private npm proxy registry/ - ); - - expect(output.ok).toBeTruthy(); - }); - - test('should install jquery', async () => { - const testCwd = path.join(tempRootFolder, '_jquery_'); - await execAndWaitForOutputToMatch( - 'npm', - ['install', '--prefix', testCwd, 'jquery', '--registry', `http://localhost:${port}`], - /''/, - { - cwd: verdaccioInstall, - } - ); - - const exist = await expectFileToExist( - path.join(testCwd, 'node_modules', 'jquery', 'package.json') - ); - expect(exist).toBeTruthy(); - }); - - afterAll(async () => { - registryProcess.kill(); - }); -}); diff --git a/test/e2e-cli/test/__partials/npm_commands.ts b/test/e2e-cli/test_bk/__partials/npm_commands.ts similarity index 89% rename from test/e2e-cli/test/__partials/npm_commands.ts rename to test/e2e-cli/test_bk/__partials/npm_commands.ts index b821777d1..5497b5931 100644 --- a/test/e2e-cli/test/__partials/npm_commands.ts +++ b/test/e2e-cli/test_bk/__partials/npm_commands.ts @@ -7,7 +7,7 @@ export function installVerdaccio(verdaccioInstall) { verdaccioInstall, 'verdaccio', '--registry', - 'http://localhost:4873', + 'http://localhost:6001', '--no-package-lock' ); } diff --git a/test/e2e-cli/test_bk/info.spec.ts b/test/e2e-cli/test_bk/info.spec.ts new file mode 100644 index 000000000..92f8754ee --- /dev/null +++ b/test/e2e-cli/test_bk/info.spec.ts @@ -0,0 +1,37 @@ +import { initialSetup } from '../utils/registry'; +import { npm, pnpm, yarn } from '../utils/process'; + +describe('install a package', () => { + jest.setTimeout(90000); + const port = '9010'; + let registryProcess; + + beforeAll(async () => { + registryProcess = await initialSetup(port); + }); + + test('should run npm info json body', async () => { + const resp = await npm('info', 'verdaccio', '--json'); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.name).toEqual('verdaccio'); + expect(parsedBody.dependencies).toBeDefined(); + }); + + test('should run yarn classic info json body', async () => { + const resp = await yarn('info', 'verdaccio', '--json'); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.data.name).toEqual('verdaccio'); + expect(parsedBody.data.dependencies).toBeDefined(); + }); + + test('should run pnpm info json body', async () => { + const resp = await pnpm('info', 'verdaccio', '--json'); + const parsedBody = JSON.parse(resp.stdout as string); + expect(parsedBody.name).toEqual('verdaccio'); + expect(parsedBody.dependencies).toBeDefined(); + }); + + afterAll(async () => { + registryProcess.child.kill(); + }); +}); diff --git a/test/e2e-cli/test_bk/install.spec.ts b/test/e2e-cli/test_bk/install.spec.ts new file mode 100644 index 000000000..577fa2508 --- /dev/null +++ b/test/e2e-cli/test_bk/install.spec.ts @@ -0,0 +1,61 @@ +import semver from 'semver'; +import { addNpmPrefix, addRegistry, addYarnPrefix, initialSetup, Setup } from '../utils/registry'; +import { npm, pnpm, pnpmWithCwd, yarn, yarnWithCwd } from '../utils/process'; +import { createProject } from '../utils/utils'; + +describe('install a package', () => { + jest.setTimeout(90000); + const port = '9011'; + let setup: Setup; + + beforeAll(async () => { + setup = await initialSetup(port); + }); + + test('should run npm install', async () => { + const projectFolder = createProject('webpack-npm-jest'); + const resp = await npm( + 'install', + 'jest', + '--json', + ...addNpmPrefix(projectFolder), + ...addRegistry(port) + ); + expect(resp.stderr).toBeUndefined(); + + const resp2 = await npm('run', 'jest', '--version', ...addNpmPrefix(projectFolder)); + expect(semver.valid(resp2.stdout)).toBeTruthy(); + }); + + test('should run pnpm install', async () => { + const projectFolder = createProject('webpack-pnpm-test'); + const resp = await pnpm( + 'install', + 'jest@26.6.3', + ...addNpmPrefix(projectFolder), + ...addRegistry(port) + ); + expect(resp.stderr).toBeUndefined(); + + // TODO: verify package was correctly installed + }); + + test('should run yarn classic install', async () => { + const projectFolder = createProject('jest-yarn-test'); + const resp = await yarn( + 'add', + 'jest@26.6.3', + ...addYarnPrefix(projectFolder), + ...addRegistry(port) + ); + expect(resp.stderr).toBeUndefined(); + + const resp2 = await yarnWithCwd(projectFolder, 'jest', '--version'); + // yarn output is to verbose + expect(resp2.stdout).toMatch(/26.6.3/); + }); + + afterAll(async () => { + setup.child.kill(); + }); +}); diff --git a/test/e2e-cli/test_bk/listen.spec.ts b/test/e2e-cli/test_bk/listen.spec.ts new file mode 100644 index 000000000..09dcc6976 --- /dev/null +++ b/test/e2e-cli/test_bk/listen.spec.ts @@ -0,0 +1,23 @@ +import { initialSetup } from '../utils/registry'; +import { callRegistry } from '../utils/web'; + +describe('install a package', () => { + jest.setTimeout(90000); + const port = '9012'; + let registryProcess; + + beforeAll(async () => { + registryProcess = await initialSetup(port); + }); + + test('should match the listing port and load metadata', async () => { + const body = await callRegistry(`http://localhost:${port}/verdaccio`); + const parsedBody = JSON.parse(body); + + expect(parsedBody.name).toEqual('verdaccio'); + }); + + afterAll(async () => { + registryProcess.child.kill(); + }); +}); diff --git a/test/e2e-cli/tsconfig.json b/test/e2e-cli/tsconfig.json new file mode 100644 index 000000000..385a6f173 --- /dev/null +++ b/test/e2e-cli/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.reference.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./build" + } +} diff --git a/test/e2e-cli/utils/global.js b/test/e2e-cli/utils/global.js index 8cff9d73f..bd222b2ee 100644 --- a/test/e2e-cli/utils/global.js +++ b/test/e2e-cli/utils/global.js @@ -1,11 +1,14 @@ const namespace = Object.create(null); +import buildDebug from 'debug'; + +const debug = buildDebug('verdaccio:e2e:global'); exports.addItem = function (name, value) { namespace[name] = value; }; exports.getItem = function (name) { - console.log('get-item', name, namespace); + debug('get-item %o:%o', name, namespace); if (!(name in namespace)) { throw new Error('The item '.concat(name, ' does exist in the namespace')); } diff --git a/test/e2e-cli/utils/process.ts b/test/e2e-cli/utils/process.ts index e8bca4187..04e8e6db8 100644 --- a/test/e2e-cli/utils/process.ts +++ b/test/e2e-cli/utils/process.ts @@ -1,17 +1,26 @@ -import * as child_process from 'child_process'; +import { spawn } from 'child_process'; import { SpawnOptions } from 'child_process'; +import readline from 'readline'; +import buildDebug from 'debug'; -export async function _exec(options, cmd, args) { +const debug = buildDebug('verdaccio:e2e:process'); + +export type ExecOutput = { + stdout: string; + stderr: string; +}; + +export async function _exec(options: SpawnOptions, cmd, args): Promise { + debug('start _exec %o %o %o', options, cmd, args); let stdout = ''; - let stderr = ''; - const flags = []; - const cwd = process.cwd(); + let stderr; const env = options.env; - console.log(`Running \`${cmd} ${args.map((x) => `"${x}"`).join(' ')}\`${flags}...`); - console.log(`CWD: ${cwd}`); - console.log(`ENV: ${JSON.stringify(env)}`); + debug(`Running \`${cmd} ${args.join(' ')}`); + debug(`CWD: %o`, options.cwd); + debug(`ENV: ${JSON.stringify(env)}`); const spawnOptions = { - cwd, + cwd: options.cwd, + stdio: options.stdio || 'pipe', ...(env ? { env } : {}), }; @@ -21,31 +30,11 @@ export async function _exec(options, cmd, args) { spawnOptions['stdio'] = 'pipe'; } - const childProcess = child_process.spawn(cmd, args, spawnOptions); - childProcess.stdout.on('data', (data) => { - stdout += data.toString('utf-8'); - if (options.silent) { - return; - } + const childProcess = spawn(cmd, args, spawnOptions); + const rl = readline.createInterface({ input: childProcess.stdout }); - data - .toString('utf-8') - .split(/[\n\r]+/) - .filter((line) => line !== '') - .forEach((line) => console.log(' ' + line)); - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString('utf-8'); - if (options.silent) { - return; - } - - data - .toString('utf-8') - .split(/[\n\r]+/) - .filter((line) => line !== '') - .forEach((line) => console.error(' ' + line)); + rl.on('line', function (line) { + stdout += line; }); const err = new Error(`Running "${cmd} ${args.join(' ')}" returned error code `); @@ -55,44 +44,59 @@ export async function _exec(options, cmd, args) { resolve({ stdout, stderr }); } else { err.message += `${error}...\n\nSTDOUT:\n${stdout}\n\nSTDERR:\n${stderr}\n`; - reject(err); + reject({ stdout, stderr: err }); } }); - - if (options.waitForMatch) { - const match = options.waitForMatch; - childProcess.stdout.on('data', (data) => { - // console.log("-->data==>", data.toString(), data.toString().match(match)); - if (data.toString().match(match)) { - resolve({ ok: true, stdout, stderr }); - } - }); - childProcess.stderr.on('data', (data) => { - if (data.toString().match(match)) { - resolve({ stdout, stderr }); - } - }); - } }); } -export function execAndWaitForOutputToMatch( - cmd: string, - args: string[], - match: RegExp, - spawnOptions: SpawnOptions = {} -): any { - return _exec({ waitForMatch: match, ...spawnOptions, silence: true }, cmd, args); +// export function execAndWaitForOutputToMatch( +// cmd: string, +// args: string[], +// match: RegExp, +// spawnOptions: SpawnOptions = {} +// ): any { +// return _exec({ waitForMatch: match, ...spawnOptions, silence: true }, cmd, args); +// } + +export function pnpmGlobal(rootFolder, ...args) { + const pnpmCmd = require.resolve('pnpm'); + debug('pnpmCommand %o', pnpmCmd); + debug('run pnpm on %o', rootFolder); + return _exec( + { + cwd: rootFolder, + }, + 'pnpm', + args + ); } -export function npm(...args) { +export function npm(...args): Promise { return _exec({}, 'npm', args); } -export function runVerdaccio(cmd, installation, args, match: RegExp): any { - return _exec({ cwd: installation, silent: true, waitForMatch: match }, cmd, args); +export function yarn(...args): Promise { + return _exec({}, 'yarn', args); } -export function silentNpm(...args) { +export function pnpm(...args): Promise { + return _exec({}, 'pnpm', args); +} + +export function pnpmWithCwd(cwd, ...args): Promise { + return _exec({ cwd }, 'pnpm', args); +} + +export function yarnWithCwd(cwd, ...args): Promise { + return _exec({ cwd }, 'yarn', args); +} + +export function nodeCwd(cwd, ...args): Promise { + return _exec({ cwd }, 'yarn', args); +} + +export function silentNpm(...args): Promise { + debug('run silent npm %o', args); return _exec({ silent: true }, 'npm', args); } diff --git a/test/e2e-cli/utils/registry.spec.ts b/test/e2e-cli/utils/registry.spec.ts new file mode 100644 index 000000000..a4667447d --- /dev/null +++ b/test/e2e-cli/utils/registry.spec.ts @@ -0,0 +1,7 @@ +import { addNpmPrefix } from './registry'; + +describe('registry utils', function () { + test('prefix', () => { + expect([...addNpmPrefix('foo')]).toEqual(''); + }); +}); diff --git a/test/e2e-cli/utils/registry.ts b/test/e2e-cli/utils/registry.ts index b10964fc0..a2519e64c 100644 --- a/test/e2e-cli/utils/registry.ts +++ b/test/e2e-cli/utils/registry.ts @@ -1,20 +1,134 @@ /* eslint-disable prefer-promise-reject-errors */ -import { fork } from 'child_process'; +import { ChildProcess, fork } from 'child_process'; +import path from 'path'; +import fs from 'fs'; +import buildDebug from 'debug'; -export function spawnRegistry(verdaccioPath: string, args: string[], childOptions) { +import { silentNpm } from './process'; + +const debug = buildDebug('verdaccio:e2e:registry-utils'); + +export function createInstallationFolder(tempRootFolder) { + const verdaccioInstall = path.join(tempRootFolder, 'verdaccio-root-install'); + fs.mkdirSync(verdaccioInstall); + return verdaccioInstall; +} + +export function addNpmPrefix(installFolder) { + return ['--prefix', installFolder]; +} + +export function addYarnPrefix(installFolder) { + // info regarding cwd flag + // https://github.com/yarnpkg/yarn/pull/4174 + return ['--cwd', installFolder]; +} + +export function addRegistry(port) { + return ['--registry', `http://localhost:${port}`]; +} + +export function installVerdaccio(verdaccioInstall) { + debug('installing verdaccio from internal registry'); + return silentNpm( + 'install', + ...addNpmPrefix(verdaccioInstall), + 'verdaccio', + ...addRegistry('6001'), + // lock file is not useful for this purpose + '--no-package-lock', + '-no-shrinkwrap', + // reduce external calls and potential test failures + '--no-audit' + ); +} + +export type Setup = { + child: ChildProcess; + install: string; +}; + +export async function initialSetup(port: string | number): Promise { + // temp folder created on test_environment.ts + const tempRootFolder = global.__namespace.getItem('dir-suite-root'); + debug('initial setup on %o and port %o', tempRootFolder, port); + // create temporary installation folder + const verdaccioInstall = createInstallationFolder(tempRootFolder); + debug('install folder %o', verdaccioInstall); + // create a file path for the future the configuration file + const verdaccioConfigPathOnInstallLocation = path.join(tempRootFolder, 'verdaccio.yaml'); + debug('config file location %o', verdaccioConfigPathOnInstallLocation); + // install a global verdaccio + debug('install verdaccio start'); + await installVerdaccio(verdaccioInstall); + debug('install verdaccio finish'); + // copy the original config verdaccio file + fs.copyFileSync( + path.join(__dirname, '../../../packages/config/src/conf/default.yaml'), + verdaccioConfigPathOnInstallLocation + ); + // location of verdaccio binary installed in the previous step + const pathVerdaccioModule = require.resolve('verdaccio/bin/verdaccio', { + paths: [verdaccioInstall], + }); + debug('path verdaccio module %o', pathVerdaccioModule); + // spawn the registry + const processChild = await forkRegistry( + pathVerdaccioModule, + ['-c', verdaccioConfigPathOnInstallLocation, '-l', port], + { + cwd: verdaccioInstall, + silent: false, + }, + port + ); + + return { + child: processChild, + install: verdaccioInstall, + }; +} + +export function getVerdaccioPath() { + const verdaccioPath = path.normalize( + path.join(process.cwd(), '../../packages/verdaccio/debug/bootstrap.js') + ); + + return verdaccioPath; +} + +export function forkRegistry( + verdaccioPath: string, + args: string[], + childOptions, + port +): Promise { + debug('spawning registry for %o in port %o', verdaccioPath, port); return new Promise((resolve, reject) => { let _childOptions = { silent: true, ...childOptions }; - + debug('options %o', _childOptions); + debug('fork path %o', verdaccioPath); + debug('args %o', args); const childFork = fork(verdaccioPath, args, _childOptions); - childFork.on('message', (msg: {verdaccio_started: boolean}) => { - if (msg.verdaccio_started) { + childFork.on('message', (msg) => { + if ('verdaccio_started' in msg) { + debug('spawning registry [started] in port %o', port); resolve(childFork); } }); - childFork.on('error', (err) => reject([err])); - childFork.on('disconnect', (err) => reject([err])); - childFork.on('exit', (err) => reject([err])); + childFork.on('error', (err) => { + debug('error %o', err); + reject([err]); + }); + childFork.on('disconnect', (err) => { + debug('disconnect %o', err); + reject([err]); + }); + childFork.on('exit', (err) => { + debug('exit %o', err); + reject([err]); + }); }); } diff --git a/test/e2e-cli/utils/utils.ts b/test/e2e-cli/utils/utils.ts index e648a3bba..a45343b44 100644 --- a/test/e2e-cli/utils/utils.ts +++ b/test/e2e-cli/utils/utils.ts @@ -1,6 +1,14 @@ import path from 'path'; import fs from 'fs'; +export function createProject(projectName: string) { + // @ts-ignore + const tempRootFolder = global.__namespace.getItem('dir-suite-root'); + const verdaccioInstall = path.join(tempRootFolder, projectName); + fs.mkdirSync(verdaccioInstall); + + return verdaccioInstall; +} export function copyConfigFile(rootFolder, configTemplate): string { const configPath = path.join(rootFolder, 'verdaccio.yaml'); fs.copyFileSync(path.join(__dirname, configTemplate), configPath);