diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 04a8ce94a..48021c0a6 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at nock+coc@martynus.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at nock+coc@martynus.net or richard@maintainer.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..b4ff30fa2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,60 @@ +# Contribute + +👋 Thanks for thinking about contributing to nock! We, the maintainers, are glad you're here and will be excited to help you get started if you have any questions. For now, here are some basic instructions for how we manage this project. + +Please note that this project is released with a [Contributor Code of Conduct](./CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. + +**Table of Contents** + + + +- [Commit Message conventions](#commit-message-conventions) +- [Generate README TOC](#generate-readme-toc) +- [Running tests](#running-tests) + * [Airplane mode](#airplane-mode) + + + +### Commit Message conventions + +`nock` releases are automated using [semantic-release](https://github.com/semantic-release/semantic-release). +To automatically calculate the correct version number as well as changelogs, +three commit message conventions need to be followed + +- Commit bug fixes with `fix: ...` or `fix(scope): ...` prefix in commit subject +- Commit new features with `feat: ...` or `feat(scope): ...` prefix in commit subject +- Commit breaking changes by adding `BREAKING CHANGE: ` in the commit body + (not the subject line) + +Other helpful conventions are + +- Commit test files with `test: ...` or `test(scope): ...` prefix +- Commit changes to `package.json`, `.gitignore` and other meta files with + `chore(filename-without-ext): ...` +- Commit changes to README files or comments with `docs: ...` +- Code style changes with `style: standard` + +The commit message(s) of a pull request can be fixed using the `squash & merge` button. + +### Generate README TOC + +Make sure to update the README's table of contents whenever you update the README using the following npm script. + +``` +$ npm run toc +``` + +### Running tests + +``` +$ npm test +``` + +#### Airplane mode + +Some of the tests depend on online connectivity. To skip them, set the `AIRPLANE` environment variable to some value. + +``` +$ export AIRPLANE=true +$ npm test +``` \ No newline at end of file diff --git a/LICENSE b/LICENSE index ccfa6f7c4..f199fa83e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Pedro Teixeira and other contributors +Copyright (c) 2011-2018 Pedro Teixeira and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8bd409305..ec7c3b965 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Greenkeeper](https://badges.greenkeeper.io/nock/nock.svg)](https://greenkeeper.io/) -Nock is an HTTP mocking and expectations library for Node.js +Nock is an HTTP server mocking and expectations library for Node.js. Nock can be used to test modules that perform HTTP requests in isolation. @@ -18,7 +18,7 @@ For instance, if a module performs HTTP requests to a CouchDB server or makes HT - [How does it work?](#how-does-it-work) - [Install](#install) * [Node version support](#node-version-support) -- [Use](#use) +- [Usage](#usage) * [READ THIS! - About interceptors](#read-this---about-interceptors) * [Specifying hostname](#specifying-hostname) * [Specifying path](#specifying-path) @@ -48,7 +48,7 @@ For instance, if a module performs HTTP requests to a CouchDB server or makes HT * [Request Body filtering](#request-body-filtering) * [Request Headers Matching](#request-headers-matching) * [Optional Requests](#optional-requests) - * [Allow __unmocked__ requests on a mocked hostname](#allow-unmocked-requests-on-a-mocked-hostname) + * [Allow __unmocked__ requests on a mocked hostname](#allow-__unmocked__-requests-on-a-mocked-hostname) - [Expectations](#expectations) * [.isDone()](#isdone) * [.cleanAll()](#cleanall) @@ -73,30 +73,27 @@ For instance, if a module performs HTTP requests to a CouchDB server or makes HT - [Nock Back](#nock-back) * [Setup](#setup) + [Options](#options) - * [Usage](#usage) + * [Usage](#usage-1) + [Options](#options-1) + [Modes](#modes) - [Debugging](#debugging) - [PROTIP](#protip) - [Contributing](#contributing) - * [Generate README TOC](#generate-readme-toc) - * [Running tests](#running-tests) - + [Airplane mode](#airplane-mode) - [License](#license) -# How does it work? +## How does it work? Nock works by overriding Node's `http.request` function. Also, it overrides `http.ClientRequest` too to cover for modules that use it directly. -# Install +## Install ```sh -$ npm install nock +$ npm install --save nock ``` -## Node version support +### Node version support | node | nock | |---|---| @@ -107,7 +104,7 @@ $ npm install nock | 5 | up to 8.x | | 6 | 9.x | -# Use +## Usage On your test, you can setup your mocking object like this: @@ -130,14 +127,14 @@ It will intercept an HTTP GET request to '/users/1' and reply with a status 200, Then the test can call the module, and the module will do the HTTP requests. -## READ THIS! - About interceptors +### READ THIS! - About interceptors When you setup an interceptor for a URL and that interceptor is used, it is removed from the interceptor list. This means that you can intercept 2 or more calls to the same URL and return different things on each of them. It also means that you must setup one interceptor for each request you are going to have, otherwise nock will throw an error because that URL was not present in the interceptor list. If you don’t want interceptors to be removed as they are used, you can use the [.persist()](#persist) method. -## Specifying hostname +### Specifying hostname The request hostname can be a string or a RegExp. @@ -153,9 +150,9 @@ var scope = nock(/example\.com/) .reply(200, 'domain regex matched'); ``` -> (You can choose to include or not the protocol in the hostname matching) +> Note: You can choose to include or not the protocol in the hostname matching. -## Specifying path +### Specifying path The request path can be a string, a RegExp or a filter function and you can use any [HTTP verb](#http-verbs). @@ -185,7 +182,7 @@ var scope = nock('http://www.example.com') .reply(200, 'path using function matched'); ``` -## Specifying request body +### Specifying request body You can specify the request body to be matched as the second argument to the `get`, `post`, `put` or `delete` specifications. There are four types of second argument allowed: @@ -232,7 +229,7 @@ nock('http://www.example.com') ``` -## Specifying request query string +### Specifying request query string Nock understands query strings. Instead of placing the entire URL, you can specify the query part as an object: @@ -281,7 +278,7 @@ nock('http://example.com') .reply(200, {results: [{id: 'pgte'}]}); ``` -## Specifying replies +### Specifying replies You can specify the return status code for a path on the first argument of reply like this: @@ -380,7 +377,7 @@ var scope = nock('http://www.google.com') }); ``` -#### Access original request and headers +##### Access original request and headers If you're using the reply callback style, you can access the original client request using `this.req` like this: @@ -394,7 +391,7 @@ var scope = nock('http://www.google.com') }); ``` -### Replying with errors +#### Replying with errors You can reply with an error like this: @@ -412,16 +409,16 @@ nock('http://www.google.com') .replyWithError({'message': 'something awful happened', 'code': 'AWFUL_ERROR'}); ``` -> NOTE: This will emit an `error` event on the `request` object, not the reply. +> Note: This will emit an `error` event on the `request` object, not the reply. -## Specifying headers +### Specifying headers -### Header field names are case-insensitive +#### Header field names are case-insensitive Per [HTTP/1.1 4.2 Message Headers](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2) specification, all message headers are case insensitive and thus internally Nock uses lower-case for all field names even if some other combination of cases was specified either in mocking specification or in mocked requests themselves. -### Specifying Request Headers +#### Specifying Request Headers You can specify the request headers like this: @@ -482,7 +479,7 @@ var scope = nock('http://www.example.com') .reply(200); ``` -### Specifying Reply Headers +#### Specifying Reply Headers You can specify the reply headers like this: @@ -508,7 +505,7 @@ var scope = nock('http://www.headdy.com') }); ``` -### Default Reply Headers +#### Default Reply Headers You can also specify default reply headers for all responses like this: @@ -535,7 +532,7 @@ var scope = nock('http://www.headdy.com') .reply(200, 'The default headers should come too'); ``` -### Including Content-Length Header Automatically +#### Including Content-Length Header Automatically When using `scope.reply()` to set a response body manually, you can have the `Content-Length` header calculated automatically. @@ -550,7 +547,7 @@ var scope = nock('http://www.headdy.com') **NOTE:** this does not work with streams or other advanced means of specifying the reply body. -### Including Date Header Automatically +#### Including Date Header Automatically You can automatically append a `Date` header to your mock reply: @@ -561,7 +558,7 @@ var scope = nock('http://www.headdy.com') .reply(200, { hello: 'world' }); ``` -## HTTP Verbs +### HTTP Verbs Nock supports any HTTP verb, and it has convenience methods for the GET, POST, PUT, HEAD, DELETE, PATCH and MERGE HTTP verbs. @@ -573,7 +570,7 @@ var scope = nock('http://my.domain.com') .reply(304); ``` -## Support for HTTP and HTTPS +### Support for HTTP and HTTPS By default nock assumes HTTP. If you need to use HTTPS you can specify the `https://` prefix like this: @@ -582,7 +579,7 @@ var scope = nock('https://secure.my.server.com') // ... ``` -## Non-standard ports +### Non-standard ports You are able to specify a non-standard port like this: @@ -591,7 +588,7 @@ var scope = nock('http://my.server.com:8081') ... ``` -## Repeat response n times +### Repeat response n times You are able to specify the number of times to repeat the same response. @@ -613,7 +610,7 @@ nock('http://zombo.com').get('/').twice().reply(200, 'Ok'); nock('http://zombo.com').get('/').thrice().reply(200, 'Ok'); ``` -## Delay the response body +### Delay the response body You are able to specify the number of milliseconds that the response body should be delayed. Response header will be replied immediately. `delayBody(1000)` is equivalent to `delay({body: 1000})`. @@ -627,7 +624,7 @@ nock('http://my.server.com') NOTE: the [`'response'`](http://nodejs.org/api/http.html#http_event_response) event will occur immediately, but the [IncomingMessage](http://nodejs.org/api/http.html#http_http_incomingmessage) will not emit it's `'end'` event until after the delay. -## Delay the response +### Delay the response You are able to specify the number of milliseconds that your reply should be delayed. @@ -659,11 +656,11 @@ nock('http://my.server.com') .reply(200, '') ``` -## Delay the connection +### Delay the connection `delayConnection(1000)` is equivalent to `delay({head: 1000})`. -## Socket timeout +### Socket timeout You are able to specify the number of milliseconds that your connection should be idle, to simulate a socket timeout. @@ -688,7 +685,7 @@ req.end(); NOTE: the timeout will be fired immediately, and will not leave the simulated connection idle for the specified period of time. -## Chaining +### Chaining You can chain behaviour like this: @@ -714,7 +711,7 @@ var scope = nock('http://myapp.iriscouch.com') }); ``` -## Scope filtering +### Scope filtering You can filter the scope (protocol, domain or port) of nock through a function. The filtering function is accepted at the `filteringScope` field of the `options` argument. @@ -730,7 +727,7 @@ var scope = nock('https://api.dropbox.com', { .reply(200); ``` -## Path filtering +### Path filtering You can also filter the URLs based on a function. @@ -758,7 +755,7 @@ var scope = nock('http://api.myservice.com') Note that `scope.filteringPath` is not cumulative: it should only be used once per scope. -## Request Body filtering +### Request Body filtering You can also filter the request body based on a function. @@ -784,7 +781,7 @@ var scope = nock('http://api.myservice.com') .reply(201, 'OK'); ``` -## Request Headers Matching +### Request Headers Matching If you need to match requests only if certain request headers match, you can. @@ -821,7 +818,7 @@ var scope = nock('http://api.myservice.com') }) ``` -## Optional Requests +### Optional Requests By default every mocked request is expected to be made exactly once, and until it is it'll appear in `scope.pendingMocks()`, and `scope.isDone()` will return false (see [expectations](#expectations)). In many cases this is fine, but in some (especially cross-test setup code) it's useful to be able to mock a request that may or may not happen. You can do this with `optionally()`. Optional requests are consumed just like normal ones once matched, but they do not appear in `pendingMocks()`, and `isDone()` will return true for scopes with only optional requests pending. @@ -838,7 +835,7 @@ example.get("/pathB").optionally().reply(200); example.pendingMocks() // [] ``` -## Allow __unmocked__ requests on a mocked hostname +### Allow __unmocked__ requests on a mocked hostname If you need some request on the same host name to be mocked and some others to **really** go through the HTTP stack, you can use the `allowUnmocked` option like this: @@ -852,9 +849,9 @@ var scope = nock('http://my.existing.service.com', options) // GET /other/url => actually makes request to the server ``` -> Bear in mind that, when applying `{allowUnmocked: true}` if the request is made to the real server, no interceptor is removed. +> Note: When applying `{allowUnmocked: true}`, if the request is made to the real server, no interceptor is removed. -# Expectations +## Expectations Every time an HTTP request is performed for a scope that is mocked, Nock expects to find a handler for it. If it doesn't, it will throw an error. @@ -874,7 +871,7 @@ setTimeout(function() { }, 5000); ``` -## .isDone() +### .isDone() You can call `isDone()` on a single expectation to determine if the expectation was met: @@ -892,14 +889,14 @@ It is also available in the global scope, which will determine if all expectatio nock.isDone(); ``` -## .cleanAll() +### .cleanAll() You can cleanup all the prepared mocks (could be useful to cleanup some state after a failed test) like this: ```js nock.cleanAll(); ``` -## .persist() +### .persist() You can make all the interceptors for a scope persist by calling `.persist()` on it: @@ -920,7 +917,7 @@ var scope = nock('http://example.com').persist().get('/').reply(200, 'ok'); scope.persist(false); ``` -## .pendingMocks() +### .pendingMocks() If a scope is not done, you can inspect the scope to infer which ones are still pending using the `scope.pendingMocks()` function: @@ -936,7 +933,7 @@ It is also available in the global scope: console.error('pending mocks: %j', nock.pendingMocks()); ``` -## .activeMocks() +### .activeMocks() You can see every mock that is currently active (i.e. might potentially reply to requests) in a scope using `scope.activeMocks()`. A mock is active if it is pending, optional but not yet completed, or persisted. Mocks that have intercepted their requests and are no longer doing anything are the only mocks which won't appear here. @@ -952,7 +949,7 @@ It is also available in the global scope: console.error('active mocks: %j', nock.activeMocks()); ``` -## .isActive() +### .isActive() Your tests may sometimes want to deactivate the nock interceptor. Once deactivated, nock needs to be re-activated to work. @@ -963,7 +960,7 @@ Sample: if (!nock.isActive()) nock.activate() ``` -# Logging +## Logging Nock can log matches if you pass in a log function like this: @@ -973,7 +970,7 @@ var google = nock('http://google.com') ... ``` -# Restoring +## Restoring You can restore the HTTP interceptor to the normal unmocked behaviour by calling: @@ -984,7 +981,7 @@ nock.restore(); **note 2**: restore will also remove the http interceptor itself. You need to run [nock.activate()](#activating) to re-activate the http interceptor. Without re-activation, nock will not intercept any calls. -# Activating +## Activating Only for cases where nock has been deactivated using [nock.restore()](#restoring), you can reactivate the HTTP interceptor to start intercepting HTTP calls using: @@ -994,7 +991,7 @@ nock.activate(); **note**: To check if nock HTTP interceptor is active or deactive, use [nock.isActive()](#isactive). -# Turning Nock Off (experimental!) +## Turning Nock Off (experimental!) You can bypass Nock completely by setting `NOCK_OFF` environment variable to `"true"`. @@ -1004,7 +1001,7 @@ This way you can have your tests hit the real servers just by switching on this $ NOCK_OFF=true node my_test.js ``` -# Enable/Disable real HTTP request +## Enable/Disable real HTTP request By default, any requests made to a host that is not mocked will be executed normally. If you want to block these requests, nock allows you to do so. @@ -1064,7 +1061,7 @@ nock.cleanAll(); nock.enableNetConnect(); ``` -# Recording +## Recording This is a cool feature: @@ -1084,7 +1081,7 @@ In order to stop recording you should call `nock.restore()` and recording will s **ATTENTION!:** when recording is enabled, nock does no validation, nor will any mocks be enabled. Please be sure to turn off recording before attempting to use any mocks in your tests. -## `dont_print` option +### `dont_print` option If you just want to capture the generated code into a var as an array you can use: @@ -1102,7 +1099,7 @@ Copy and paste that code into your tests, customize at will, and you're done! Yo (Remember that you should do this one test at a time). -## `output_objects` option +### `output_objects` option In case you want to generate the code yourself or use the test data in some other way, you can pass the `output_objects` option to `rec`: @@ -1165,7 +1162,7 @@ nockDefs.forEach(function(def) { var nocks = nock.define(nockDefs); ``` -## `enable_reqheaders_recording` option +### `enable_reqheaders_recording` option Recording request headers by default is deemed more trouble than its worth as some of them depend on the timestamp or other values that may change after the tests have been recorder thus leading to complex postprocessing of recorded tests. Thus by default the request headers are not recorded. @@ -1181,7 +1178,7 @@ nock.recorder.rec({ Note that even when request headers recording is enabled Nock will never record `user-agent` headers. `user-agent` values change with the version of Node and underlying operating system and are thus useless for matching as all that they can indicate is that the user agent isn't the one that was used to record the tests. -## `logging` option +### `logging` option Nock will print using `console.log` by default (assuming that `dont_print` is `false`). If a different function is passed into `logging`, nock will send the log string (or object, when using `output_objects`) to that function. Here's a basic example. @@ -1194,7 +1191,7 @@ nock.recorder.rec({ }); ``` -## `use_separator` option +### `use_separator` option By default, nock will wrap it's output with the separator string `<<<<<<-- cut here -->>>>>>` before and after anything it prints, whether to the console or a custom log function given with the `logging` option. @@ -1206,7 +1203,7 @@ nock.recorder.rec({ }); ``` -## .removeInterceptor() +### .removeInterceptor() This allows removing a specific interceptor. This can be either an interceptor instance or options for a url. It's useful when there's a list of common interceptors shared between tests, where an individual test requires one of the shared interceptors to behave differently. Examples: @@ -1232,14 +1229,14 @@ var interceptor = nock('http://example.org') nock.removeInterceptor(interceptor); ``` -# Events +## Events A scope emits the following events: * `emit('request', function(req, interceptor, body))`; * `emit('replied', function(req, interceptor))`; -## Global no match event +### Global no match event You can also listen for no match events like this: @@ -1249,11 +1246,11 @@ nock.emitter.on('no match', function(req) { }); ``` -# Nock Back +## Nock Back fixture recording support and playback -## Setup +### Setup **You must specify a fixture directory before using, for example: @@ -1266,13 +1263,13 @@ nockBack.fixtures = '/path/to/fixtures/'; nockBack.setMode('record'); ``` -### Options +#### Options - `nockBack.fixtures` : path to fixture directory - `nockBack.setMode()` : the mode to use -## Usage +### Usage By default if the fixture doesn't exist, a `nockBack` will create a new fixture and save the recorded output for you. The next time you run the test, if the fixture exists, it will be loaded in. @@ -1335,7 +1332,7 @@ return nockBack('promisedFixture.json') }); ``` -### Options +#### Options As an optional second parameter you can pass the following options @@ -1345,7 +1342,7 @@ As an optional second parameter you can pass the following options - `recorder`: custom options to pass to the recorder -### Modes +#### Modes to set the mode call `nockBack.setMode(mode)` or run the tests with the `NOCK_BACK_MODE` environment variable set before loading nock. If the mode needs to be changed programatically, the following is valid: `nockBack.setMode(nockBack.currentMode)` @@ -1357,14 +1354,14 @@ to set the mode call `nockBack.setMode(mode)` or run the tests with the `NOCK_BA - lockdown: use recorded nocks, disables all http calls even when not nocked, doesn't record -# Debugging +## Debugging Nock uses debug, so just run with environmental variable DEBUG set to nock.* ```js $ DEBUG=nock.* node my_test.js ``` -# PROTIP +## PROTIP If you don't want to match the request body you can use this trick (by @theycallmeswift): @@ -1377,56 +1374,14 @@ var scope = nock('http://api.myservice.com') .reply(200, 'OK'); ``` -# Contributing +## Contributing + +Thanks for wanting to contribute! Take a look at our [Contributing Guide](CONTRIBUTING.md) for notes on our commit message conventions and how to run tests. Please note that this project is released with a [Contributor Code of Conduct](./CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. -## Commit Message conventions - -`nock` releases are automated using [semantic-release](https://github.com/semantic-release/semantic-release). -To automatically calculate the correct version number as well as changelogs, -three commit message conventions need to be followed - -- Commit bug fixes with `fix: ...` or `fix(scope): ...` prefix in commit subject -- Commit new features with `feat: ...` or `feat(scope): ...` prefix in commit subject -- Commit breaking changes by adding `BREAKING CHANGE: ` in the commit body - (not the subject line) - -Other helpful conventions are - -- Commit test files with `test: ...` or `test(scope): ...` prefix -- Commit changes to `package.json`, `.gitignore` and other meta files with - `chore(filename-without-ext): ...` -- Commit changes to README files or comments with `docs: ...` -- Code style changes with `style: standard` - -The commit message(s) of a pull request can be fixed using the `squash & merge` button. - -## Generate README TOC - -Make sure to update the README's table of contents whenever you update the README using the following npm script. - -``` -$ npm run toc -``` - -## Running tests - -``` -$ npm test -``` - -### Airplane mode - -Some of the tests depend on online connectivity. To skip them, set the `AIRPLANE` environment variable to some value. - -``` -$ export AIRPLANE=true -$ npm test -``` - -# License +## License [MIT](LICENSE) diff --git a/package.json b/package.json index b2073bc6d..b1eb9476f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nock", - "description": "HTTP Server mocking for Node.js", + "description": "HTTP server mocking and expectations library for Node.js", "tags": [ "Mock", "HTTP", @@ -204,7 +204,7 @@ "coverage": "nyc tap --harmony ./tests/test_*.js", "coveralls": "cat ./coverage/lcov.info | coveralls", "lint": "eslint '**/*.js'", - "toc": "markdown-toc -i README.md", + "toc": "markdown-toc -i README.md && markdown-toc -i CONTRIBUTING.md ", "semantic-release": "semantic-release" }, "nyc": {