# @trinitymirrordigital/dragonfly-jest-config

Setup standard Jest config for dragonfly projects

## Install

```bash
yarn add -D jest @trinitymirrordigital/dragonfly-jest-config jest-extended
```

## Usage

Create jest.config.js in the root of your project and add the following:

```javascript
/*
 * For a detailed explanation regarding each configuration property, visit:
 * https://jestjs.io/docs/configuration
 */

const jestConfig = require('@trinitymirrordigital/dragonfly-jest-config');

module.exports = {
  ...jestConfig,
  // Add your specific project config here
};
```

then add the following to the following to your package.json:

```json
"scripts": {
  "test": "yarn run test:jest",
  "test:jest": "jest",
  "test:jest:watch": "jest --watch",
  "test:jest:watch:slow": "jest --watch --no-cache",
},
```

## Packages that are included:

- [Jest](https://jestjs.io/) - main unit testing
- [Jest-extends](https://github.com/jest-community/jest-extended) - additional expects
- [jest-fetch-mock](https://github.com/jefflau/jest-fetch-mock) - for mock fetch requests

## Helper methods

For fetch methods jest-fetch-mock is bound to the global scope so the following will work:

```javascript
//api.test.js
import { APIRequest } from './api';

describe('testing api', () => {
  beforeEach(() => {
    fetch.resetMocks();
  });

  it('calls google and returns data to me', async () => {
    fetch.mockResponseOnce(JSON.stringify({ data: '12345' }));

    //assert on the response
    const res = await APIRequest('google');
    expect(res.data).toEqual('12345');

    //assert on the times called and arguments given to fetch
    expect(fetch.mock.calls.length).toEqual(1);
    expect(fetch.mock.calls[0][0]).toEqual('https://google.com');
  });
});
```

### ManageMocks

To help manage mocks you can utilise the manageMock global object:

To add:

```javascript
manageMock.add(myMock);
//or
manageMock.add([myMock, myMock2, myMock3]);
```

to clear all mocks:

```javascript
manageMock.clearAfter(); // triggers afterEach method
// or
afterEach(() => {
  manageMock.clear();
});
```

to reset all mocks:

```javascript
afterEach(() => {
  manageMock.reset();
});
```

to remove a move from the mockManager:

```javascript
manageMock.removeAll(); // triggers afterAll
```

to remove a specific mock:

```javascript
afterAll(() => {
  manageMock.delete(myMock);
});
```

### Event helper

So if you need to mock a click event just call the following:

```javascript
const myButton = document.querySelector('button');
global.simulateEvent(myButton, 'click');
```

### Sizing helpers

Jest will often return 0 for these values, so if you need to mock page size you can do the following :

For clientWidth:

```javascript
const myDiv = document.querySelector('.some-div');
myDiv._MockClientWidth = 250;
expect(myDiv.clientWidth).toEqual(250);
```

For clientHeight:

```javascript
const myDiv = document.querySelector('.some-div');
myDiv._MockClientHeight = 250;
expect(myDiv.clientHeight).toEqual(250);
```

for getBoundingClientRect:

```javascript
const myDiv = document.querySelector('.some-div');
myDiv._MockClientRect = { left: 250, top: 10, right: 20, bottom: 20, width: 250, height: 250 };
expect(myDiv.getBoundingClientRect()).toContainAllEntries([
  ['left', 250],
  ['top', 10],
  ['right', 20],
  ['bottom', 20],
  ['width', 250],
  ['height', 250],
]);
```

## Additional Extends

### Element matchers

| Matcher           | Example                                                                          |
| :---------------- | :------------------------------------------------------------------------------- |
| toBeElement       | `expect(document.createElement('div')).toBeElement();`                           |
| toHaveAttribute   | `expect(document.querySelector('div')).toHaveAttribute('aria-hidden', 'false');` |
| toHaveTextContent | `expect(document.querySelector('div')).toHaveTextContent('Some text');`          |
| toHaveCssClass    | `expect(document.querySelector('div')).toHaveCssClass('some-class');`            |

### ShadowDom matcher

| Matcher             | Example                                                                                  |
| :------------------ | :--------------------------------------------------------------------------------------- |
| toHaveShadowElement | `expect(document.querySelector('my-component')).toHaveShadowElement('h1');`              |
| toHaveShadowClass   | `expect(document.querySelector('my-component')).toHaveShadowClass('div', 'some-class');` |

### Other Matchers

| Matcher     | Example                                                |
| :---------- | :----------------------------------------------------- |
| toBeElement | `expect(document.createElement('div')).toBeElement();` |
| hasKey      | `expect({foo: 'bar'}).hasKey('foo');`                  |
