• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# FakeRegistry
2
3This is a replacement for npm-registry-mock in times where its fixtures are
4not used.  (Adding support for its standard fixtures is TODO, but should be
5straightforward—tacks-ify them and call `mr.mock…`
6
7# Usage
8
9The intent is for this to be a drop in replacement for npm-registry-mock
10(and by extension hock).  New scripts will be better served using its native
11interface, however.
12
13# Main Interface
14
15## Logging
16
17All requests the mock registry receives are logged at the `http` level. You can
18see these by running your tests with:
19
20```
21npm --loglevel=http run tap test/tap/name-of-test.js
22```
23
24Or directly with:
25
26```
27npm_config_loglevel=http node test/tap/name-of-test.js
28```
29
30## Construction
31
32Ordinarily there's no reason to construct more than one FakeRegistyr object
33at a time, as it can be entirely reset between tests, so best practice
34would be to use its singleton.
35
36```
37const common = require('../common-tap.js')
38const mr = common.fakeRegistry
39```
40
41If you have need of multiple registries at the same time, you can construct
42them by hand:
43
44```
45const common = require('../common-tap.js')
46const FakeRegistry = common.fakeRegistry.FakeRegistry
47const mr = new FakeRegistry(opts)
48```
49
50## new FakeRegistry(opts)
51
52Valid options are:
53
54* `opts.port` is the first port to try when looking for an available port.  If it
55  is unavialable it will be incremented until one available is found.
56
57  The default value of `port` is taken from `common.npm`.
58
59* `opts.keepNodeAlive` will instruct FakeRegistry to not unref the
60  underlying server.
61
62## mr.reset() → this
63
64Reset all mocks to their default values. Further requests
65
66## mr.listen() → Promise(mr)
67
68Start listening for connections.  The promise resolves when the server is
69online and ready to accept connections.
70
71`mr.port` and `mr.registry` contain the port that was actually selected.
72
73To ease compatibility, `common` will also have its `port` and `registry`
74values updated at this time. Note that this means `common.port` refers
75to the port of the most recent listening server. Each server will maintain
76its own `mr.port`.
77
78Any errors emitted by the server while it was coming online will result in a
79promise rejection.
80
81## mr.mock(method, url, respondWith) → this
82
83Adds a new route that matches `method` (should be all caps) and `url`.
84
85`respondWith` can be:
86
87* A function, that takes `(request, response)` as arguments and calls
88  [`response` methods](https://nodejs.org/api/http.html#http_class_http_serverresponse)
89  to do what it wants.  Does not have a return value.  This function may be
90  async (the response isn't complete till its stream completes), typically
91  either because you piped something into it or called `response.end()`.
92* An array of `[statusCode, responseBody]`. `responseBody` may be a string or
93  an object. Objects are serialized with `JSON.stringify`.
94
95## mr.close() → Promise(mr)
96
97Calls `mr.reset()` to clear the mocks.
98
99Calls `.close()` on the http server.  The promise resolves when the http
100server completes closing.  Any errors while the http server was closing will
101result in a rejection. If running with `keepNodeAlive` set this call
102is required for node to exit the event loop.
103
104# Events
105
106## mr.on('error', err => { … })
107
108Error events from the http server are forwarded to the associated fake
109registry instance.
110
111The exception to this is while the `mr.listen()` and `mr.close()` promises
112are waiting to complete. Those promises capture any errors during their duration
113and turn them into rejections. (Errors during those phases are very rare.)
114
115# Compat Interface
116
117## Differences
118
119### Ports
120
121You aren't guaranteed to get the port you ask for.  If the port you asked
122for is in use, it will be incremented until an available port is found.
123
124`server.port` and `server.registry` contain the port that was actually selected.
125
126For compatibility reasons:
127
128`common.port` and `common.registry` will contain the port of the most recent
129instance of FakeRegistry.  Usually these there is only one instance and so
130this has the same value as the per-server attributes.
131
132This means that if your fixtures make use of the port or server address they
133need to be configured _after_ you construct
134
135### Request Bodies
136
137Request bodies are NOT matched against. Two routes for the same URL but different
138request bodies will overwrite one another.
139
140### Call Count Assertions
141
142That is, things like `twice()` that assert that the end point will be hit
143two times are not supported.  This library does not provide any assertions,
144just a barebones http server.
145
146### Default Route Behavior
147
148If no route can be found then a `404` response will be provided.
149
150## Construction
151
152const common = require('../common-tap.js')
153const mr = common.fakeRegistry.compat
154
155### mr(options[, callback]) → Promise(server)
156
157Construct a new mock server.  Hybrid, callback/promise constructor. Options
158are `port` and `keepNodeAlive`.  `keepNodeAlive` defaults to `true` for
159compatibility mode and the default value of port comes from `common.port`.
160
161### done()
162
163Resets all of the configured mocks.
164
165### close()
166
167Calls `this.reset()` and `this.server.close()`.  To reopen this instance use
168`this.listen()`.
169
170### filteringRequestBody()
171
172Does nothing. Bodies are never matched when routing anyway so this is unnecessary.
173
174### get(url) → MockReply
175### delete(url) → MockReply
176### post(url, body) → MockReply
177### put(url, body) → MockReply
178
179Begins to add a route for an HTTP method and URL combo.  Does not actually
180add it till `reply()` is called on the returned object.
181
182Note that the body argument for post and put is always ignored.
183
184## MockReply methods
185
186### twice() → this
187
188Does nothing. Call count assertions are not supported.
189
190### reply(status, responseBody)
191
192Actually adds the route, set to reply with the associated status and
193responseBody.
194
195Currently no mime-types are set.
196
197If `responseBody` is `typeof === 'object'` then `JSON.stringify()` will be
198called on it to serialize it, otherwise `String()` will be used.
199