Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
8cff8ee
[email protected]
zkat May 24, 2018
bfc4f87
[email protected]
zkat May 24, 2018
5320961
[email protected]
zkat May 24, 2018
6c29461
test: Flat installs are ok
iarna May 24, 2018
0483f5c
Flatten dependencies and add dev deps to git
iarna May 24, 2018
c8ba757
dedupe: Fix deduping bundles (eg don't)
iarna May 24, 2018
cd698f0
audit: Add synopsis to brief help and suppress trailing newline (#20762)
wyardley May 31, 2018
7ba3fca
errors: direct people to npm.community instead of github (#20855)
zkat Jun 1, 2018
ecc7560
audit: add test to make sure dev: true is preserved
zkat Jun 1, 2018
4a51277
[email protected]
iarna Jun 7, 2018
b7cc48d
[email protected]
iarna Jun 7, 2018
bae657c
[email protected]
iarna Jun 7, 2018
3d46e5c
[email protected]
iarna Jun 7, 2018
d0a905d
[email protected]
iarna Jun 7, 2018
4fc1f81
[email protected]
iarna Jun 7, 2018
f722029
[email protected]
iarna Jun 7, 2018
f456fca
scripts: auto generate ignores
iarna Jun 7, 2018
0762ebb
chore: Prune dev deps from git
iarna Jun 7, 2018
bdce96e
[email protected]
iarna Jun 7, 2018
ef9fa1c
remove unused direct dep ansi-regex
iarna Jun 7, 2018
0d14b0b
chore: reshuffle ansi-regex for better deduping
iarna Jun 7, 2018
68a1018
chore: reshuffle strip-ansi for better deduping
iarna Jun 7, 2018
0d5251f
chore: reshuffle is-fullwidth-code-point for better deduping
iarna Jun 7, 2018
2d08866
test: Add fake-registry, npm-registry-mock replacement
iarna Jun 8, 2018
eef5d19
add npm audit resolve command
naugtur Jun 16, 2018
a72795d
add audit-resolv.json support to audit command, pass on npm.prefix to…
naugtur Jun 20, 2018
f67dd20
latest audit resolver, updated dependencies
naugtur Jun 20, 2018
ce07933
config: Enable config for suppressing update-notifier (#20750)
travi Jun 28, 2018
88efbf6
docs: fix typo in registry page (#20859)
strugee Jun 28, 2018
d2ad776
run-script: show suggestions when script name is typoed (#20879)
watilde Jun 28, 2018
6808ee3
misc: Exclude /.github directory from package (#20881)
styfle Jun 28, 2018
61bf827
docs: Fixed a small grammar error in the README (#20947)
Jun 28, 2018
8f033d7
node-gyp: fix regex to match multi-digit versions (#20948)
Trott Jun 28, 2018
833efe4
docs: Add info about tarball requirements (#20986)
Maximaximum Jun 28, 2018
f5230c9
docs: small typo fix in CONTRIBUTING.md (#21018)
reggi Jun 28, 2018
9fc0dc4
docs: clarify text in npm-link.md (#21019)
davidgilbertson Jun 28, 2018
3924c72
docs: Add missing "if" (#21064)
roblourens Jun 28, 2018
177cbb4
cache: Add warning text about using temp cache for debugging (#21105)
karanjthakkar Jun 28, 2018
fe4240e
[email protected]
zkat Jun 28, 2018
feb4e2b
doc: update changelog for [email protected]
zkat Jun 28, 2018
d7cf1b3
update AUTHORS
zkat Jun 29, 2018
ea9415f
6.2.0-next.0
zkat Jun 29, 2018
ecdcbd7
misc: remove postinstall script that broke stuff (#21129)
zkat Jul 5, 2018
5440b5e
doc: update changelog for [email protected]
zkat Jul 5, 2018
843bdd6
6.2.0-next.1
zkat Jul 5, 2018
d9b2712
[email protected]
zkat Jul 10, 2018
2ac48f8
[email protected]
zkat Jul 10, 2018
8dc6d76
[email protected]
zkat Jul 10, 2018
90c759f
[email protected]
zkat Jul 10, 2018
5724983
docs: remove back-ticks not being parsed as markdown (#21165)
hchiam Jul 10, 2018
7381783
docs: republish waiting period (#20920)
gmattie Jul 10, 2018
244b183
audit: add support for --parseable output (#20554)
luislobo Jul 10, 2018
7984206
version: Add new sign-git-commit config (#12697)
tribou Jul 10, 2018
4c32413
run-script: Do not use SET to fetch the env in git-bash or cygwin
gucong3000 May 2, 2018
616a97b
Merge branch 'audit-resolver' of github.com:naugtur/npm into audit-re…
naugtur Jul 12, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
test: Add fake-registry, npm-registry-mock replacement
  • Loading branch information
iarna committed Jun 8, 2018
commit 2d08866327013522fc5fbe61ed872b8f30e92775
16 changes: 5 additions & 11 deletions test/common-tap.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ var path = require('path')

var port = exports.port = 1337
exports.registry = 'http://localhost:' + port

var fakeRegistry = require('./fake-registry.js')
exports.fakeRegistry = fakeRegistry

const ourenv = {}
ourenv.npm_config_loglevel = 'error'
ourenv.npm_config_progress = 'false'
Expand Down Expand Up @@ -145,18 +149,8 @@ exports.pendIfWindows = function (why) {
process.exit(0)
}

let mr
exports.withServer = cb => {
if (!mr) { mr = Bluebird.promisify(require('npm-registry-mock')) }
return mr({port: port++, throwOnUnmatched: true})
.tap(server => {
server.registry = exports.registry.replace(exports.port, server.port)
return cb(server)
})
.then((server) => {
server.done()
return server.close()
})
return fakeRegistry.compat().tap(cb).then(server => server.close())
}

exports.newEnv = function () {
Expand Down
149 changes: 149 additions & 0 deletions test/fake-registry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
'use strict'
const common = require('./common-tap.js')
const Bluebird = require('bluebird')
const log = require('npmlog')

const http = require('http')
const EventEmitter = require('events')
// See mock-registry.md for details

class FakeRegistry extends EventEmitter {
constructor (opts) {
if (!opts) opts = {}
super(opts)
this.mocks = {}
this.port = opts.port || common.port
this.registry = 'http://localhost:' + this.port
this.server = http.createServer()
if (!opts.keepNodeAlive) this.server.unref()
this.server.on('request', (req, res) => {
if (this.mocks[req.method] && this.mocks[req.method][req.url]) {
this.mocks[req.method][req.url](req, res)
} else {
res.statusCode = 404
res.end(JSON.stringify({error: 'not found'}))
}
log.http('fake-registry', res.statusCode || 'unknown', '→', req.method, req.url)
})
this._error = err => {
log.silly('fake-registry', err)
this.emit('error', err)
}
this._addErrorHandler()
}
reset () {
this.mocks = {}
return this
}
close () {
this.reset()
this._removeErrorHandler()
return new Promise((resolve, reject) => {
this.server.once('error', reject)
this.server.once('close', () => {
this.removeListener('error', reject)
resolve(this)
})
this.server.close()
})
}
_addErrorHandler () {
this.server.on('error', this._error)
}
_removeErrorHandler () {
if (!this._error) return
this.server.removeListener('error', this._error)
}
listen (cb) {
this._removeErrorHandler()
return this._findPort(this.port).then(port => {
this._addErrorHandler()
this.port = port
this.registry = 'http://localhost:' + port
common.port = this.port
common.registry = this.registry
return this
}).asCallback(cb)
}
_findPort (port) {
return new Bluebird((resolve, reject) => {
let onListening
const onError = err => {
this.server.removeListener('listening', onListening)
if (err.code === 'EADDRINUSE') {
return resolve(this._findPort(++port))
} else {
return reject(err)
}
}
onListening = () => {
this.server.removeListener('error', onError)
resolve(port)
}
this.server.once('error', onError)
this.server.once('listening', onListening)
this.server.listen(port)
})
}

mock (method, url, respondWith) {
log.http('fake-registry', 'mock', method, url, respondWith)
if (!this.mocks[method]) this.mocks[method] = {}
if (typeof respondWith === 'function') {
this.mocks[method][url] = respondWith
} else if (Array.isArray(respondWith)) {
const [status, body] = respondWith
this.mocks[method][url] = (req, res) => {
res.statusCode = status
if (typeof body === 'object') {
res.end(JSON.stringify(body))
} else {
res.end(String(body))
}
}
} else {
throw new Error('Invalid args, expected: mr.mock(method, url, [status, body])')
}
return this
}

// compat
done () {
this.reset()
}
filteringRequestBody () {
return this
}
post (url, matchBody) {
return this._createReply('POST', url)
}
get (url) {
return this._createReply('GET', url)
}
put (url, matchBody) {
return this._createReply('PUT', url)
}
delete (url) {
return this._createReply('DELETE', url)
}
_createReply (method, url) {
const mr = this
return {
twice: function () { return this },
reply: function (status, responseBody) {
mr.mock(method, url, [status, responseBody])
return mr
}
}
}
}

module.exports = new FakeRegistry()
module.exports.FakeRegistry = FakeRegistry
module.exports.compat = function (opts, cb) {
if (arguments.length === 1 && typeof opts === 'function') {
cb = opts
opts = {}
}
return new FakeRegistry(Object.assign({keepNodeAlive: true}, opts || {})).listen(cb)
}
198 changes: 198 additions & 0 deletions test/fake-registry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# FakeRegistry

This is a replacement for npm-registry-mock in times where its fixtures are
not used. (Adding support for its standard fixtures is TODO, but should be
straightforward—tacks-ify them and call `mr.mock…`

# Usage

The intent is for this to be a drop in replacement for npm-registry-mock
(and by extension hock). New scripts will be better served using its native
interface, however.

# Main Interface

## Logging

All requests the mock registry receives are logged at the `http` level. You can
see these by running your tests with:

```
npm --loglevel=http run tap test/tap/name-of-test.js
```

Or directly with:

```
npm_config_loglevel=http node test/tap/name-of-test.js
```

## Construction

Ordinarily there's no reason to construct more than one FakeRegistyr object
at a time, as it can be entirely reset between tests, so best practice
would be to use its singleton.

```
const common = require('../common-tap.js')
const mr = common.mockRegistry
```

If you have need of multiple registries at the same time, you can construct
them by hand:

```
const common = require('../common-tap.js')
const FakeRegistry = common.mockRegistry.FakeRegistry
const mr = new FakeRegistry(opts)
```

## new FakeRegistry(opts)

Valid options are:

* `opts.port` is the first port to try when looking for an available port. If it
is unavialable it will be incremented until one available is found.

The default value of `port` is taken from `common.npm`.

* `opts.keepNodeAlive` will instruct FakeRegistry to not unref the
underlying server.

## mr.reset() → this

Reset all mocks to their default values. Further requests

## mr.listen() → Promise(mr)

Start listening for connections. The promise resolves when the server is
online and ready to accept connections.

`mr.port` and `mr.registry` contain the port that was actually selected.

To ease compatibility, `common` will also have its `port` and `registry`
values updated at this time. Note that this means `common.port` refers
to the port of the most recent listening server. Each server will maintain
its own `mr.port`.

Any errors emitted by the server while it was coming online will result in a
promise rejection.

## mr.mock(method, url, respondWith) → this

Adds a new route that matches `method` (should be all caps) and `url`.

`respondWith` can be:

* A function, that takes `(request, response)` as arguments and calls
[`response` methods](https://nodejs.org/api/http.html#http_class_http_serverresponse)
to do what it wants. Does not have a return value. This function may be
async (the response isn't complete till its stream completes), typically
either because you piped something into it or called `response.end()`.
* An array of `[statusCode, responseBody]`. `responseBody` may be a string or
an object. Objects are serialized with `JSON.stringify`.

## mr.close() → Promise(mr)

Calls `mr.reset()` to clear the mocks.

Calls `.close()` on the http server. The promise resolves when the http
server completes closing. Any errors while the http server was closing will
result in a rejection. If running with `keepNodeAlive` set this call
is required for node to exit the event loop.

# Events

## mr.on('error', err => { … })

Error events from the http server are forwarded to the associated fake
registry instance.

The exception to this is while the `mr.listen()` and `mr.close()` promises
are waiting to complete. Those promises capture any errors during their duration
and turn them into rejections. (Errors during those phases are very rare.)

# Compat Interface

## Differences

### Ports

You aren't guaranteed to get the port you ask for. If the port you asked
for is in use, it will be incremented until an available port is found.

`server.port` and `server.registry` contain the port that was actually selected.

For compatibility reasons:

`common.port` and `common.registry` will contain the port of the most recent
instance of FakeRegistry. Usually these there is only one instance and so
this has the same value as the per-server attributes.

This means that if your fixtures make use of the port or server address they
need to be configured _after_ you construct

### Request Bodies

Request bodies are NOT matched against. Two routes for the same URL but different
request bodies will overwrite one another.

### Call Count Assertions

That is, things like `twice()` that assert that the end point will be hit
two times are not supported. This library does not provide any assertions,
just a barebones http server.

### Default Route Behavior

If no route can be found then a `404` response will be provided.

## Construction

const common = require('../common-tap.js')
const mr = common.mockRegistry.compat

### mr(options[, callback]) → Promise(server)

Construct a new mock server. Hybrid, callback/promise constructor. Options
are `port` and `keepNodeAlive`. `keepNodeAlive` defaults to `true` for
compatibility mode and the default value of port comes from `common.port`.

### done()

Resets all of the configured mocks.

### close()

Calls `this.reset()` and `this.server.close()`. To reopen this instance use
`this.listen()`.

### filteringRequestBody()

Does nothing. Bodies are never matched when routing anyway so this is unnecessary.

### get(url) → MockReply
### delete(url) → MockReply
### post(url, body) → MockReply
### put(url, body) → MockReply

Begins to add a route for an HTTP method and URL combo. Does not actually
add it till `reply()` is called on the returned object.

Note that the body argument for post and put is always ignored.

## MockReply methods

### twice() → this

Does nothing. Call count assertions are not supported.

### reply(status, responseBody)

Actually adds the route, set to reply with the associated status and
responseBody.

Currently no mime-types are set.

If `responseBody` is `typeof === 'object'` then `JSON.stringify()` will be
called on it to serialize it, otherwise `String()` will be used.
2 changes: 1 addition & 1 deletion test/tap/audit-fix.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const BB = require('bluebird')

const common = BB.promisifyAll(require('../common-tap.js'))
const fs = require('fs')
const mr = BB.promisify(require('npm-registry-mock'))
const mr = common.fakeRegistry.compat
const path = require('path')
const rimraf = BB.promisify(require('rimraf'))
const Tacks = require('tacks')
Expand Down