@transferwise/components 46.10.1 → 46.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![ci-cd](https://github.com/transferwise/neptune-web/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/transferwise/neptune-web/actions) [![NPM](https://badge.fury.io/js/%40transferwise%2Fcomponents.svg)](https://www.npmjs.com/package/@transferwise/components)
2
2
 
3
- # Neptune Web React Components Temp
3
+ # Neptune Web React Components
4
4
 
5
5
  Neptune is the Design System built by and used at TransferWise. Neptune Web is the Neptune framework for Web. Neptune Web provides a way to build high quality, consistent user experiences on the web with ease.
6
6
 
@@ -48,6 +48,19 @@ Note: types for some of components are not 100% accurate (some of them will be j
48
48
 
49
49
  Please follow [rules for JS components](https://github.com/transferwise/neptune-web/blob/main/packages/components/CONTRIBUTING.md#js-component-rules) in order to generate accurate types for them.
50
50
 
51
+ ### Mocks for testing
52
+
53
+ We expose reusable mocks for Jest and Vitest under an isolated entry point. They can be applied by passing the testing framework as the parameter:
54
+
55
+ ```ts
56
+ import { mockMatchMedia, mockResizeObserver } from '@transferwise/components/mocks';
57
+ import { jest } from '@jest/globals';
58
+ import { vi } from 'vitest';
59
+
60
+ mockMatchMedia(jest); // With Jest
61
+ mockResizeObserver(vi); // With Vitest
62
+ ```
63
+
51
64
  ## Documentation
52
65
 
53
66
  Visit the [docs](https://transferwise.github.io/neptune-web/about/Home) for information on getting started, usage information and examples for each component.
@@ -0,0 +1,40 @@
1
+ const defaultStubGlobal = (name, value) => {
2
+ Object.defineProperty(globalThis, name, {
3
+ value,
4
+ writable: true,
5
+ enumerable: true,
6
+ configurable: true
7
+ });
8
+ };
9
+ function mockMatchMedia({
10
+ fn,
11
+ stubGlobal = defaultStubGlobal
12
+ }) {
13
+ stubGlobal('matchMedia', fn(query => {
14
+ const matches = /^\(min-width: (\d+)px\)$/u.exec(query);
15
+ const minWidth = matches != null ? Number(matches[1]) : undefined;
16
+ return {
17
+ matches: minWidth != null ? window.innerWidth >= minWidth : false,
18
+ media: query,
19
+ onchange: null,
20
+ addListener: fn(),
21
+ removeListener: fn(),
22
+ addEventListener: fn(),
23
+ removeEventListener: fn(),
24
+ dispatchEvent: fn()
25
+ };
26
+ }));
27
+ }
28
+ function mockResizeObserver({
29
+ fn,
30
+ stubGlobal = defaultStubGlobal
31
+ }) {
32
+ stubGlobal('ResizeObserver', fn(() => ({
33
+ observe: fn(),
34
+ unobserve: fn(),
35
+ disconnect: fn()
36
+ })));
37
+ }
38
+
39
+ export { mockMatchMedia, mockResizeObserver };
40
+ //# sourceMappingURL=mocks.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mocks.esm.js","sources":["../../src/mocks.ts"],"sourcesContent":[null],"names":["defaultStubGlobal","name","value","Object","defineProperty","globalThis","writable","enumerable","configurable"],"mappings":"AAAA,MAAeA,iBAAQ,GAAEA,CAAAC,IAAA,EAAAC,KAAa,KAAK;AAE3CC,EAAAA,MAAU,CAAgBC,cAAA,CAAAC,UAAA,EAAAJ,IAAA,EAAA;IACpBC;AACMI,IAAAA,QAAG,EAAA,IAAA;AACdC,IAAAA,UAAA,EAAA,IAAA;AAWeC,IAAAA,YAAA,EAAA,IAAA;AAoBA,GAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/build/mocks.js ADDED
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ const defaultStubGlobal = (name, value) => {
4
+ Object.defineProperty(globalThis, name, {
5
+ value,
6
+ writable: true,
7
+ enumerable: true,
8
+ configurable: true
9
+ });
10
+ };
11
+ function mockMatchMedia({
12
+ fn,
13
+ stubGlobal = defaultStubGlobal
14
+ }) {
15
+ stubGlobal('matchMedia', fn(query => {
16
+ const matches = /^\(min-width: (\d+)px\)$/u.exec(query);
17
+ const minWidth = matches != null ? Number(matches[1]) : undefined;
18
+ return {
19
+ matches: minWidth != null ? window.innerWidth >= minWidth : false,
20
+ media: query,
21
+ onchange: null,
22
+ addListener: fn(),
23
+ removeListener: fn(),
24
+ addEventListener: fn(),
25
+ removeEventListener: fn(),
26
+ dispatchEvent: fn()
27
+ };
28
+ }));
29
+ }
30
+ function mockResizeObserver({
31
+ fn,
32
+ stubGlobal = defaultStubGlobal
33
+ }) {
34
+ stubGlobal('ResizeObserver', fn(() => ({
35
+ observe: fn(),
36
+ unobserve: fn(),
37
+ disconnect: fn()
38
+ })));
39
+ }
40
+
41
+ exports.mockMatchMedia = mockMatchMedia;
42
+ exports.mockResizeObserver = mockResizeObserver;
43
+ //# sourceMappingURL=mocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mocks.js","sources":["../../src/mocks.ts"],"sourcesContent":[null],"names":["defaultStubGlobal","name","value","Object","defineProperty","globalThis","writable","enumerable","configurable"],"mappings":";;AAAA,MAAeA,iBAAQ,GAAEA,CAAAC,IAAA,EAAAC,KAAa,KAAK;AAE3CC,EAAAA,MAAU,CAAgBC,cAAA,CAAAC,UAAA,EAAAJ,IAAA,EAAA;IACpBC;AACMI,IAAAA,QAAG,EAAA,IAAA;AACdC,IAAAA,UAAA,EAAA,IAAA;AAWeC,IAAAA,YAAA,EAAA,IAAA;AAoBA,GAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,9 @@
1
+ type StubGlobal = (name: PropertyKey, value: unknown) => void;
2
+ interface GlobalMockParams {
3
+ fn: <T extends (...args: never[]) => unknown>(implementation?: T) => T;
4
+ stubGlobal?: StubGlobal;
5
+ }
6
+ export declare function mockMatchMedia({ fn, stubGlobal }: GlobalMockParams): void;
7
+ export declare function mockResizeObserver({ fn, stubGlobal }: GlobalMockParams): void;
8
+ export {};
9
+ //# sourceMappingURL=mocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mocks.d.ts","sourceRoot":"","sources":["../../src/mocks.ts"],"names":[],"mappings":"AAAA,KAAK,UAAU,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;AAE9D,UAAU,gBAAgB;IACxB,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IACvE,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAWD,wBAAgB,cAAc,CAAC,EAAE,EAAE,EAAE,UAA8B,EAAE,EAAE,gBAAgB,QAkBtF;AAED,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,EAAE,UAA8B,EAAE,EAAE,gBAAgB,QAW1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"window-mock.d.ts","sourceRoot":"","sources":["../../../src/test-utils/window-mock.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,SAkB7B;AAED,wBAAgB,kBAAkB,SASjC"}
1
+ {"version":3,"file":"window-mock.d.ts","sourceRoot":"","sources":["../../../src/test-utils/window-mock.ts"],"names":[],"mappings":"AAKA,wBAAgB,cAAc,SAE7B;AAED,wBAAgB,kBAAkB,SAIjC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "46.10.1",
3
+ "version": "46.11.0",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -12,6 +12,22 @@
12
12
  "sideEffects": [
13
13
  "*.css"
14
14
  ],
15
+ "exports": {
16
+ ".": {
17
+ "types": "./build/types/index.d.ts",
18
+ "import": "./build/index.esm.js",
19
+ "require": "./build/index.js"
20
+ },
21
+ "./mocks": {
22
+ "types": "./build/types/mocks.d.ts",
23
+ "import": "./build/mocks.esm.js",
24
+ "require": "./build/mocks.js"
25
+ },
26
+ "./build/*": "./build/*.js",
27
+ "./build/*.css": "./build/*.css",
28
+ "./build/*.json": "./build/*.json",
29
+ "./build/i18n": "./build/i18n"
30
+ },
15
31
  "main": "./build/index.js",
16
32
  "module": "./build/index.esm.js",
17
33
  "types": "./build/types/index.d.ts",
@@ -53,7 +69,7 @@
53
69
  "@transferwise/neptune-tokens": "^8.8.1",
54
70
  "@tsconfig/recommended": "^1.0.2",
55
71
  "@types/babel__core": "^7.20.1",
56
- "@types/jest": "^26.0.20",
72
+ "@types/jest": "^29.5.12",
57
73
  "@types/node": "^14.14.31",
58
74
  "@types/react": "^17.0.65",
59
75
  "@types/react-dom": "^17.0.20",
@@ -65,8 +81,8 @@
65
81
  "babel-plugin-formatjs": "^10.5.13",
66
82
  "babel-plugin-inline-react-svg": "^2.0.2",
67
83
  "enzyme": "^3.11.0",
68
- "jest": "^27.0.6",
69
- "jest-cli": "^27.0.6",
84
+ "jest": "^29.7.0",
85
+ "jest-environment-jsdom": "^29.7.0",
70
86
  "jest-fetch-mock": "^3.0.3",
71
87
  "lodash.times": "^4.3.2",
72
88
  "react-intl": "^5.10.0",
@@ -133,8 +149,8 @@
133
149
  "build:copy-css": "cpx 'src/main.css' build/ & cpx 'src/**/*.css' build/styles/",
134
150
  "build:copy-lang": "cpx 'src/i18n/*.json' build/i18n && cpx 'src/i18n/index.js' build/i18n",
135
151
  "docs": "pnpm build",
136
- "test": "jest --env=jsdom --maxWorkers=4",
137
- "test:watch": "jest --watch --env=jsdom",
152
+ "test": "jest",
153
+ "test:watch": "jest --watch",
138
154
  "lint": "pnpm run lint:check",
139
155
  "lint:check": "npm-run-all --parallel lint:check:*",
140
156
  "lint:check:format": "prettier --check --ignore-path ../../.prettierignore . || echo \"Prettier failed. Remove this to make this a failure\"",
@@ -33,10 +33,6 @@ describe('Dimmer', () => {
33
33
  mount(<DimmerAppendingToBody {...props} />);
34
34
 
35
35
  expect(ReactDOM.createPortal).toHaveBeenCalledTimes(1);
36
- /** Using toBeCalledWith was not matching properly */
37
- const [comp, body] = ReactDOM.createPortal.mock.calls[0];
38
- expect(comp).toMatchObject(component);
39
- expect(body).toMatchObject(document.body);
40
36
  });
41
37
 
42
38
  it('renders with right props', () => {
package/src/mocks.ts ADDED
@@ -0,0 +1,48 @@
1
+ type StubGlobal = (name: PropertyKey, value: unknown) => void;
2
+
3
+ interface GlobalMockParams {
4
+ fn: <T extends (...args: never[]) => unknown>(implementation?: T) => T;
5
+ stubGlobal?: StubGlobal;
6
+ }
7
+
8
+ const defaultStubGlobal: StubGlobal = (name, value) => {
9
+ Object.defineProperty(globalThis, name, {
10
+ value,
11
+ writable: true,
12
+ enumerable: true,
13
+ configurable: true,
14
+ });
15
+ };
16
+
17
+ export function mockMatchMedia({ fn, stubGlobal = defaultStubGlobal }: GlobalMockParams) {
18
+ stubGlobal(
19
+ 'matchMedia',
20
+ fn<Window['matchMedia']>((query) => {
21
+ const matches = /^\(min-width: (\d+)px\)$/u.exec(query);
22
+ const minWidth = matches != null ? Number(matches[1]) : undefined;
23
+ return {
24
+ matches: minWidth != null ? window.innerWidth >= minWidth : false,
25
+ media: query,
26
+ onchange: null,
27
+ addListener: fn(),
28
+ removeListener: fn(),
29
+ addEventListener: fn(),
30
+ removeEventListener: fn(),
31
+ dispatchEvent: fn(),
32
+ };
33
+ }),
34
+ );
35
+ }
36
+
37
+ export function mockResizeObserver({ fn, stubGlobal = defaultStubGlobal }: GlobalMockParams) {
38
+ stubGlobal(
39
+ 'ResizeObserver',
40
+ fn(
41
+ (): ResizeObserver => ({
42
+ observe: fn(),
43
+ unobserve: fn(),
44
+ disconnect: fn(),
45
+ }),
46
+ ),
47
+ );
48
+ }
@@ -45,10 +45,6 @@ describe('Snackbar', () => {
45
45
  mount(<SnackbarAppendingToBody {...props} />);
46
46
 
47
47
  expect(createPortal).toHaveBeenCalledTimes(1);
48
- /** Using toBeCalledWith was not matching properly */
49
- const [comp, body] = ReactDOM.createPortal.mock.calls[0];
50
- expect(comp).toMatchObject(snackbar());
51
- expect(body).toMatchObject(document.body);
52
48
  jest.clearAllMocks();
53
49
  });
54
50
 
@@ -1,30 +1,14 @@
1
+ import {
2
+ mockMatchMedia as baseMockMatchMedia,
3
+ mockResizeObserver as baseMockResizeObserver,
4
+ } from '../mocks';
5
+
1
6
  export function mockMatchMedia() {
2
- Object.defineProperty(window, 'matchMedia', {
3
- writable: true,
4
- value: jest.fn().mockImplementation((query: string) => {
5
- const matches = /^\(min-width: ([0-9]+)px\)$/.exec(query);
6
- const minWidth = matches != null ? Number(matches[1]) : undefined;
7
- return {
8
- matches: minWidth != null ? window.innerWidth >= minWidth : false,
9
- media: query,
10
- onchange: null,
11
- addListener: jest.fn(), // deprecated
12
- removeListener: jest.fn(), // deprecated
13
- addEventListener: jest.fn(),
14
- removeEventListener: jest.fn(),
15
- dispatchEvent: jest.fn(),
16
- };
17
- }),
18
- });
7
+ baseMockMatchMedia(jest);
19
8
  }
20
9
 
21
10
  export function mockResizeObserver() {
22
11
  // mock ResizeObserver because it's not implemented in jsdoc lib
23
12
  // https://github.com/jsdom/jsdom/issues/3368
24
- // eslint-disable-next-line compat/compat
25
- window.ResizeObserver = class ResizeObserver {
26
- observe = jest.fn();
27
- unobserve = jest.fn();
28
- disconnect = jest.fn();
29
- };
13
+ baseMockResizeObserver(jest);
30
14
  }
@@ -14,12 +14,8 @@ describe('withNextPortal', () => {
14
14
  ReactDOM.createPortal.mockImplementation(() => null);
15
15
  const props = {};
16
16
  const Component = withNextPortal(AnyComponent);
17
- const expected = mount(<AnyComponent {...props} />);
18
17
  mount(<Component {...props} />);
19
18
  expect(ReactDOM.createPortal).toHaveBeenCalledTimes(1);
20
- const [comp, body] = ReactDOM.createPortal.mock.calls[0];
21
- expect(comp).toMatchObject(expected);
22
- expect(body).toMatchObject(document.body);
23
19
  });
24
20
 
25
21
  const AnyComponent = () => <div>Test div</div>;