Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuy Adorno <ruyadorno@hotmail.com>2021-03-25 07:45:30 +0300
committerRuy Adorno <ruyadorno@hotmail.com>2021-03-26 00:32:24 +0300
commit97b41528739460b2e9e72e09000aded412418cb2 (patch)
tree98236ceca0ff02dc8528f674d09d319a7cc871de
parent59cf37962a2286e0f7d3bd37fa9c8bc3bac94218 (diff)
add smoke tests
Lightweight smoke test suite that runs common commands so that we can also have a holistic check during CI. PR-URL: https://github.com/npm/cli/pull/2959 Credit: @ruyadorno Close: #2959 Reviewed-by: @nlf
-rw-r--r--.github/workflows/ci.yml42
-rw-r--r--.npmignore4
-rw-r--r--Makefile5
-rw-r--r--package.json3
-rw-r--r--smoke-tests/content/abbrev.json449
-rw-r--r--smoke-tests/content/abbrev.min.json89
-rw-r--r--smoke-tests/content/abbrev/-/abbrev-1.0.4.tgzbin0 -> 2295 bytes
-rw-r--r--smoke-tests/content/abbrev/-/abbrev-1.1.1.tgzbin0 -> 2301 bytes
-rw-r--r--smoke-tests/content/promise-all-reject-late.json138
-rw-r--r--smoke-tests/content/promise-all-reject-late.min.json44
-rw-r--r--smoke-tests/content/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgzbin0 -> 30838 bytes
-rw-r--r--smoke-tests/index.js196
-rw-r--r--smoke-tests/server.js276
-rw-r--r--tap-snapshots/smoke-tests-index.js-TAP.test.js649
14 files changed, 1893 insertions, 2 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 851b3fdcb..14f362b45 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -37,6 +37,48 @@ jobs:
- name: Run linting
run: node . run licenses
+ smoke-tests:
+ strategy:
+ fail-fast: false
+ matrix:
+ node-version: [10.x, 12.x, 14.x]
+ platform:
+ - os: ubuntu-latest
+ shell: bash
+ - os: macos-latest
+ shell: bash
+ - os: windows-latest
+ shell: bash
+ - os: windows-latest
+ shell: powershell
+
+ runs-on: ${{ matrix.platform.os }}
+ defaults:
+ run:
+ shell: ${{ matrix.platform.shell }}
+
+ steps:
+ # Checkout the npm/cli repo
+ - uses: actions/checkout@v2
+
+ # Installs the specific version of Node.js
+ - name: Use Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v1
+ with:
+ node-version: ${{ matrix.node-version }}
+
+ # Run the installer script
+ - name: Install dependencies
+ run: |
+ node . install --ignore-scripts --no-audit
+ node . rebuild
+
+ # Run the smoke tests
+ - name: Run Smoke tests
+ run: node . run --ignore-scripts smoke-tests -- --no-check-coverage -t600 -Rbase -c
+ env:
+ DEPLOY_VERSION: testing
+
build:
strategy:
fail-fast: false
diff --git a/.npmignore b/.npmignore
index 409905efd..9d02b99f9 100644
--- a/.npmignore
+++ b/.npmignore
@@ -39,3 +39,7 @@ docs/template.html
Session.vim
.nyc_output
/.editorconfig
+
+# don't ship smoke tests
+smoke-tests/
+tap-snapshots/smoke-tests-index.js-TAP.test.js
diff --git a/Makefile b/Makefile
index 656f64f79..b8add91b6 100644
--- a/Makefile
+++ b/Makefile
@@ -76,6 +76,9 @@ docs/content/using-npm/config.md: scripts/config-doc.js lib/utils/config/*.js
test: dev-deps
node bin/npm-cli.js test
+smoke-tests: dev-deps
+ node bin/npm-cli.js run smoke-tests
+
ls-ok:
node . ls --production >/dev/null
@@ -93,7 +96,7 @@ prune:
@[[ "$(shell git status -s)" != "" ]] && echo "ERR: found unpruned files" && exit 1 || echo "git status is clean"
-publish: gitclean ls-ok link test docs prune
+publish: gitclean ls-ok link test smoke-tests docs prune
@git push origin :v$(shell node bin/npm-cli.js --no-timing -v) 2>&1 || true
git push origin $(BRANCH) &&\
git push origin --tags &&\
diff --git a/package.json b/package.json
index 4d531d7de..2dcc65543 100644
--- a/package.json
+++ b/package.json
@@ -207,7 +207,8 @@
"lint": "npm run eslint -- test/lib test/bin \"lib/**/*.js\"",
"lintfix": "npm run lint -- --fix",
"prelint": "rimraf test/npm_cache*",
- "resetdeps": "bash scripts/resetdeps.sh"
+ "resetdeps": "bash scripts/resetdeps.sh",
+ "smoke-tests": "tap smoke-tests/index.js"
},
"//": [
"XXX temporarily only run unit tests while v7 beta is in progress",
diff --git a/smoke-tests/content/abbrev.json b/smoke-tests/content/abbrev.json
new file mode 100644
index 000000000..ffcf5474a
--- /dev/null
+++ b/smoke-tests/content/abbrev.json
@@ -0,0 +1,449 @@
+{
+ "_id": "abbrev",
+ "_rev": "72-d1d46bef3d311d6da6737e109e771869",
+ "name": "abbrev",
+ "dist-tags": {
+ "latest": "1.1.1"
+ },
+ "versions": {
+ "1.0.3": {
+ "name": "abbrev",
+ "version": "1.0.3",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "./lib/abbrev.js",
+ "scripts": {
+ "test": "node lib/abbrev.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/isaacs/abbrev-js.git"
+ },
+ "_id": "abbrev@1.0.3",
+ "engines": {
+ "node": "*"
+ },
+ "_engineSupported": true,
+ "_npmVersion": "1.0.0rc7",
+ "_nodeVersion": "v0.5.0-pre",
+ "_defaultsLoaded": true,
+ "dist": {
+ "shasum": "aa049c967f999222aa42e14434f0c562ef468241",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.3.tgz"
+ },
+ "directories": {}
+ },
+ "1.0.4": {
+ "name": "abbrev",
+ "version": "1.0.4",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "./lib/abbrev.js",
+ "scripts": {
+ "test": "node lib/abbrev.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/isaacs/abbrev-js"
+ },
+ "license": {
+ "type": "MIT",
+ "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE"
+ },
+ "_id": "abbrev@1.0.4",
+ "dist": {
+ "shasum": "bd55ae5e413ba1722ee4caba1f6ea10414a59ecd",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz"
+ },
+ "_npmVersion": "1.1.70",
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "directories": {}
+ },
+ "1.0.5": {
+ "name": "abbrev",
+ "version": "1.0.5",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "abbrev.js",
+ "scripts": {
+ "test": "node test.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/isaacs/abbrev-js"
+ },
+ "license": {
+ "type": "MIT",
+ "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE"
+ },
+ "bugs": {
+ "url": "https://github.com/isaacs/abbrev-js/issues"
+ },
+ "homepage": "https://github.com/isaacs/abbrev-js",
+ "_id": "abbrev@1.0.5",
+ "_shasum": "5d8257bd9ebe435e698b2fa431afde4fe7b10b03",
+ "_from": ".",
+ "_npmVersion": "1.4.7",
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "dist": {
+ "shasum": "5d8257bd9ebe435e698b2fa431afde4fe7b10b03",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz"
+ },
+ "directories": {}
+ },
+ "1.0.6": {
+ "name": "abbrev",
+ "version": "1.0.6",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "abbrev.js",
+ "scripts": {
+ "test": "node test.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
+ },
+ "license": "ISC",
+ "gitHead": "648a6735d9c5a7a04885e3ada49eed4db36181c2",
+ "bugs": {
+ "url": "https://github.com/isaacs/abbrev-js/issues"
+ },
+ "homepage": "https://github.com/isaacs/abbrev-js#readme",
+ "_id": "abbrev@1.0.6",
+ "_shasum": "b6d632b859b3fa2d6f7e4b195472461b9e32dc30",
+ "_from": ".",
+ "_npmVersion": "2.10.0",
+ "_nodeVersion": "2.0.1",
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "isaacs@npmjs.com"
+ },
+ "dist": {
+ "shasum": "b6d632b859b3fa2d6f7e4b195472461b9e32dc30",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.6.tgz"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "directories": {}
+ },
+ "1.0.7": {
+ "name": "abbrev",
+ "version": "1.0.7",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "abbrev.js",
+ "scripts": {
+ "test": "tap test.js --cov"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
+ },
+ "license": "ISC",
+ "devDependencies": {
+ "tap": "^1.2.0"
+ },
+ "gitHead": "821d09ce7da33627f91bbd8ed631497ed6f760c2",
+ "bugs": {
+ "url": "https://github.com/isaacs/abbrev-js/issues"
+ },
+ "homepage": "https://github.com/isaacs/abbrev-js#readme",
+ "_id": "abbrev@1.0.7",
+ "_shasum": "5b6035b2ee9d4fb5cf859f08a9be81b208491843",
+ "_from": ".",
+ "_npmVersion": "2.10.1",
+ "_nodeVersion": "2.0.1",
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "isaacs@npmjs.com"
+ },
+ "dist": {
+ "shasum": "5b6035b2ee9d4fb5cf859f08a9be81b208491843",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "directories": {}
+ },
+ "1.0.9": {
+ "name": "abbrev",
+ "version": "1.0.9",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "abbrev.js",
+ "scripts": {
+ "test": "tap test.js --cov"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
+ },
+ "license": "ISC",
+ "devDependencies": {
+ "tap": "^5.7.2"
+ },
+ "files": [
+ "abbrev.js"
+ ],
+ "gitHead": "c386cd9dbb1d8d7581718c54d4ba944cc9298d6f",
+ "bugs": {
+ "url": "https://github.com/isaacs/abbrev-js/issues"
+ },
+ "homepage": "https://github.com/isaacs/abbrev-js#readme",
+ "_id": "abbrev@1.0.9",
+ "_shasum": "91b4792588a7738c25f35dd6f63752a2f8776135",
+ "_from": ".",
+ "_npmVersion": "3.9.1",
+ "_nodeVersion": "4.4.4",
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ "dist": {
+ "shasum": "91b4792588a7738c25f35dd6f63752a2f8776135",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "_npmOperationalInternal": {
+ "host": "packages-16-east.internal.npmjs.com",
+ "tmp": "tmp/abbrev-1.0.9.tgz_1466016055839_0.7825860097073019"
+ },
+ "directories": {}
+ },
+ "1.1.0": {
+ "name": "abbrev",
+ "version": "1.1.0",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "abbrev.js",
+ "scripts": {
+ "test": "tap test.js --100",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "postpublish": "git push origin --all; git push origin --tags"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
+ },
+ "license": "ISC",
+ "devDependencies": {
+ "tap": "^10.1"
+ },
+ "files": [
+ "abbrev.js"
+ ],
+ "gitHead": "7136d4d95449dc44115d4f78b80ec907724f64e0",
+ "bugs": {
+ "url": "https://github.com/isaacs/abbrev-js/issues"
+ },
+ "homepage": "https://github.com/isaacs/abbrev-js#readme",
+ "_id": "abbrev@1.1.0",
+ "_shasum": "d0554c2256636e2f56e7c2e5ad183f859428d81f",
+ "_from": ".",
+ "_npmVersion": "4.3.0",
+ "_nodeVersion": "8.0.0-pre",
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ "dist": {
+ "shasum": "d0554c2256636e2f56e7c2e5ad183f859428d81f",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "_npmOperationalInternal": {
+ "host": "packages-12-west.internal.npmjs.com",
+ "tmp": "tmp/abbrev-1.1.0.tgz_1487054000015_0.9229173036292195"
+ },
+ "directories": {}
+ },
+ "1.1.1": {
+ "name": "abbrev",
+ "version": "1.1.1",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "main": "abbrev.js",
+ "scripts": {
+ "test": "tap test.js --100",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "postpublish": "git push origin --all; git push origin --tags"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
+ },
+ "license": "ISC",
+ "devDependencies": {
+ "tap": "^10.1"
+ },
+ "files": [
+ "abbrev.js"
+ ],
+ "gitHead": "a9ee72ebc8fe3975f1b0c7aeb3a8f2a806a432eb",
+ "bugs": {
+ "url": "https://github.com/isaacs/abbrev-js/issues"
+ },
+ "homepage": "https://github.com/isaacs/abbrev-js#readme",
+ "_id": "abbrev@1.1.1",
+ "_npmVersion": "5.4.2",
+ "_nodeVersion": "8.5.0",
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ "dist": {
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "shasum": "f8f2c887ad10bf67f634f005b6987fed3179aac8",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz"
+ },
+ "maintainers": [
+ {
+ "name": "gabra",
+ "email": "jerry+1@npmjs.com"
+ },
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "_npmOperationalInternal": {
+ "host": "s3://npm-registry-packages",
+ "tmp": "tmp/abbrev-1.1.1.tgz_1506566833068_0.05750026390887797"
+ },
+ "directories": {}
+ }
+ },
+ "maintainers": [
+ {
+ "email": "quitlahok@gmail.com",
+ "name": "nlf"
+ },
+ {
+ "email": "ruyadorno@hotmail.com",
+ "name": "ruyadorno"
+ },
+ {
+ "email": "darcy@darcyclarke.me",
+ "name": "darcyclarke"
+ },
+ {
+ "email": "evilpacket@gmail.com",
+ "name": "adam_baldwin"
+ },
+ {
+ "email": "i@izs.me",
+ "name": "isaacs"
+ }
+ ],
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me"
+ },
+ "description": "Like ruby's abbrev module, but in js",
+ "time": {
+ "modified": "2020-10-13T05:04:03.636Z",
+ "created": "2011-03-21T22:21:11.183Z",
+ "1.0.1": "2011-03-21T22:21:11.183Z",
+ "1.0.2": "2011-03-21T22:21:11.183Z",
+ "1.0.3": "2011-03-21T22:21:11.183Z",
+ "1.0.3-1": "2011-03-24T23:01:19.581Z",
+ "1.0.4": "2013-01-09T00:01:24.135Z",
+ "1.0.5": "2014-04-17T20:09:12.523Z",
+ "1.0.6": "2015-05-21T00:58:16.778Z",
+ "1.0.7": "2015-05-30T22:57:54.685Z",
+ "1.0.9": "2016-06-15T18:41:01.215Z",
+ "1.1.0": "2017-02-14T06:33:20.235Z",
+ "1.1.1": "2017-09-28T02:47:13.220Z"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/isaacs/abbrev-js.git"
+ },
+ "users": {
+ "leesei": true,
+ "ceejbot": true,
+ "isaacs": true,
+ "npm-www": true,
+ "tunnckocore": true,
+ "ruanyu1": true,
+ "leodutra": true,
+ "jessaustin": true,
+ "jian263994241": true,
+ "floriannagel": true,
+ "tdmalone": true,
+ "ryanve": true,
+ "detj": true,
+ "monjer": true,
+ "d-band": true
+ },
+ "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n",
+ "readmeFilename": "README.md",
+ "homepage": "https://github.com/isaacs/abbrev-js#readme",
+ "bugs": {
+ "url": "https://github.com/isaacs/abbrev-js/issues"
+ },
+ "license": "ISC"
+}
diff --git a/smoke-tests/content/abbrev.min.json b/smoke-tests/content/abbrev.min.json
new file mode 100644
index 000000000..c03d91c9c
--- /dev/null
+++ b/smoke-tests/content/abbrev.min.json
@@ -0,0 +1,89 @@
+{
+ "name": "abbrev",
+ "dist-tags": {
+ "latest": "1.1.1"
+ },
+ "versions": {
+ "1.0.3": {
+ "name": "abbrev",
+ "version": "1.0.3",
+ "dist": {
+ "shasum": "aa049c967f999222aa42e14434f0c562ef468241",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.3.tgz"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "1.0.4": {
+ "name": "abbrev",
+ "version": "1.0.4",
+ "dist": {
+ "shasum": "bd55ae5e413ba1722ee4caba1f6ea10414a59ecd",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz"
+ }
+ },
+ "1.0.5": {
+ "name": "abbrev",
+ "version": "1.0.5",
+ "dist": {
+ "shasum": "5d8257bd9ebe435e698b2fa431afde4fe7b10b03",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz"
+ }
+ },
+ "1.0.6": {
+ "name": "abbrev",
+ "version": "1.0.6",
+ "dist": {
+ "shasum": "b6d632b859b3fa2d6f7e4b195472461b9e32dc30",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.6.tgz"
+ }
+ },
+ "1.0.7": {
+ "name": "abbrev",
+ "version": "1.0.7",
+ "devDependencies": {
+ "tap": "^1.2.0"
+ },
+ "dist": {
+ "shasum": "5b6035b2ee9d4fb5cf859f08a9be81b208491843",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz"
+ }
+ },
+ "1.0.9": {
+ "name": "abbrev",
+ "version": "1.0.9",
+ "devDependencies": {
+ "tap": "^5.7.2"
+ },
+ "dist": {
+ "shasum": "91b4792588a7738c25f35dd6f63752a2f8776135",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz"
+ }
+ },
+ "1.1.0": {
+ "name": "abbrev",
+ "version": "1.1.0",
+ "devDependencies": {
+ "tap": "^10.1"
+ },
+ "dist": {
+ "shasum": "d0554c2256636e2f56e7c2e5ad183f859428d81f",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz"
+ }
+ },
+ "1.1.1": {
+ "name": "abbrev",
+ "version": "1.1.1",
+ "devDependencies": {
+ "tap": "^10.1"
+ },
+ "dist": {
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "shasum": "f8f2c887ad10bf67f634f005b6987fed3179aac8",
+ "tarball": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz"
+ }
+ }
+ },
+ "modified": "2020-10-13T05:04:03.636Z"
+}
diff --git a/smoke-tests/content/abbrev/-/abbrev-1.0.4.tgz b/smoke-tests/content/abbrev/-/abbrev-1.0.4.tgz
new file mode 100644
index 000000000..dfd1b5591
--- /dev/null
+++ b/smoke-tests/content/abbrev/-/abbrev-1.0.4.tgz
Binary files differ
diff --git a/smoke-tests/content/abbrev/-/abbrev-1.1.1.tgz b/smoke-tests/content/abbrev/-/abbrev-1.1.1.tgz
new file mode 100644
index 000000000..4d9504504
--- /dev/null
+++ b/smoke-tests/content/abbrev/-/abbrev-1.1.1.tgz
Binary files differ
diff --git a/smoke-tests/content/promise-all-reject-late.json b/smoke-tests/content/promise-all-reject-late.json
new file mode 100644
index 000000000..e243b92a3
--- /dev/null
+++ b/smoke-tests/content/promise-all-reject-late.json
@@ -0,0 +1,138 @@
+{
+ "_id": "promise-all-reject-late",
+ "_rev": "1-bb2ac9479869cc8479d1dd01c568acc0",
+ "name": "promise-all-reject-late",
+ "dist-tags": {
+ "latest": "1.0.1"
+ },
+ "versions": {
+ "1.0.0": {
+ "name": "promise-all-reject-late",
+ "version": "1.0.0",
+ "description": "Like Promise.all, but save rejections until all promises are resolved",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me",
+ "url": "https://izs.me"
+ },
+ "license": "ISC",
+ "scripts": {
+ "test": "tap",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "prepublishOnly": "git push origin --follow-tags"
+ },
+ "tap": {
+ "check-coverage": true
+ },
+ "devDependencies": {
+ "tap": "^14.10.5"
+ },
+ "gitHead": "e9614a15b22f421aa97ff281d4e0f23681edbe98",
+ "_id": "promise-all-reject-late@1.0.0",
+ "_nodeVersion": "13.3.0",
+ "_npmVersion": "6.13.4",
+ "dist": {
+ "integrity": "sha512-f5XvVl++12pEo7Sv7f7FGfzVuVpeY2msNKjn7nNcXyOSKh5uVu7IAzDO6RE9hDVoHJhxvg+gqEacwkZ891Se5g==",
+ "shasum": "4fa37515e2d78c3b0462414402a8debce62b8b9f",
+ "tarball": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.0.tgz",
+ "fileCount": 7,
+ "unpackedSize": 123039,
+ "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeBmldCRA9TVsSAnZWagAAaigP/2CarvNCbglNS0dgjOoH\n7ZuFo1cG+N8BkZct00TyEJjuB+5UUmv9TSnZogfEOGutvMqUTSRhvm3fOWsJ\n7TXs8zJ6SotDR9+xlxqi/skpYXfRdNjdaMvo9kYO5jaV84pstdbl17sPeYXd\nCudbAKp1sYodlaJyqpyfUd2PWUNe/VGLODmjLogHB4/bevT3tdjsdauKrUS4\n3VFw8sS1Fwp7P2YneNIK3C1TY/Yb66KysZO23VsQemCQFKXpQJMa9B6yj8zs\n5BQp+W5tM70IfW6OXD0+Vt2jWr9jmKmoWVEiL5usJT3zD7vRbeH3xQvSEgDD\nskI8vH8iJ+3EbEOWTGlIu7mX88Dp2KnHOoRUkOR03WJWuGnsTC8Uyqi0F1Xd\nFeFlaeNzynR/R2LcdRNiFOM+1xtzfAtVGF7TIp9UjgJwSNNkEMlkNzQqSiC7\n/AeqsAYoBBNmYWY2fvXdS9HQ4HfIGjI++jCYWX4I7sUvOjqfcwlEz8MwromA\nqeBAFPdvnB0F/q/AOOLkcdsO81jES7ts0nB7bDt0rDbztWWq34BSMDnNoSDo\nDE9q8u7g68tQcr3WmOQr4ro10sSbJVJZmz8DSJKCbVJ+FN0+GM+49oyyhIFl\nOjokXn5U8ASEdiZnmFnt51dr9A4fyjhehotJA6qSs7t2fBe86VnufijC971U\nv3Jc\r\n=lLwf\r\n-----END PGP SIGNATURE-----\r\n"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ "directories": {},
+ "_npmOperationalInternal": {
+ "host": "s3://npm-registry-packages",
+ "tmp": "tmp/promise-all-reject-late_1.0.0_1577478492470_0.9438095135747766"
+ },
+ "_hasShrinkwrap": false
+ },
+ "1.0.1": {
+ "name": "promise-all-reject-late",
+ "version": "1.0.1",
+ "description": "Like Promise.all, but save rejections until all promises are resolved",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me",
+ "url": "https://izs.me"
+ },
+ "license": "ISC",
+ "scripts": {
+ "test": "tap",
+ "preversion": "npm test",
+ "postversion": "npm publish",
+ "prepublishOnly": "git push origin --follow-tags"
+ },
+ "tap": {
+ "check-coverage": true
+ },
+ "devDependencies": {
+ "tap": "^14.10.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "gitHead": "c892a9db86650c9229ab4cc70395106684d6818a",
+ "_id": "promise-all-reject-late@1.0.1",
+ "_nodeVersion": "12.14.1",
+ "_npmVersion": "6.13.6",
+ "dist": {
+ "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==",
+ "shasum": "f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2",
+ "tarball": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz",
+ "fileCount": 8,
+ "unpackedSize": 123171,
+ "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeL65kCRA9TVsSAnZWagAAas4P/2WFFJvncp0LWb3DbE0t\ndx9BhZEwY3W8V6ug8uKvph24LoQp1PakkncscKS7PsCVHyIslD+fi6V99AmI\nOmL2ECAMUd5N69Cs8eTi4tKTNtUoIslfCu0+SMlCAF11D7oBXSabdOxGQofA\nuksoHdCqGM6M1y2BGjK7FR8dSwvgbQCPaUzazZ5w7w4XqVxDlzbvNj2E5mSF\n5HjlT5q239uNQppwPIFpisyi9DKa0ran2N7F2ioZ1PHvhFCqo6rmL8tAQsxQ\n+3OA4eFD0FJCJuqd3MOaY66mkncfNpmPvQYMyigKBUdJJyrgNsB67yfaFduy\ndK198Bnva5kotttQ4EHxM6gkqRm2d9o1/sYmAUtDELgrVDxzeNl+yG+nCkho\n1ta4cY+wy1dTjqAYaprQJ855nIeGGnr3tvz4dEGX/5eyh5K+oYVOYRFvWFX6\nVlEhBmSRqamfW5N1ndMyY18FM+Vc12yu66yZ3z1FqbgEGqdf3EP3lwWqClpP\nbPdXANzHM1FIz1PGHC7IZFWXH5KV1z+JXXahg/d8CLzz0PY6jaBt4c2xDvo7\nLaEAm7kNMbdewKvuTuG7x2Kqyf1KwjpOhXMrq6h0rlFm0pRt0xAArQ9Sglw8\n2Vq9Ic9EEsSIpzA5iQ86O1xkTREGHTB3uTRXUJixXIGkhLkhBB+Uj9y+GoOh\nX+Dm\r\n=yF+m\r\n-----END PGP SIGNATURE-----\r\n"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "_npmUser": {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ },
+ "directories": {},
+ "_npmOperationalInternal": {
+ "host": "s3://npm-registry-packages",
+ "tmp": "tmp/promise-all-reject-late_1.0.1_1580183139628_0.5159334029276426"
+ },
+ "_hasShrinkwrap": false
+ }
+ },
+ "time": {
+ "created": "2019-12-27T20:28:12.428Z",
+ "1.0.0": "2019-12-27T20:28:12.645Z",
+ "modified": "2020-01-28T03:45:42.154Z",
+ "1.0.1": "2020-01-28T03:45:39.762Z"
+ },
+ "maintainers": [
+ {
+ "name": "isaacs",
+ "email": "i@izs.me"
+ }
+ ],
+ "description": "Like Promise.all, but save rejections until all promises are resolved",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me",
+ "url": "https://izs.me"
+ },
+ "license": "ISC",
+ "readme": "# promise-all-reject-late\n\nLike Promise.all, but save rejections until all promises are resolved.\n\nThis is handy when you want to do a bunch of things in parallel, and\nrollback on failure, without clobbering or conflicting with those parallel\nactions that may be in flight. For example, creating a bunch of files,\nand deleting any if they don't all succeed.\n\nExample:\n\n```js\nconst lateReject = require('promise-all-reject-late')\n\nconst { promisify } = require('util')\nconst fs = require('fs')\nconst writeFile = promisify(fs.writeFile)\n\nconst createFilesOrRollback = (files) => {\n return lateReject(files.map(file => writeFile(file, 'some data')))\n .catch(er => {\n // try to clean up, then fail with the initial error\n // we know that all write attempts are finished at this point\n return lateReject(files.map(file => rimraf(file)))\n .catch(er => {\n console.error('failed to clean up, youre on your own i guess', er)\n })\n .then(() => {\n // fail with the original error\n throw er\n })\n })\n}\n```\n\n## API\n\n* `lateReject([array, of, promises])` - Resolve all the promises,\n returning a promise that rejects with the first error, or resolves with\n the array of results, but only after all promises are settled.\n",
+ "readmeFilename": "README.md",
+ "_cached": false,
+ "_contentLength": 0
+} \ No newline at end of file
diff --git a/smoke-tests/content/promise-all-reject-late.min.json b/smoke-tests/content/promise-all-reject-late.min.json
new file mode 100644
index 000000000..699be7aaf
--- /dev/null
+++ b/smoke-tests/content/promise-all-reject-late.min.json
@@ -0,0 +1,44 @@
+{
+ "name": "promise-all-reject-late",
+ "dist-tags": {
+ "latest": "1.0.1"
+ },
+ "versions": {
+ "1.0.0": {
+ "name": "promise-all-reject-late",
+ "version": "1.0.0",
+ "devDependencies": {
+ "tap": "^14.10.5"
+ },
+ "dist": {
+ "integrity": "sha512-f5XvVl++12pEo7Sv7f7FGfzVuVpeY2msNKjn7nNcXyOSKh5uVu7IAzDO6RE9hDVoHJhxvg+gqEacwkZ891Se5g==",
+ "shasum": "4fa37515e2d78c3b0462414402a8debce62b8b9f",
+ "tarball": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.0.tgz",
+ "fileCount": 7,
+ "unpackedSize": 123039,
+ "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeBmldCRA9TVsSAnZWagAAaigP/2CarvNCbglNS0dgjOoH\n7ZuFo1cG+N8BkZct00TyEJjuB+5UUmv9TSnZogfEOGutvMqUTSRhvm3fOWsJ\n7TXs8zJ6SotDR9+xlxqi/skpYXfRdNjdaMvo9kYO5jaV84pstdbl17sPeYXd\nCudbAKp1sYodlaJyqpyfUd2PWUNe/VGLODmjLogHB4/bevT3tdjsdauKrUS4\n3VFw8sS1Fwp7P2YneNIK3C1TY/Yb66KysZO23VsQemCQFKXpQJMa9B6yj8zs\n5BQp+W5tM70IfW6OXD0+Vt2jWr9jmKmoWVEiL5usJT3zD7vRbeH3xQvSEgDD\nskI8vH8iJ+3EbEOWTGlIu7mX88Dp2KnHOoRUkOR03WJWuGnsTC8Uyqi0F1Xd\nFeFlaeNzynR/R2LcdRNiFOM+1xtzfAtVGF7TIp9UjgJwSNNkEMlkNzQqSiC7\n/AeqsAYoBBNmYWY2fvXdS9HQ4HfIGjI++jCYWX4I7sUvOjqfcwlEz8MwromA\nqeBAFPdvnB0F/q/AOOLkcdsO81jES7ts0nB7bDt0rDbztWWq34BSMDnNoSDo\nDE9q8u7g68tQcr3WmOQr4ro10sSbJVJZmz8DSJKCbVJ+FN0+GM+49oyyhIFl\nOjokXn5U8ASEdiZnmFnt51dr9A4fyjhehotJA6qSs7t2fBe86VnufijC971U\nv3Jc\r\n=lLwf\r\n-----END PGP SIGNATURE-----\r\n"
+ }
+ },
+ "1.0.1": {
+ "name": "promise-all-reject-late",
+ "version": "1.0.1",
+ "devDependencies": {
+ "tap": "^14.10.5"
+ },
+ "dist": {
+ "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==",
+ "shasum": "f8ebf13483e5ca91ad809ccc2fcf25f26f8643c2",
+ "tarball": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz",
+ "fileCount": 8,
+ "unpackedSize": 123171,
+ "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeL65kCRA9TVsSAnZWagAAas4P/2WFFJvncp0LWb3DbE0t\ndx9BhZEwY3W8V6ug8uKvph24LoQp1PakkncscKS7PsCVHyIslD+fi6V99AmI\nOmL2ECAMUd5N69Cs8eTi4tKTNtUoIslfCu0+SMlCAF11D7oBXSabdOxGQofA\nuksoHdCqGM6M1y2BGjK7FR8dSwvgbQCPaUzazZ5w7w4XqVxDlzbvNj2E5mSF\n5HjlT5q239uNQppwPIFpisyi9DKa0ran2N7F2ioZ1PHvhFCqo6rmL8tAQsxQ\n+3OA4eFD0FJCJuqd3MOaY66mkncfNpmPvQYMyigKBUdJJyrgNsB67yfaFduy\ndK198Bnva5kotttQ4EHxM6gkqRm2d9o1/sYmAUtDELgrVDxzeNl+yG+nCkho\n1ta4cY+wy1dTjqAYaprQJ855nIeGGnr3tvz4dEGX/5eyh5K+oYVOYRFvWFX6\nVlEhBmSRqamfW5N1ndMyY18FM+Vc12yu66yZ3z1FqbgEGqdf3EP3lwWqClpP\nbPdXANzHM1FIz1PGHC7IZFWXH5KV1z+JXXahg/d8CLzz0PY6jaBt4c2xDvo7\nLaEAm7kNMbdewKvuTuG7x2Kqyf1KwjpOhXMrq6h0rlFm0pRt0xAArQ9Sglw8\n2Vq9Ic9EEsSIpzA5iQ86O1xkTREGHTB3uTRXUJixXIGkhLkhBB+Uj9y+GoOh\nX+Dm\r\n=yF+m\r\n-----END PGP SIGNATURE-----\r\n"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ }
+ },
+ "modified": "2020-01-28T03:45:42.154Z",
+ "_cached": false,
+ "_contentLength": 2803
+} \ No newline at end of file
diff --git a/smoke-tests/content/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz b/smoke-tests/content/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz
new file mode 100644
index 000000000..7da404423
--- /dev/null
+++ b/smoke-tests/content/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz
Binary files differ
diff --git a/smoke-tests/index.js b/smoke-tests/index.js
new file mode 100644
index 000000000..38c3ed306
--- /dev/null
+++ b/smoke-tests/index.js
@@ -0,0 +1,196 @@
+const fs = require('fs')
+const { promisify } = require('util')
+const execAsync = promisify(require('child_process').exec)
+const { resolve } = require('path')
+const t = require('tap')
+
+const normalizePath = path => path.replace(/[A-Z]:/, '').replace(/\\/g, '/')
+const cwd = normalizePath(process.cwd())
+t.cleanSnapshot = s => s.split(cwd).join('{CWD}')
+ .split(registry).join('https://registry.npmjs.org/')
+ .split(normalizePath(process.execPath)).join('node')
+ .split(process.cwd()).join('{CWD}')
+ .replace(/\\+/g, '/')
+ .replace(/\r\n/g, '\n')
+
+// setup server
+const registryServer = require('./server.js')
+const { registry } = registryServer
+t.test('setup server', { bail: true, buffered: false }, registryServer)
+
+// setup fixtures
+const path = t.testdir({
+ '.npmrc': '',
+ cache: {},
+ project: {},
+ bin: {},
+})
+const localPrefix = resolve(path, 'project')
+const userconfigLocation = resolve(path, '.npmrc')
+const npmLocation = resolve(__dirname, '..')
+const cacheLocation = resolve(path, 'cache')
+const binLocation = resolve(path, 'bin')
+const env = {
+ HOME: path,
+ PATH: `${process.env.PATH}:${binLocation}`,
+}
+const npmOpts = `--registry=${registry} --cache="${cacheLocation}" --userconfig="${userconfigLocation}" --no-audit --no-update-notifier --loglevel=silly`
+const npmBin = `"${process.execPath}" "${npmLocation}" ${npmOpts}`
+const exec = async cmd => {
+ const res = await execAsync(cmd, { cwd: localPrefix, env })
+ if (res.stderr)
+ console.error(res.stderr)
+ return String(res.stdout)
+}
+const readFile = filename =>
+ String(fs.readFileSync(resolve(localPrefix, filename)))
+
+t.test('npm init', async t => {
+ const cmd = `${npmBin} init -y`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes, 'should have successful npm init result')
+ const pkg = JSON.parse(fs.readFileSync(resolve(localPrefix, 'package.json')))
+ t.equal(pkg.name, 'project', 'should have expected generated name')
+ t.equal(pkg.version, '1.0.0', 'should have expected generated version')
+})
+
+t.test('npm install prodDep@version', async t => {
+ const cmd = `${npmBin} install abbrev@1.0.4`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes.replace(/in.*s/, ''),
+ 'should have expected install reify output')
+ t.matchSnapshot(
+ readFile('package.json'),
+ 'should have expected package.json result'
+ )
+ t.matchSnapshot(
+ readFile('package-lock.json'),
+ 'should have expected lockfile result'
+ )
+})
+
+t.test('npm install dev dep', async t => {
+ const cmd = `${npmBin} install -D promise-all-reject-late`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes.replace(/in.*s/, ''),
+ 'should have expected dev dep added reify output')
+ t.matchSnapshot(
+ readFile('package.json'),
+ 'should have expected dev dep added package.json result'
+ )
+ t.matchSnapshot(
+ readFile('package-lock.json'),
+ 'should have expected dev dep added lockfile result'
+ )
+})
+
+t.test('npm ls', async t => {
+ const cmd = `${npmBin} ls`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected ls output')
+})
+
+t.test('npm fund', async t => {
+ const cmd = `${npmBin} fund`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected fund output')
+})
+
+t.test('npm explain', async t => {
+ const cmd = `${npmBin} explain abbrev`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected explain output')
+})
+
+t.test('npm diff', async t => {
+ const cmd = `${npmBin} diff --diff=abbrev@1.0.4 --diff=abbrev@1.1.1`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected diff output')
+})
+
+t.test('npm outdated', async t => {
+ const cmd = `${npmBin} outdated`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected outdated output')
+})
+
+t.test('npm set-script', async t => {
+ const cmd = `${npmBin} set-script "hello" "echo Hello"`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected set-script output')
+ t.matchSnapshot(
+ readFile('package.json'),
+ 'should have expected script added package.json result'
+ )
+})
+
+t.test('npm run-script', async t => {
+ const cmd = `${npmBin} run hello`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected run-script output')
+})
+
+t.test('npm prefix', async t => {
+ const cmd = `${npmBin} prefix`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected prefix output')
+})
+
+t.test('npm view', async t => {
+ const cmd = `${npmBin} view abbrev@1.0.4`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes,
+ 'should have expected view output')
+})
+
+t.test('npm update dep', async t => {
+ const cmd = `${npmBin} update abbrev`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes.replace(/in.*s/, ''),
+ 'should have expected update reify output')
+ t.matchSnapshot(
+ readFile('package.json'),
+ 'should have expected update package.json result'
+ )
+ t.matchSnapshot(
+ readFile('package-lock.json'),
+ 'should have expected update lockfile result'
+ )
+})
+
+t.test('npm uninstall', async t => {
+ const cmd = `${npmBin} uninstall promise-all-reject-late`
+ const cmdRes = await exec(cmd)
+
+ t.matchSnapshot(cmdRes.replace(/in.*s/, ''),
+ 'should have expected uninstall reify output')
+ t.matchSnapshot(
+ readFile('package.json'),
+ 'should have expected uninstall package.json result'
+ )
+ t.matchSnapshot(
+ readFile('package-lock.json'),
+ 'should have expected uninstall lockfile result'
+ )
+})
diff --git a/smoke-tests/server.js b/smoke-tests/server.js
new file mode 100644
index 000000000..88cb5883d
--- /dev/null
+++ b/smoke-tests/server.js
@@ -0,0 +1,276 @@
+const {join, dirname} = require('path')
+const {existsSync, readFileSync, writeFileSync} = require('fs')
+const PORT = 12345 + (+process.env.TAP_CHILD_ID || 0)
+const http = require('http')
+const https = require('https')
+
+const mkdirp = require('mkdirp')
+const doProxy = process.env.ARBORIST_TEST_PROXY
+const missing = /\/@isaacs(\/|%2[fF])(this-does-not-exist-at-all|testing-missing-tgz\/-\/)/
+const corgiDoc = 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'
+const { gzipSync, unzipSync } = require('zlib')
+
+let advisoryBulkResponse = null
+let failAdvisoryBulk = false
+let auditResponse = null
+let failAudit = false
+const startServer = cb => {
+ const server = module.exports.server = http.createServer((req, res) => {
+ res.setHeader('connection', 'close')
+
+ if (req.url === '/-/npm/v1/security/advisories/bulk') {
+ const body = []
+ req.on('data', c => body.push(c))
+ req.on('end', () => {
+ res.setHeader('connection', 'close')
+ if (failAdvisoryBulk) {
+ res.statusCode = 503
+ return res.end('no advisory bulk for you')
+ }
+ if (!advisoryBulkResponse) {
+ if (auditResponse && !failAudit) {
+ // simulate what the registry does when quick audits are allowed,
+ // but advisory bulk requests are not
+ res.statusCode = 405
+ return res.end(JSON.stringify({
+ code: 'MethodNotAllowedError',
+ message: 'POST is not allowed',
+ }))
+ } else {
+ res.statusCode = 404
+ return res.end('not found')
+ }
+ }
+ if (doProxy && !existsSync(advisoryBulkResponse)) {
+ // hit the main registry, then fall back to staging for now
+ // XXX: remove this when bulk advisory endpoint pushed to production!
+ const opts = {
+ host: 'registry.npmjs.org',
+ method: req.method,
+ path: req.url,
+ headers: {
+ ...req.headers,
+ accept: '*',
+ host: 'registry.npmjs.org',
+ connection: 'close',
+ 'if-none-match': '',
+ },
+ }
+ const handleUpstream = upstream => {
+ res.statusCode = upstream.statusCode
+ if (upstream.statusCode >= 300 || upstream.statusCode < 200) {
+ console.error('UPSTREAM ERROR', upstream.statusCode)
+ return upstream.pipe(res)
+ }
+ res.setHeader('content-encoding', upstream.headers['content-encoding'])
+ const file = advisoryBulkResponse
+ console.error('PROXY', `${req.url} -> ${file} ${upstream.statusCode}`)
+ mkdirp.sync(dirname(file))
+ const data = []
+ upstream.on('end', () => {
+ const out = Buffer.concat(data)
+ const obj = JSON.parse(unzipSync(out).toString())
+ writeFileSync(file, JSON.stringify(obj, 0, 2) + '\n')
+ res.end(out)
+ })
+ upstream.on('data', c => data.push(c))
+ }
+ return https.request(opts).on('response', upstream => {
+ if (upstream.statusCode !== 200) {
+ console.error('ATTEMPTING TO PROXY FROM STAGING')
+ console.error('NOTE: THIS WILL FAIL WHEN NOT ON VPN!')
+ opts.host = 'security-microservice-3-west.npm.red'
+ opts.headers.host = opts.host
+ opts.path = '/v1/advisories/bulk'
+ https.request(opts)
+ .on('response', upstream => handleUpstream(upstream))
+ .end(Buffer.concat(body))
+ } else
+ handleUpstream(upstream)
+ }).end(Buffer.concat(body))
+ } else {
+ res.setHeader('content-encoding', 'gzip')
+ res.end(gzipSync(readFileSync(advisoryBulkResponse)))
+ }
+ })
+ return
+ } else if (req.url === '/-/npm/v1/security/audits/quick') {
+ const body = []
+ req.on('data', c => body.push(c))
+ req.on('end', () => {
+ res.setHeader('connection', 'close')
+ if (failAudit) {
+ res.statusCode = 503
+ return res.end('no audit for you')
+ }
+ if (!auditResponse) {
+ res.statusCode = 404
+ return res.end('not found')
+ }
+ if (doProxy && !existsSync(auditResponse)) {
+ return https.request({
+ host: 'registry.npmjs.org',
+ method: req.method,
+ path: req.url,
+ headers: {
+ ...req.headers,
+ accept: '*',
+ host: 'registry.npmjs.org',
+ connection: 'close',
+ 'if-none-match': '',
+ },
+ }).on('response', upstream => {
+ res.statusCode = upstream.statusCode
+ if (upstream.statusCode >= 300 || upstream.statusCode < 200) {
+ console.error('UPSTREAM ERROR', upstream.statusCode)
+ // don't save if it's not a valid response
+ return upstream.pipe(res)
+ }
+ res.setHeader('content-encoding', upstream.headers['content-encoding'])
+ const file = auditResponse
+ console.error('PROXY', `${req.url} -> ${file} ${upstream.statusCode}`)
+ mkdirp.sync(dirname(file))
+ const data = []
+ upstream.on('end', () => {
+ const out = Buffer.concat(data)
+ // make it a bit prettier to read later
+ const obj = JSON.parse(unzipSync(out).toString())
+ writeFileSync(file, JSON.stringify(obj, 0, 2) + '\n')
+ res.end(out)
+ })
+ upstream.on('data', c => data.push(c))
+ }).end(Buffer.concat(body))
+ } else {
+ res.setHeader('content-encoding', 'gzip')
+ res.end(gzipSync(readFileSync(auditResponse)))
+ }
+ })
+ return
+ }
+
+ const f = join(__dirname, 'content', join('/', req.url.replace(/@/, '').replace(/%2f/i, '/')))
+ const isCorgi = req.headers.accept.includes('application/vnd.npm.install-v1+json')
+ const file = f + (
+ isCorgi && existsSync(`${f}.min.json`) ? '.min.json'
+ : existsSync(`${f}.json`) ? '.json'
+ : existsSync(`${f}/index.json`) ? 'index.json'
+ : ''
+ )
+
+ try {
+ const body = readFileSync(file)
+ res.setHeader('content-length', body.length)
+ res.setHeader('content-type', /\.min\.json$/.test(file) ? corgiDoc
+ : /\.json$/.test(file) ? 'application/json'
+ : 'application/octet-stream')
+ res.end(body)
+ } catch (er) {
+ // testing things going missing from the registry somehow
+ if (missing.test(req.url)) {
+ res.statusCode = 404
+ res.end('{"error": "not found"}')
+ return
+ }
+
+ if (doProxy) {
+ return https.get({
+ host: 'registry.npmjs.org',
+ path: req.url,
+ headers: {
+ ...req.headers,
+ accept: '*',
+ 'accept-encoding': 'identity',
+ host: 'registry.npmjs.org',
+ connection: 'close',
+ 'if-none-match': '',
+ },
+ }).on('response', upstream => {
+ const errorStatus =
+ upstream.statusCode >= 300 || upstream.statusCode < 200
+
+ if (errorStatus)
+ console.error('UPSTREAM ERROR', upstream.statusCode)
+
+ const ct = upstream.headers['content-type']
+ const isJson = ct.includes('application/json')
+ const file = isJson ? f + '.json' : f
+ console.error('PROXY', `${req.url} -> ${file} ${ct}`)
+ mkdirp.sync(dirname(file))
+ const data = []
+ res.statusCode = upstream.statusCode
+ res.setHeader('content-type', ct)
+ upstream.on('end', () => {
+ console.error('ENDING', req.url)
+ const out = Buffer.concat(data)
+ if (!errorStatus) {
+ if (isJson) {
+ const obj = JSON.parse(out.toString())
+ writeFileSync(file, JSON.stringify(obj, 0, 2) + '\n')
+ const mrm = require('minify-registry-metadata')
+ const minFile = file.replace(/\.json$/, '.min.json')
+ writeFileSync(minFile, JSON.stringify(mrm(obj), 0, 2) + '\n')
+ console.error('WROTE JSONS', [file, minFile])
+ } else
+ writeFileSync(file, out)
+ }
+ res.end(out)
+ })
+ upstream.on('data', c => data.push(c))
+ }).end()
+ }
+
+ res.statusCode = er.code === 'ENOENT' ? 404 : 500
+ if (res.method === 'GET')
+ console.error(er)
+ res.setHeader('content-type', 'text/plain')
+ res.end(er.stack)
+ }
+ })
+ server.listen(PORT, cb)
+}
+
+module.exports = t => startServer(() => {
+ t.parent.teardown(() => module.exports.server.close())
+ t.end()
+})
+
+module.exports.auditResponse = value => {
+ if (auditResponse && auditResponse !== value) {
+ throw new Error('setting audit response, but already set\n' +
+ '(did you forget to call the returned function on teardown?)')
+ }
+ auditResponse = value
+ return () => auditResponse = null
+}
+module.exports.failAudit = () => {
+ failAudit = true
+ return () => failAudit = false
+}
+
+module.exports.advisoryBulkResponse = value => {
+ if (advisoryBulkResponse && advisoryBulkResponse !== value) {
+ throw new Error('setting advisory bulk response, but already set\n' +
+ '(did you forget to call the returned function on teardown?)')
+ }
+ advisoryBulkResponse = value
+ return () => advisoryBulkResponse = null
+}
+module.exports.failAdvisoryBulk = () => {
+ failAdvisoryBulk = true
+ return () => failAdvisoryBulk = false
+}
+
+module.exports.registry = `http://localhost:${PORT}/`
+
+module.exports.start = startServer
+module.exports.stop = () => module.exports.server.close()
+
+if (require.main === module) {
+ startServer(() => {
+ console.log(`Mock registry live at:
+ ${module.exports.registry}
+Press ^D to close gracefully.`)
+ })
+ process.openStdin()
+ process.stdin.on('end', () => module.exports.server.close())
+}
diff --git a/tap-snapshots/smoke-tests-index.js-TAP.test.js b/tap-snapshots/smoke-tests-index.js-TAP.test.js
new file mode 100644
index 000000000..aa8977316
--- /dev/null
+++ b/tap-snapshots/smoke-tests-index.js-TAP.test.js
@@ -0,0 +1,649 @@
+/* IMPORTANT
+ * This snapshot file is auto-generated, but designed for humans.
+ * It should be checked into source control and tracked carefully.
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
+ * Make sure to inspect the output below. Do not ignore changes!
+ */
+'use strict'
+exports[`smoke-tests/index.js TAP npm diff > should have expected diff output 1`] = `
+diff --git a/package.json b/package.json
+index v1.0.4..v1.1.1 100644
+--- a/package.json
++++ b/package.json
+@@ -1,15 +1,21 @@
+ {
+ "name": "abbrev",
+- "version": "1.0.4",
++ "version": "1.1.1",
+ "description": "Like ruby's abbrev module, but in js",
+ "author": "Isaac Z. Schlueter <i@izs.me>",
+- "main": "./lib/abbrev.js",
++ "main": "abbrev.js",
+ "scripts": {
+- "test": "node lib/abbrev.js"
++ "test": "tap test.js --100",
++ "preversion": "npm test",
++ "postversion": "npm publish",
++ "postpublish": "git push origin --all; git push origin --tags"
+ },
+ "repository": "http://github.com/isaacs/abbrev-js",
+- "license": {
+- "type": "MIT",
+- "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE"
+- }
++ "license": "ISC",
++ "devDependencies": {
++ "tap": "^10.1"
++ },
++ "files": [
++ "abbrev.js"
++ ]
+ }
+diff --git a/LICENSE b/LICENSE
+index v1.0.4..v1.1.1 100644
+--- a/LICENSE
++++ b/LICENSE
+@@ -1,4 +1,27 @@
+-Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
++This software is dual-licensed under the ISC and MIT licenses.
++You may use this software under EITHER of the following licenses.
++
++----------
++
++The ISC License
++
++Copyright (c) Isaac Z. Schlueter and Contributors
++
++Permission to use, copy, modify, and/or distribute this software for any
++purpose with or without fee is hereby granted, provided that the above
++copyright notice and this permission notice appear in all copies.
++
++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++
++----------
++
++Copyright Isaac Z. Schlueter and Contributors
+ All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person
+diff --git a/lib/abbrev.js b/lib/abbrev.js
+deleted file mode 100644
+index v1.0.4..v1.1.1
+--- a/lib/abbrev.js
++++ b/lib/abbrev.js
+@@ -1,111 +0,0 @@
+-
+-module.exports = exports = abbrev.abbrev = abbrev
+-
+-abbrev.monkeyPatch = monkeyPatch
+-
+-function monkeyPatch () {
+- Object.defineProperty(Array.prototype, 'abbrev', {
+- value: function () { return abbrev(this) },
+- enumerable: false, configurable: true, writable: true
+- })
+-
+- Object.defineProperty(Object.prototype, 'abbrev', {
+- value: function () { return abbrev(Object.keys(this)) },
+- enumerable: false, configurable: true, writable: true
+- })
+-}
+-
+-function abbrev (list) {
+- if (arguments.length !== 1 || !Array.isArray(list)) {
+- list = Array.prototype.slice.call(arguments, 0)
+- }
+- for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
+- args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
+- }
+-
+- // sort them lexicographically, so that they're next to their nearest kin
+- args = args.sort(lexSort)
+-
+- // walk through each, seeing how much it has in common with the next and previous
+- var abbrevs = {}
+- , prev = ""
+- for (var i = 0, l = args.length ; i < l ; i ++) {
+- var current = args[i]
+- , next = args[i + 1] || ""
+- , nextMatches = true
+- , prevMatches = true
+- if (current === next) continue
+- for (var j = 0, cl = current.length ; j < cl ; j ++) {
+- var curChar = current.charAt(j)
+- nextMatches = nextMatches && curChar === next.charAt(j)
+- prevMatches = prevMatches && curChar === prev.charAt(j)
+- if (!nextMatches && !prevMatches) {
+- j ++
+- break
+- }
+- }
+- prev = current
+- if (j === cl) {
+- abbrevs[current] = current
+- continue
+- }
+- for (var a = current.substr(0, j) ; j <= cl ; j ++) {
+- abbrevs[a] = current
+- a += current.charAt(j)
+- }
+- }
+- return abbrevs
+-}
+-
+-function lexSort (a, b) {
+- return a === b ? 0 : a > b ? 1 : -1
+-}
+-
+-
+-// tests
+-if (module === require.main) {
+-
+-var assert = require("assert")
+-var util = require("util")
+-
+-console.log("running tests")
+-function test (list, expect) {
+- var actual = abbrev(list)
+- assert.deepEqual(actual, expect,
+- "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "/n"+
+- "actual: "+util.inspect(actual))
+- actual = abbrev.apply(exports, list)
+- assert.deepEqual(abbrev.apply(exports, list), expect,
+- "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "/n"+
+- "actual: "+util.inspect(actual))
+-}
+-
+-test([ "ruby", "ruby", "rules", "rules", "rules" ],
+-{ rub: 'ruby'
+-, ruby: 'ruby'
+-, rul: 'rules'
+-, rule: 'rules'
+-, rules: 'rules'
+-})
+-test(["fool", "foom", "pool", "pope"],
+-{ fool: 'fool'
+-, foom: 'foom'
+-, poo: 'pool'
+-, pool: 'pool'
+-, pop: 'pope'
+-, pope: 'pope'
+-})
+-test(["a", "ab", "abc", "abcd", "abcde", "acde"],
+-{ a: 'a'
+-, ab: 'ab'
+-, abc: 'abc'
+-, abcd: 'abcd'
+-, abcde: 'abcde'
+-, ac: 'acde'
+-, acd: 'acde'
+-, acde: 'acde'
+-})
+-
+-console.log("pass")
+-
+-}
+/ No newline at end of file
+diff --git a/abbrev.js b/abbrev.js
+new file mode 100644
+index v1.0.4..v1.1.1
+--- a/abbrev.js
++++ b/abbrev.js
+@@ -0,0 +1,61 @@
++module.exports = exports = abbrev.abbrev = abbrev
++
++abbrev.monkeyPatch = monkeyPatch
++
++function monkeyPatch () {
++ Object.defineProperty(Array.prototype, 'abbrev', {
++ value: function () { return abbrev(this) },
++ enumerable: false, configurable: true, writable: true
++ })
++
++ Object.defineProperty(Object.prototype, 'abbrev', {
++ value: function () { return abbrev(Object.keys(this)) },
++ enumerable: false, configurable: true, writable: true
++ })
++}
++
++function abbrev (list) {
++ if (arguments.length !== 1 || !Array.isArray(list)) {
++ list = Array.prototype.slice.call(arguments, 0)
++ }
++ for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
++ args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
++ }
++
++ // sort them lexicographically, so that they're next to their nearest kin
++ args = args.sort(lexSort)
++
++ // walk through each, seeing how much it has in common with the next and previous
++ var abbrevs = {}
++ , prev = ""
++ for (var i = 0, l = args.length ; i < l ; i ++) {
++ var current = args[i]
++ , next = args[i + 1] || ""
++ , nextMatches = true
++ , prevMatches = true
++ if (current === next) continue
++ for (var j = 0, cl = current.length ; j < cl ; j ++) {
++ var curChar = current.charAt(j)
++ nextMatches = nextMatches && curChar === next.charAt(j)
++ prevMatches = prevMatches && curChar === prev.charAt(j)
++ if (!nextMatches && !prevMatches) {
++ j ++
++ break
++ }
++ }
++ prev = current
++ if (j === cl) {
++ abbrevs[current] = current
++ continue
++ }
++ for (var a = current.substr(0, j) ; j <= cl ; j ++) {
++ abbrevs[a] = current
++ a += current.charAt(j)
++ }
++ }
++ return abbrevs
++}
++
++function lexSort (a, b) {
++ return a === b ? 0 : a > b ? 1 : -1
++}
+
+`
+
+exports[`smoke-tests/index.js TAP npm explain > should have expected explain output 1`] = `
+abbrev@1.0.4
+node_modules/abbrev
+ abbrev@"^1.0.4" from the root project
+
+`
+
+exports[`smoke-tests/index.js TAP npm fund > should have expected fund output 1`] = `
+project@1.0.0
+\`-- https://github.com/sponsors/isaacs
+ \`-- promise-all-reject-late@1.0.1
+
+
+`
+
+exports[`smoke-tests/index.js TAP npm init > should have successful npm init result 1`] = `
+Wrote to {CWD}/smoke-tests/index/project/package.json:
+
+{
+ "name": "project",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo /"Error: no test specified/" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC"
+}
+
+
+
+`
+
+exports[`smoke-tests/index.js TAP npm install dev dep > should have expected dev dep added lockfile result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ },
+ "devDependencies": {
+ "promise-all-reject-late": "^1.0.1"
+ }
+ },
+ "node_modules/abbrev": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz",
+ "integrity": "sha1-vVWuXkE7oXIu5Mq6H26hBBSlns0="
+ },
+ "node_modules/promise-all-reject-late": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz",
+ "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ }
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz",
+ "integrity": "sha1-vVWuXkE7oXIu5Mq6H26hBBSlns0="
+ },
+ "promise-all-reject-late": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz",
+ "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==",
+ "dev": true
+ }
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm install dev dep > should have expected dev dep added package.json result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo /"Error: no test specified/" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ },
+ "devDependencies": {
+ "promise-all-reject-late": "^1.0.1"
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm install dev dep > should have expected dev dep added reify output 1`] = `
+
+added 1 package
+
+1 package is looking for funding
+ run \`npm fund\` for details
+
+`
+
+exports[`smoke-tests/index.js TAP npm install prodDep@version > should have expected install reify output 1`] = `
+
+added 1 package
+
+`
+
+exports[`smoke-tests/index.js TAP npm install prodDep@version > should have expected lockfile result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ }
+ },
+ "node_modules/abbrev": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz",
+ "integrity": "sha1-vVWuXkE7oXIu5Mq6H26hBBSlns0="
+ }
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz",
+ "integrity": "sha1-vVWuXkE7oXIu5Mq6H26hBBSlns0="
+ }
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm install prodDep@version > should have expected package.json result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo /"Error: no test specified/" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm ls > should have expected ls output 1`] = `
+project@1.0.0 {CWD}/smoke-tests/index/project
++-- abbrev@1.0.4
+\`-- promise-all-reject-late@1.0.1
+
+
+`
+
+exports[`smoke-tests/index.js TAP npm outdated > should have expected outdated output 1`] = `
+Package Current Wanted Latest Location Depended by
+abbrev 1.0.4 1.1.1 1.1.1 node_modules/abbrev project
+
+`
+
+exports[`smoke-tests/index.js TAP npm prefix > should have expected prefix output 1`] = `
+{CWD}/smoke-tests/index/project
+
+`
+
+exports[`smoke-tests/index.js TAP npm run-script > should have expected run-script output 1`] = `
+
+> project@1.0.0 hello
+> echo Hello
+
+Hello
+
+`
+
+exports[`smoke-tests/index.js TAP npm set-script > should have expected script added package.json result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo /"Error: no test specified/" && exit 1",
+ "hello": "echo Hello"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ },
+ "devDependencies": {
+ "promise-all-reject-late": "^1.0.1"
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm set-script > should have expected set-script output 1`] = `
+
+`
+
+exports[`smoke-tests/index.js TAP npm uninstall > should have expected uninstall lockfile result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ }
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ }
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ }
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm uninstall > should have expected uninstall package.json result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo /"Error: no test specified/" && exit 1",
+ "hello": "echo Hello"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm uninstall > should have expected uninstall reify output 1`] = `
+
+removed 1 package
+
+`
+
+exports[`smoke-tests/index.js TAP npm update dep > should have expected update lockfile result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ },
+ "devDependencies": {
+ "promise-all-reject-late": "^1.0.1"
+ }
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "node_modules/promise-all-reject-late": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz",
+ "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ }
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "promise-all-reject-late": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz",
+ "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==",
+ "dev": true
+ }
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm update dep > should have expected update package.json result 1`] = `
+{
+ "name": "project",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo /"Error: no test specified/" && exit 1",
+ "hello": "echo Hello"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "^1.0.4"
+ },
+ "devDependencies": {
+ "promise-all-reject-late": "^1.0.1"
+ }
+}
+
+`
+
+exports[`smoke-tests/index.js TAP npm update dep > should have expected update reify output 1`] = `
+
+changed 1 package
+
+1 package is looking for funding
+ run \`npm fund\` for details
+
+`
+
+exports[`smoke-tests/index.js TAP npm view > should have expected view output 1`] = `
+
+abbrev@1.0.4 | MIT | deps: none | versions: 8
+Like ruby's abbrev module, but in js
+https://github.com/isaacs/abbrev-js#readme
+
+dist
+.tarball: https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz
+.shasum: bd55ae5e413ba1722ee4caba1f6ea10414a59ecd
+
+maintainers:
+- nlf <quitlahok@gmail.com>
+- ruyadorno <ruyadorno@hotmail.com>
+- darcyclarke <darcy@darcyclarke.me>
+- adam_baldwin <evilpacket@gmail.com>
+- isaacs <i@izs.me>
+
+dist-tags:
+latest: 1.1.1
+
+published over a year ago by isaacs <i@izs.me>
+
+`