nodejs/deps/npm/test/fake-registry.js
isaacs 1721034a40 deps: upgrade npm to 6.10.0
PR-URL: https://github.com/nodejs/node/pull/28525
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
2019-07-18 15:12:49 -07:00

157 lines
4.1 KiB
JavaScript

'use strict'
const common = require('./common-tap.js')
const Bluebird = require('bluebird')
const silentLogger = {
http: () => {},
silly: () => {}
}
const log = process.env.TAP_CHILD_ID
? silentLogger
: require('npmlog')
const http = require('http')
const EventEmitter = require('events')
// See fake-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)
}