Giter VIP home page Giter VIP logo

snapstub's Introduction


snapstub logo

snapstub

NPM version GitHub Actions License

Snapshot-based stub/mocking of APIs

Small command line tool that allows you to take "snapshots" of any given API endpoint and store the response. Using the start command will spawn a server that will serve all previously stored endpoints.

Heavily inspired by Jest Snapshot testing

Table of Contents

Install

npm install -g snapstub

Usage

Make sure you're in the desired folder to host your api mock files.

โฌ‡๏ธ Creates a new api stub:

snapstub add http://example.com/api/foo/bar

...create as many snapshots as you want.

๐Ÿš€ Starts your mock server:

snapstub start

โœจ Your endpoint will be locally available at: http://localhost:8059/api/foo/bar


Advanced Usage

Using different http methods

If you want to save one or many different http methods, use the --method option:

snapstub add http://example.com/api/foo/bar --method=get,post,put

Using custom headers to add a new route

If you need to pass a custom header along with your request, let's say one is needed for a auth token or any other reason, use the --header option:

snapstub add http://example.com/api/user/42 --header "X-Token: 1234"

You can set as many custom headers as you need:

snapstub add http://example.com/api/login --header "X-User: foo" --header "X-Token: bar"

Using html or plain text

In order to save or add a html or plain text endpoint a --nojson flag must be specified in order to bypass json encode/decode:

snapstub add http://example.com/html --nojson

Sending data when adding a new route

Usually a POST/PUT method will also require data to be sent along with the request, you can do so by using the --data option:

snapstub add http://example.com/api/user/new --data "name=Foo"

Content-Type headers will be set automatically but if you specify one (using --header option) that will take precedence.

It also accepts json data (Content-Type will be set to application/json automatically):

snapstub add http://example.com/api/user/new --data '{ "name": "Lorem" }'

If no method is defined it defaults to POST, if you want to use PUT instead just use the --method option:

snapstub add http://example.com/api/user/update --data "name=Bar" --method=put

Sending data read from a file

You can also point the --data option to a file in order to use the contents of that file as a payload. This is a good way to maintain repeatable calls to POST/PUT routes. Given that there is a payload.json file in the current working directory:

snapstub add http://example.com/api/user/add --data ./payload.json

Headers will be automatically added and the content will be exactly as read from the file.

Saving standard input data into a new endpoint

This is a very useful workflow that allows you to combine Chrome's Copy as cURL web dev tools option with the ability to store a snapstub route.

curl http://example.com/api/foo | snapstub save /api/foo

or you can just save any arbitrary data:

cat foo.json | snapstub save /api/foo # similar to $ cp foo.json __mocks__/api/foo

or even:

echo '{"data":true}' | snapstub save /api/foo

Deterministic mocks using query-string or headers

snapstub provides out of the box support to deterministic mocking by using query-string, headers, cookies thanks to request-hash. Deterministic results for those cases will create a file name suffixed by a unique hash which snapstub uses in order to serve the correct value when using the snapstub start server.

Deterministic results for query strings in the urls is active by default, for headers or cookies however you'll need to configure which values you'll want to use in order to create the unique hash. It can be set using the --hashHeaders or --hashCookies options:

snapstub add http://example.com/api/user/42 --header "X-Token: 1234" --hashHeaders=x-token
โœ”  Successfully added: __mocks__/api/user/42/get-491db12454c89a51646710b06bc6c51f9d45.json

Both --hashHeaders and --hashCookies accepts a comma-separated list of keys.

Customizing hash algorithm

The algorithm used to create the unique hash can also be customized using the --hashAlgorithm option.

Change defaults

Using custom port and/or folder name:

export SNAPSTUB_FOLDER_NAME=my-mock-folder/
export SNAPSTUB_PORT=9000
snapstub start

More info

By default snapshots will be saved in a __mocks__ folder that resolves from the current working directory, so make sure you run the commands from the correct project folder you desire.


Programmatic API

A JavaScript programmatic api is available if you're using node.js:

const snapstub = require('snapstub');

// starts the mock server
snapstub.start({
	verbose: true,
	mockFolderName: '__mocks__',
	port: 8080
});

The following methods are available, please note all values used are just example values meant to ilustrate a common usage:

add(opts)

snapstub.add({
	url: 'http://example.com/api/v1/data',
	addOptions: {
		headers: {
			'content-type': 'application/json',
			'Cookie': 'FOO=bar;'
		},
		body: 'lorem=ipsum',
		method: 'post'
	},
	mockFolderName: '__mocks__'
});

save(opts)

snapstub.save({
	url: '/api/v1/data',
	saveOptions: {
		data: { foo: 'bar' },
		headers: { 'X-Foo': 'bar' },
		hashAlgorithm: 'sha256',
		hashHeaders: ['x-foo'],
		hashCookies: [],
		method: 'post',
		nojson: false
	},
	mockFolderName: '__mocks__'
});

start(opts)

snapstub.start({
	hashAlgorithm: 'sha256',
	hashHeaders: ['x-foo'],
	hashCookies: [],
	verbose: true,
	mockFolderName: '__mocks__',
	port: 8080
});

stop()

snapstub.stop();

Credits

  • Logo: Camera by Simon Child from the Noun Project
  • snapstub wouldn't be possible without stubborn-server - it's a very flexible mock server based on static files, if you have the need to handle more complex scenarios (handling route params, dynamic responses, etc) go take a look at it.

Maintainers

Contribute

Please do! This is an open source project. If you would like a feature, open a pull request. If you have a bug or want to discuss something, open an issue.

License

MIT ยฉ Ruy Adorno

snapstub's People

Contributors

g-harel avatar igneel64 avatar lpmi-13 avatar richardlitt avatar ruyadorno avatar sdepold avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

snapstub's Issues

Status code 204 not handled

Hello,
When a request (giving a HTTP 204) is recorded, the resulting file looks like:
get-bbf8b8270b12be24192d49e1363a9e936e11d94332d0bf02d594e731023c9f8c.json

and its content is empty. Whenever stubborn serves this file, it gets an exception as it tries to parse the content thinking it is json (I had to put some console.logs in stubborn to uncover this stack trace). In the end, a HTTP 404 is sent back to the client.

SyntaxError: C:\dev\__mocks__\get-bbf8b8270b12be24192d49e1363a9e936e11d94332d0bf02d594e731023c9f8c.json: Unexpected end of JSON input
    at parse (<anonymous>)
    at Object.Module._extensions..json (internal/modules/cjs/loader.js:1128:22)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Module.require (internal/modules/cjs/loader.js:974:19)
    at Module.hijacked [as require] (C:\dev\node_modules\stubborn-server\server\force-require.js:14:28)
    at require (internal/modules/cjs/helpers.js:92:18)
    at hashLoader (C:\dev\node_modules\stubborn-server-hash-loader\lib\index.js:27:17)
    at C:\dev\node_modules\stubborn-server\server\path-resolver.js:24:34
    at Array.reduce (<anonymous>)

I see stubborn has a possibility to have a custom js file to handle the response. If I remove the mock and replace it by:
C:\dev_mocks_\get-bbf8b8270b12be24192d49e1363a9e936e11d94332d0bf02d594e731023c9f8c.js with this content:

module.exports = (req, res, stub) => {
  res.status(204).send();
};

then my webapp receives the HTTP 204.

Do you think it would be possible to have this in snapstub?
Thanks.

Support for query parameters

Currently, it seems the system doesn't support multiple api endpoints with different query parameters.

snapstub add http://example.com/api/v1/something/?q=query1
snapstub add http://example.com/api/v1/something/?q=query2

In this case, both api have different response, but only 1 response is saved under __mocks. The second one will overwrite the first one.

Mechanism to add endpoints from secure hosts that do not contain a valid certificate

Unfortunatly, some dev environment are less flexible than others and dev stacks are run on ssl port only.

example : snapstub add https://localhost

the work around is to call export NODE_TLS_REJECT_UNAUTHORIZED="0" before stubing but it's a bit insecure for all command that follows as it affect all processes started from the same cli and child nodes as well

my suggestion is to add a flag to snapstub to configure in it's process only with process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; just before the request call to scope that security issue only within the mock tool

What do you think?
maybe it should be implemented into stubborn-server instead?

otherwise it's not blocking anything
image

Request: optional config file

Hello @ruyadorno,

First off thanks for the awesome tool!

As the title states it would be awesome if we were able to use an optional config file. In my case for example we have a ton of endpoints and need to include a bunch of custom headers. Having to either type out the commands manually or writing a script for it might not be ideal for everyone so might I suggest the use of a config file or something similar. The structure for it could be quite simple, the following for example:

{
  "headers": {
    "name": "value"
  },
  "methods": ["get", "put"],
  "endpoints": [
    "some/api/endpoint"
  ]
}

It might even be nice to have the option to create multiple of these objects as you might not want to test the same methods for each endpoint.

If you have any reasons why this is a bad idea please share them so we might be able to come up with a good alternative.

trailing whitespaces inside empty objects and empty arrays

right now if I run:

curl https://cdn.example.com/foo.json | snapstub save /foo

and the JSON response contains empty objects/arrays like:

{ "foo": [], "bar": {} }

the saved file will be formatted like (note trailing whitespaces):

{
    "foo": [
        
    ],
    "bar": {
        
    }
}

I would expect it to be formatted like this instead:

{
  "foo": [],
  "bar": {}
}

Maybe we should use JSON.stringify({ "foo": [], "bar": {} }, undefined, ' ') instead of jsonlint/lib/formatter? - one advantage is that jsonlint is able to format invalid/broken JSON as well tho...

Not all routes are shown when snapstub start is called.

When you start the server, you don't see any routes for folders that only have hashed filenames in them.

In start.js you have the following line defining the glob which is used to figure out which routes to show in printRoutes():

const patterns = methods.map(m => **/${m}.+(json|js|mjs|cjs));

if you change this by adding a * after ${m}:

const patterns = methods.map(m => **/${m}*.+(json|js|mjs|cjs));

then you will see all routes, even for folders that only contained hashed filenames.

Also would be nice if we could turn off the output when calling save programmatically. Or better still also let us pass in a log4js logger instance to use for the output.

Thanks!

Upgrading to stubborn-server@2

Hey @ruyadorno, I have used this package with a really nice use-case that would require the CORS upgrade that we added in zeachco/stubborn-server#54.

Would it be in your plans to allow a PR with the upgrade? As I have seen from the release notes the only breaking change is requirment of Node >= 10.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.