Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/duailibe/jest-json
Jest matchers to work with JSON strings
https://github.com/duailibe/jest-json
hacktoberfest javascript jest jest-matchers json testing
Last synced: 3 months ago
JSON representation
Jest matchers to work with JSON strings
- Host: GitHub
- URL: https://github.com/duailibe/jest-json
- Owner: duailibe
- License: mit
- Created: 2018-07-19T20:37:20.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2023-09-04T22:12:47.000Z (about 1 year ago)
- Last Synced: 2024-07-19T08:55:13.581Z (4 months ago)
- Topics: hacktoberfest, javascript, jest, jest-matchers, json, testing
- Language: JavaScript
- Homepage:
- Size: 74.2 KB
- Stars: 14
- Watchers: 4
- Forks: 3
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-jest - jest-json
README
# `jest-json`
[![npm](https://img.shields.io/npm/v/jest-json.svg)](https://npmjs.org/jest-json)
[![CI](https://github.com/duailibe/jest-json/actions/workflows/ci.yaml/badge.svg)](https://github.com/duailibe/jest-json/actions/workflows/ci.yaml)
[![codecov](https://codecov.io/gh/duailibe/jest-json/branch/main/graph/badge.svg?token=uUQIzDROrx)](https://codecov.io/gh/duailibe/jest-json)Jest matchers to work with JSON strings.
## Setup
**Note:** If you're using Jest < 27.2.5, you should stick to `jest-json@^1.0`.
Add `jest-json` to your Jest config:
```json
{
"setupTestFrameworkScriptFile": "jest-json"
}
```Or if you're already using another test framework, create a setup file and require each of them:
```js
require("jest-json");
// require("some-jest-library);
```## Motivation
Say you have a function `fetchData` the calls `fetch` with a JSON body and you want to assert that `fetchData` is building the JSON string correctly.
_See this [repl.it](https://repl.it/@duailibe/jest-json-example) for a working example of this problem._
```js
function fetchData(userId, fields = []) {
if (!fields.includes("profilePicture")) {
fields = fields.concat(["profilePicture"]);
}return fetch("/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
params: { id: userId },
fields,
}),
});
}
```One option to write the test would be to check the final string:
```js
test("fetchData", () => {
fetchData("ab394js", ["name", "website"]);expect(fetch).toHaveBeenCalledWith("/users", {
method: "POST",
headers: expect.anything(),
body: JSON.stringify({
params: { id: "ab394js" },
fields: ["name", "website", "profilePicture"],
}),
});
});
```Ok, this works, but that has a few problems:
- you are testing that `"profilePicture"` will be added to the end of the `fields` list,
- you are testing the exact orders the keys of the body JSON are added.If someone changes the test to insert `"profilePicture"` in the beginning of the list, or change the JSON to `JSON.stringify({ fields, params })`, your test will now fail because the JSON string changed, even though it's equivalent to the one in the test. That means we have a flaky test. One way to fix it would be:
```js
global.fetch = jest.fn();test("fetchData", () => {
fetchData("ab394js", ["name", "website"]);expect(fetch).toHaveBeenCalledWith("/users", {
method: "POST",
headers: expect.anything(),
body: expect.anything(),
});expect(JSON.parse(fetch.mock.calls[0][1].body)).toEqual({
params: { id: "ab394js" },
fields: expect.arrayContaining(["name", "website", "profilePicture"]),
});
});
```That's better, and now we can even use `expect.arrayContaining()` to make sure we assert that the values are present, but don't care about the order.
But that's a really inconvenient way to get the string we're interested (`fetch.mock.calls[0][1].body`).
Now compare that test to this:
```js
global.fetch = jest.fn();test("fetchData", () => {
fetchData("ab394js", ["name", "website"]);expect(fetch).toHaveBeenCalledWith("/users", {
method: "POST",
headers: expect.anything(),
body: expect.jsonMatching({
params: { id: "ab394js" },
fields: expect.arrayContaining(["name", "website", "profilePicture"]),
}),
});
});
```Now that's a very neat test.
## API
### `expect.jsonMatching`
In the example above, you can use the `expect.jsonMatching` asymmetric matcher:
```js
expect(foo).toHaveBeenCalledWith(
"url",
expect.jsonMatching({
foo: "bar",
spam: "eggs",
})
);
```You can include other asymmetric matchers inside like:
```js
expect.jsonMatching(
expect.objectContaining({
foo: expect.stringMatching("bar")
})
)
```### `expect().toMatchJSON()`
It's just sugar for calling `JSON.parse()` and then `expect().toEqual()`:
```js
expect(json).toMatchJSON(expected);
// equivalent to:
const tmp = JSON.parse(json);
expect(tmp).toEqual(expected);
```## License
[MIT](./LICENSE)