@oanda/labs-widget-common 1.0.200 → 1.0.202
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/CHANGELOG.md +1588 -0
- package/dist/main/providers/Layout/LayoutProvider.test.js +181 -0
- package/dist/main/providers/Layout/LayoutProvider.test.js.map +1 -0
- package/dist/module/providers/Layout/LayoutProvider.test.js +178 -0
- package/dist/module/providers/Layout/LayoutProvider.test.js.map +1 -0
- package/dist/types/providers/Layout/LayoutProvider.test.d.ts +1 -0
- package/package.json +2 -2
- package/src/providers/Layout/LayoutProvider.test.tsx +191 -0
- package/test/components/SwitchItem.test.tsx +239 -0
- package/test/utils/useNumberFormat.test.tsx +127 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _react = require("@testing-library/react");
|
|
4
|
+
var _react2 = _interopRequireDefault(require("react"));
|
|
5
|
+
var _constants = require("../../constants");
|
|
6
|
+
var _types = require("../../types");
|
|
7
|
+
var _LayoutContext = require("./LayoutContext");
|
|
8
|
+
var _LayoutProvider = require("./LayoutProvider");
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
let mockResizeCallback = () => {};
|
|
11
|
+
const mockUseResizeObserver = jest.fn(_ref => {
|
|
12
|
+
let {
|
|
13
|
+
onResize
|
|
14
|
+
} = _ref;
|
|
15
|
+
mockResizeCallback = onResize;
|
|
16
|
+
});
|
|
17
|
+
const mockUseDebounceCallback = jest.fn(callback => callback);
|
|
18
|
+
jest.mock('usehooks-ts', () => ({
|
|
19
|
+
useResizeObserver: props => mockUseResizeObserver(props),
|
|
20
|
+
useDebounceCallback: (callback, _delay, _options) => mockUseDebounceCallback(callback)
|
|
21
|
+
}));
|
|
22
|
+
const TestConsumerComponent = () => {
|
|
23
|
+
const context = _react2.default.useContext(_LayoutContext.LayoutContext);
|
|
24
|
+
if (!context) return null;
|
|
25
|
+
return _react2.default.createElement("div", null, _react2.default.createElement("span", {
|
|
26
|
+
"data-testid": "size"
|
|
27
|
+
}, context.size), _react2.default.createElement("span", {
|
|
28
|
+
"data-testid": "isDark"
|
|
29
|
+
}, context.isDark.toString()), _react2.default.createElement("span", {
|
|
30
|
+
"data-testid": "theme"
|
|
31
|
+
}, context.theme));
|
|
32
|
+
};
|
|
33
|
+
const renderLayoutProvider = props => {
|
|
34
|
+
return (0, _react.render)(_react2.default.createElement(_LayoutProvider.LayoutProvider, props, _react2.default.createElement(TestConsumerComponent, null)));
|
|
35
|
+
};
|
|
36
|
+
describe('LayoutProvider', () => {
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
jest.clearAllMocks();
|
|
39
|
+
mockResizeCallback = () => {};
|
|
40
|
+
});
|
|
41
|
+
it('renders children and provides default context values', () => {
|
|
42
|
+
renderLayoutProvider();
|
|
43
|
+
expect(_react.screen.getByTestId('layout-provider')).toBeInTheDocument();
|
|
44
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent('');
|
|
45
|
+
expect(_react.screen.getByTestId('isDark')).toHaveTextContent('false');
|
|
46
|
+
expect(_react.screen.getByTestId('theme')).toHaveTextContent(_types.Theme.Light);
|
|
47
|
+
expect(_react.screen.getByTestId('layout-provider')).toHaveClass('lw-p-[0.125rem]');
|
|
48
|
+
expect(_react.screen.getByTestId('layout-provider')).not.toHaveClass('lw-w-fit');
|
|
49
|
+
expect(_react.screen.getByTestId('layout-provider')).toHaveStyle('colorScheme: light');
|
|
50
|
+
});
|
|
51
|
+
it('provides dark theme context values when theme is Dark', () => {
|
|
52
|
+
renderLayoutProvider({
|
|
53
|
+
theme: _types.Theme.Dark
|
|
54
|
+
});
|
|
55
|
+
expect(_react.screen.getByTestId('isDark')).toHaveTextContent('true');
|
|
56
|
+
expect(_react.screen.getByTestId('theme')).toHaveTextContent(_types.Theme.Dark);
|
|
57
|
+
expect(_react.screen.getByTestId('layout-provider')).toHaveStyle('colorScheme: dark');
|
|
58
|
+
});
|
|
59
|
+
it('provides fixedSize when specified and does not listen to resize', () => {
|
|
60
|
+
renderLayoutProvider({
|
|
61
|
+
size: _types.Size.TABLET
|
|
62
|
+
});
|
|
63
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.TABLET);
|
|
64
|
+
(0, _react.act)(() => {
|
|
65
|
+
mockResizeCallback({
|
|
66
|
+
width: _constants.MOBILE_MAX_WIDTH - 100
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.TABLET);
|
|
70
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1);
|
|
71
|
+
});
|
|
72
|
+
it('applies lw-w-fit class when shouldFitContent is true', () => {
|
|
73
|
+
renderLayoutProvider({
|
|
74
|
+
shouldFitContent: true
|
|
75
|
+
});
|
|
76
|
+
expect(_react.screen.getByTestId('layout-provider')).toHaveClass('lw-w-fit');
|
|
77
|
+
});
|
|
78
|
+
it('removes padding when shouldRemovePadding is true and size is set', () => {
|
|
79
|
+
renderLayoutProvider({
|
|
80
|
+
shouldRemovePadding: true
|
|
81
|
+
});
|
|
82
|
+
(0, _react.act)(() => {
|
|
83
|
+
mockResizeCallback({
|
|
84
|
+
width: _constants.MOBILE_MAX_WIDTH
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
expect(_react.screen.getByTestId('layout-provider')).not.toHaveClass('lw-p-[0.125rem]');
|
|
88
|
+
});
|
|
89
|
+
it('does not apply padding if size is null, even if shouldRemovePadding is false', () => {
|
|
90
|
+
renderLayoutProvider({
|
|
91
|
+
shouldRemovePadding: false
|
|
92
|
+
});
|
|
93
|
+
expect(_react.screen.getByTestId('layout-provider')).not.toHaveClass('lw-p-[0.125rem]');
|
|
94
|
+
});
|
|
95
|
+
it('applies padding when size is set and shouldRemovePadding is false', () => {
|
|
96
|
+
renderLayoutProvider({
|
|
97
|
+
shouldRemovePadding: false
|
|
98
|
+
});
|
|
99
|
+
(0, _react.act)(() => {
|
|
100
|
+
mockResizeCallback({
|
|
101
|
+
width: _constants.MOBILE_MAX_WIDTH
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
expect(_react.screen.getByTestId('layout-provider')).toHaveClass('lw-p-[0.125rem]');
|
|
105
|
+
});
|
|
106
|
+
describe('onResize behavior', () => {
|
|
107
|
+
it('sets size to MOBILE when width is less than or equal to MOBILE_MAX_WIDTH', () => {
|
|
108
|
+
renderLayoutProvider();
|
|
109
|
+
(0, _react.act)(() => {
|
|
110
|
+
mockResizeCallback({
|
|
111
|
+
width: _constants.MOBILE_MAX_WIDTH
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.MOBILE);
|
|
115
|
+
(0, _react.act)(() => {
|
|
116
|
+
mockResizeCallback({
|
|
117
|
+
width: _constants.MOBILE_MAX_WIDTH - 100
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.MOBILE);
|
|
121
|
+
});
|
|
122
|
+
it('sets size to TABLET when width is between MOBILE_MAX_WIDTH and DESKTOP_MIN_WIDTH', () => {
|
|
123
|
+
renderLayoutProvider();
|
|
124
|
+
(0, _react.act)(() => {
|
|
125
|
+
mockResizeCallback({
|
|
126
|
+
width: _constants.MOBILE_MAX_WIDTH + 1
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.TABLET);
|
|
130
|
+
(0, _react.act)(() => {
|
|
131
|
+
mockResizeCallback({
|
|
132
|
+
width: _constants.DESKTOP_MIN_WIDTH - 1
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.TABLET);
|
|
136
|
+
});
|
|
137
|
+
it('sets size to DESKTOP when width is greater than or equal to DESKTOP_MIN_WIDTH', () => {
|
|
138
|
+
renderLayoutProvider();
|
|
139
|
+
(0, _react.act)(() => {
|
|
140
|
+
mockResizeCallback({
|
|
141
|
+
width: _constants.DESKTOP_MIN_WIDTH
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.DESKTOP);
|
|
145
|
+
(0, _react.act)(() => {
|
|
146
|
+
mockResizeCallback({
|
|
147
|
+
width: _constants.DESKTOP_MIN_WIDTH + 100
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.DESKTOP);
|
|
151
|
+
});
|
|
152
|
+
it('does not update size on resize if fixedSize is provided', () => {
|
|
153
|
+
renderLayoutProvider({
|
|
154
|
+
size: _types.Size.DESKTOP
|
|
155
|
+
});
|
|
156
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.DESKTOP);
|
|
157
|
+
(0, _react.act)(() => {
|
|
158
|
+
mockResizeCallback({
|
|
159
|
+
width: _constants.MOBILE_MAX_WIDTH - 100
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
expect(_react.screen.getByTestId('size')).toHaveTextContent(_types.Size.DESKTOP);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
it('uses debounced callback for onResize', () => {
|
|
166
|
+
renderLayoutProvider();
|
|
167
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1);
|
|
168
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledWith(expect.any(Function), 50, {
|
|
169
|
+
leading: true
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
it('calls useResizeObserver with ref and onResize', () => {
|
|
173
|
+
renderLayoutProvider();
|
|
174
|
+
expect(mockUseResizeObserver).toHaveBeenCalledTimes(1);
|
|
175
|
+
expect(mockUseResizeObserver).toHaveBeenCalledWith({
|
|
176
|
+
ref: expect.any(Object),
|
|
177
|
+
onResize: expect.any(Function)
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
//# sourceMappingURL=LayoutProvider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutProvider.test.js","names":["_react","require","_react2","_interopRequireDefault","_constants","_types","_LayoutContext","_LayoutProvider","e","__esModule","default","mockResizeCallback","mockUseResizeObserver","jest","fn","_ref","onResize","mockUseDebounceCallback","callback","mock","useResizeObserver","props","useDebounceCallback","_delay","_options","TestConsumerComponent","context","React","useContext","LayoutContext","createElement","size","isDark","toString","theme","renderLayoutProvider","render","LayoutProvider","describe","beforeEach","clearAllMocks","it","expect","screen","getByTestId","toBeInTheDocument","toHaveTextContent","Theme","Light","toHaveClass","not","toHaveStyle","Dark","Size","TABLET","act","width","MOBILE_MAX_WIDTH","toHaveBeenCalledTimes","shouldFitContent","shouldRemovePadding","MOBILE","DESKTOP_MIN_WIDTH","DESKTOP","toHaveBeenCalledWith","any","Function","leading","ref","Object"],"sources":["../../../../src/providers/Layout/LayoutProvider.test.tsx"],"sourcesContent":["import { act, render, screen } from '@testing-library/react';\nimport React from 'react';\n\nimport { DESKTOP_MIN_WIDTH, MOBILE_MAX_WIDTH } from '../../constants';\nimport { Size, Theme } from '../../types';\nimport { LayoutContext } from './LayoutContext';\nimport type { LayoutWrapperProps } from './LayoutProvider';\nimport { LayoutProvider } from './LayoutProvider';\n\n// Mock usehooks-ts\nlet mockResizeCallback: (entry: { width: number }) => void = () => {};\nconst mockUseResizeObserver = jest.fn(({ onResize }) => {\n mockResizeCallback = onResize;\n});\nconst mockUseDebounceCallback = jest.fn((callback) => callback);\n\njest.mock('usehooks-ts', () => ({\n useResizeObserver: (props: any) => mockUseResizeObserver(props),\n useDebounceCallback: (callback: any, _delay: any, _options: any) =>\n mockUseDebounceCallback(callback),\n}));\n\nconst TestConsumerComponent = () => {\n const context = React.useContext(LayoutContext);\n if (!context) return null;\n return (\n <div>\n <span data-testid=\"size\">{context.size}</span>\n <span data-testid=\"isDark\">{context.isDark.toString()}</span>\n <span data-testid=\"theme\">{context.theme}</span>\n </div>\n );\n};\n\nconst renderLayoutProvider = (props?: Partial<LayoutWrapperProps>) => {\n return render(\n <LayoutProvider {...props}>\n <TestConsumerComponent />\n </LayoutProvider>\n );\n};\n\ndescribe('LayoutProvider', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n // Reset mockResizeCallback to a no-op function before each test\n mockResizeCallback = () => {};\n });\n\n it('renders children and provides default context values', () => {\n renderLayoutProvider();\n expect(screen.getByTestId('layout-provider')).toBeInTheDocument();\n expect(screen.getByTestId('size')).toHaveTextContent(''); // Initially null\n expect(screen.getByTestId('isDark')).toHaveTextContent('false');\n expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Light);\n expect(screen.getByTestId('layout-provider')).toHaveClass(\n 'lw-p-[0.125rem]'\n ); // Padding by default when size is set\n expect(screen.getByTestId('layout-provider')).not.toHaveClass('lw-w-fit');\n expect(screen.getByTestId('layout-provider')).toHaveStyle(\n 'colorScheme: light'\n );\n });\n\n it('provides dark theme context values when theme is Dark', () => {\n renderLayoutProvider({ theme: Theme.Dark });\n expect(screen.getByTestId('isDark')).toHaveTextContent('true');\n expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Dark);\n expect(screen.getByTestId('layout-provider')).toHaveStyle(\n 'colorScheme: dark'\n );\n });\n\n it('provides fixedSize when specified and does not listen to resize', () => {\n renderLayoutProvider({ size: Size.TABLET });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n\n // Simulate resize\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });\n });\n // Size should remain fixed\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1); // onResize is debounced\n });\n\n it('applies lw-w-fit class when shouldFitContent is true', () => {\n renderLayoutProvider({ shouldFitContent: true });\n expect(screen.getByTestId('layout-provider')).toHaveClass('lw-w-fit');\n });\n\n it('removes padding when shouldRemovePadding is true and size is set', () => {\n renderLayoutProvider({ shouldRemovePadding: true });\n // Simulate resize to set a size, which would normally add padding\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH });\n });\n expect(screen.getByTestId('layout-provider')).not.toHaveClass(\n 'lw-p-[0.125rem]'\n );\n });\n\n it('does not apply padding if size is null, even if shouldRemovePadding is false', () => {\n renderLayoutProvider({ shouldRemovePadding: false });\n // Size is initially null, so no padding class should be applied yet\n expect(screen.getByTestId('layout-provider')).not.toHaveClass(\n 'lw-p-[0.125rem]'\n );\n });\n\n it('applies padding when size is set and shouldRemovePadding is false', () => {\n renderLayoutProvider({ shouldRemovePadding: false });\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH }); // This will set size to MOBILE\n });\n expect(screen.getByTestId('layout-provider')).toHaveClass(\n 'lw-p-[0.125rem]'\n );\n });\n\n describe('onResize behavior', () => {\n it('sets size to MOBILE when width is less than or equal to MOBILE_MAX_WIDTH', () => {\n renderLayoutProvider();\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);\n\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);\n });\n\n it('sets size to TABLET when width is between MOBILE_MAX_WIDTH and DESKTOP_MIN_WIDTH', () => {\n renderLayoutProvider();\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH + 1 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n\n act(() => {\n mockResizeCallback({ width: DESKTOP_MIN_WIDTH - 1 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n });\n\n it('sets size to DESKTOP when width is greater than or equal to DESKTOP_MIN_WIDTH', () => {\n renderLayoutProvider();\n act(() => {\n mockResizeCallback({ width: DESKTOP_MIN_WIDTH });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n\n act(() => {\n mockResizeCallback({ width: DESKTOP_MIN_WIDTH + 100 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n });\n\n it('does not update size on resize if fixedSize is provided', () => {\n renderLayoutProvider({ size: Size.DESKTOP });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });\n });\n // Size should remain fixed\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n });\n });\n\n it('uses debounced callback for onResize', () => {\n renderLayoutProvider();\n expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1);\n expect(mockUseDebounceCallback).toHaveBeenCalledWith(\n expect.any(Function),\n 50,\n { leading: true }\n );\n });\n\n it('calls useResizeObserver with ref and onResize', () => {\n renderLayoutProvider();\n expect(mockUseResizeObserver).toHaveBeenCalledTimes(1);\n expect(mockUseResizeObserver).toHaveBeenCalledWith({\n ref: expect.any(Object), // React.RefObject\n onResize: expect.any(Function), // The debounced callback\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { act, render, screen } from '@testing-library/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { DESKTOP_MIN_WIDTH, MOBILE_MAX_WIDTH } from '../../constants';
|
|
4
|
+
import { Size, Theme } from '../../types';
|
|
5
|
+
import { LayoutContext } from './LayoutContext';
|
|
6
|
+
import { LayoutProvider } from './LayoutProvider';
|
|
7
|
+
let mockResizeCallback = () => {};
|
|
8
|
+
const mockUseResizeObserver = jest.fn(_ref => {
|
|
9
|
+
let {
|
|
10
|
+
onResize
|
|
11
|
+
} = _ref;
|
|
12
|
+
mockResizeCallback = onResize;
|
|
13
|
+
});
|
|
14
|
+
const mockUseDebounceCallback = jest.fn(callback => callback);
|
|
15
|
+
jest.mock('usehooks-ts', () => ({
|
|
16
|
+
useResizeObserver: props => mockUseResizeObserver(props),
|
|
17
|
+
useDebounceCallback: (callback, _delay, _options) => mockUseDebounceCallback(callback)
|
|
18
|
+
}));
|
|
19
|
+
const TestConsumerComponent = () => {
|
|
20
|
+
const context = React.useContext(LayoutContext);
|
|
21
|
+
if (!context) return null;
|
|
22
|
+
return React.createElement("div", null, React.createElement("span", {
|
|
23
|
+
"data-testid": "size"
|
|
24
|
+
}, context.size), React.createElement("span", {
|
|
25
|
+
"data-testid": "isDark"
|
|
26
|
+
}, context.isDark.toString()), React.createElement("span", {
|
|
27
|
+
"data-testid": "theme"
|
|
28
|
+
}, context.theme));
|
|
29
|
+
};
|
|
30
|
+
const renderLayoutProvider = props => {
|
|
31
|
+
return render(React.createElement(LayoutProvider, props, React.createElement(TestConsumerComponent, null)));
|
|
32
|
+
};
|
|
33
|
+
describe('LayoutProvider', () => {
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
jest.clearAllMocks();
|
|
36
|
+
mockResizeCallback = () => {};
|
|
37
|
+
});
|
|
38
|
+
it('renders children and provides default context values', () => {
|
|
39
|
+
renderLayoutProvider();
|
|
40
|
+
expect(screen.getByTestId('layout-provider')).toBeInTheDocument();
|
|
41
|
+
expect(screen.getByTestId('size')).toHaveTextContent('');
|
|
42
|
+
expect(screen.getByTestId('isDark')).toHaveTextContent('false');
|
|
43
|
+
expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Light);
|
|
44
|
+
expect(screen.getByTestId('layout-provider')).toHaveClass('lw-p-[0.125rem]');
|
|
45
|
+
expect(screen.getByTestId('layout-provider')).not.toHaveClass('lw-w-fit');
|
|
46
|
+
expect(screen.getByTestId('layout-provider')).toHaveStyle('colorScheme: light');
|
|
47
|
+
});
|
|
48
|
+
it('provides dark theme context values when theme is Dark', () => {
|
|
49
|
+
renderLayoutProvider({
|
|
50
|
+
theme: Theme.Dark
|
|
51
|
+
});
|
|
52
|
+
expect(screen.getByTestId('isDark')).toHaveTextContent('true');
|
|
53
|
+
expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Dark);
|
|
54
|
+
expect(screen.getByTestId('layout-provider')).toHaveStyle('colorScheme: dark');
|
|
55
|
+
});
|
|
56
|
+
it('provides fixedSize when specified and does not listen to resize', () => {
|
|
57
|
+
renderLayoutProvider({
|
|
58
|
+
size: Size.TABLET
|
|
59
|
+
});
|
|
60
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
61
|
+
act(() => {
|
|
62
|
+
mockResizeCallback({
|
|
63
|
+
width: MOBILE_MAX_WIDTH - 100
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
67
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1);
|
|
68
|
+
});
|
|
69
|
+
it('applies lw-w-fit class when shouldFitContent is true', () => {
|
|
70
|
+
renderLayoutProvider({
|
|
71
|
+
shouldFitContent: true
|
|
72
|
+
});
|
|
73
|
+
expect(screen.getByTestId('layout-provider')).toHaveClass('lw-w-fit');
|
|
74
|
+
});
|
|
75
|
+
it('removes padding when shouldRemovePadding is true and size is set', () => {
|
|
76
|
+
renderLayoutProvider({
|
|
77
|
+
shouldRemovePadding: true
|
|
78
|
+
});
|
|
79
|
+
act(() => {
|
|
80
|
+
mockResizeCallback({
|
|
81
|
+
width: MOBILE_MAX_WIDTH
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
expect(screen.getByTestId('layout-provider')).not.toHaveClass('lw-p-[0.125rem]');
|
|
85
|
+
});
|
|
86
|
+
it('does not apply padding if size is null, even if shouldRemovePadding is false', () => {
|
|
87
|
+
renderLayoutProvider({
|
|
88
|
+
shouldRemovePadding: false
|
|
89
|
+
});
|
|
90
|
+
expect(screen.getByTestId('layout-provider')).not.toHaveClass('lw-p-[0.125rem]');
|
|
91
|
+
});
|
|
92
|
+
it('applies padding when size is set and shouldRemovePadding is false', () => {
|
|
93
|
+
renderLayoutProvider({
|
|
94
|
+
shouldRemovePadding: false
|
|
95
|
+
});
|
|
96
|
+
act(() => {
|
|
97
|
+
mockResizeCallback({
|
|
98
|
+
width: MOBILE_MAX_WIDTH
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
expect(screen.getByTestId('layout-provider')).toHaveClass('lw-p-[0.125rem]');
|
|
102
|
+
});
|
|
103
|
+
describe('onResize behavior', () => {
|
|
104
|
+
it('sets size to MOBILE when width is less than or equal to MOBILE_MAX_WIDTH', () => {
|
|
105
|
+
renderLayoutProvider();
|
|
106
|
+
act(() => {
|
|
107
|
+
mockResizeCallback({
|
|
108
|
+
width: MOBILE_MAX_WIDTH
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);
|
|
112
|
+
act(() => {
|
|
113
|
+
mockResizeCallback({
|
|
114
|
+
width: MOBILE_MAX_WIDTH - 100
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);
|
|
118
|
+
});
|
|
119
|
+
it('sets size to TABLET when width is between MOBILE_MAX_WIDTH and DESKTOP_MIN_WIDTH', () => {
|
|
120
|
+
renderLayoutProvider();
|
|
121
|
+
act(() => {
|
|
122
|
+
mockResizeCallback({
|
|
123
|
+
width: MOBILE_MAX_WIDTH + 1
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
127
|
+
act(() => {
|
|
128
|
+
mockResizeCallback({
|
|
129
|
+
width: DESKTOP_MIN_WIDTH - 1
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
133
|
+
});
|
|
134
|
+
it('sets size to DESKTOP when width is greater than or equal to DESKTOP_MIN_WIDTH', () => {
|
|
135
|
+
renderLayoutProvider();
|
|
136
|
+
act(() => {
|
|
137
|
+
mockResizeCallback({
|
|
138
|
+
width: DESKTOP_MIN_WIDTH
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
142
|
+
act(() => {
|
|
143
|
+
mockResizeCallback({
|
|
144
|
+
width: DESKTOP_MIN_WIDTH + 100
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
148
|
+
});
|
|
149
|
+
it('does not update size on resize if fixedSize is provided', () => {
|
|
150
|
+
renderLayoutProvider({
|
|
151
|
+
size: Size.DESKTOP
|
|
152
|
+
});
|
|
153
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
154
|
+
act(() => {
|
|
155
|
+
mockResizeCallback({
|
|
156
|
+
width: MOBILE_MAX_WIDTH - 100
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
it('uses debounced callback for onResize', () => {
|
|
163
|
+
renderLayoutProvider();
|
|
164
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1);
|
|
165
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledWith(expect.any(Function), 50, {
|
|
166
|
+
leading: true
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
it('calls useResizeObserver with ref and onResize', () => {
|
|
170
|
+
renderLayoutProvider();
|
|
171
|
+
expect(mockUseResizeObserver).toHaveBeenCalledTimes(1);
|
|
172
|
+
expect(mockUseResizeObserver).toHaveBeenCalledWith({
|
|
173
|
+
ref: expect.any(Object),
|
|
174
|
+
onResize: expect.any(Function)
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
//# sourceMappingURL=LayoutProvider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayoutProvider.test.js","names":["act","render","screen","React","DESKTOP_MIN_WIDTH","MOBILE_MAX_WIDTH","Size","Theme","LayoutContext","LayoutProvider","mockResizeCallback","mockUseResizeObserver","jest","fn","_ref","onResize","mockUseDebounceCallback","callback","mock","useResizeObserver","props","useDebounceCallback","_delay","_options","TestConsumerComponent","context","useContext","createElement","size","isDark","toString","theme","renderLayoutProvider","describe","beforeEach","clearAllMocks","it","expect","getByTestId","toBeInTheDocument","toHaveTextContent","Light","toHaveClass","not","toHaveStyle","Dark","TABLET","width","toHaveBeenCalledTimes","shouldFitContent","shouldRemovePadding","MOBILE","DESKTOP","toHaveBeenCalledWith","any","Function","leading","ref","Object"],"sources":["../../../../src/providers/Layout/LayoutProvider.test.tsx"],"sourcesContent":["import { act, render, screen } from '@testing-library/react';\nimport React from 'react';\n\nimport { DESKTOP_MIN_WIDTH, MOBILE_MAX_WIDTH } from '../../constants';\nimport { Size, Theme } from '../../types';\nimport { LayoutContext } from './LayoutContext';\nimport type { LayoutWrapperProps } from './LayoutProvider';\nimport { LayoutProvider } from './LayoutProvider';\n\n// Mock usehooks-ts\nlet mockResizeCallback: (entry: { width: number }) => void = () => {};\nconst mockUseResizeObserver = jest.fn(({ onResize }) => {\n mockResizeCallback = onResize;\n});\nconst mockUseDebounceCallback = jest.fn((callback) => callback);\n\njest.mock('usehooks-ts', () => ({\n useResizeObserver: (props: any) => mockUseResizeObserver(props),\n useDebounceCallback: (callback: any, _delay: any, _options: any) =>\n mockUseDebounceCallback(callback),\n}));\n\nconst TestConsumerComponent = () => {\n const context = React.useContext(LayoutContext);\n if (!context) return null;\n return (\n <div>\n <span data-testid=\"size\">{context.size}</span>\n <span data-testid=\"isDark\">{context.isDark.toString()}</span>\n <span data-testid=\"theme\">{context.theme}</span>\n </div>\n );\n};\n\nconst renderLayoutProvider = (props?: Partial<LayoutWrapperProps>) => {\n return render(\n <LayoutProvider {...props}>\n <TestConsumerComponent />\n </LayoutProvider>\n );\n};\n\ndescribe('LayoutProvider', () => {\n beforeEach(() => {\n jest.clearAllMocks();\n // Reset mockResizeCallback to a no-op function before each test\n mockResizeCallback = () => {};\n });\n\n it('renders children and provides default context values', () => {\n renderLayoutProvider();\n expect(screen.getByTestId('layout-provider')).toBeInTheDocument();\n expect(screen.getByTestId('size')).toHaveTextContent(''); // Initially null\n expect(screen.getByTestId('isDark')).toHaveTextContent('false');\n expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Light);\n expect(screen.getByTestId('layout-provider')).toHaveClass(\n 'lw-p-[0.125rem]'\n ); // Padding by default when size is set\n expect(screen.getByTestId('layout-provider')).not.toHaveClass('lw-w-fit');\n expect(screen.getByTestId('layout-provider')).toHaveStyle(\n 'colorScheme: light'\n );\n });\n\n it('provides dark theme context values when theme is Dark', () => {\n renderLayoutProvider({ theme: Theme.Dark });\n expect(screen.getByTestId('isDark')).toHaveTextContent('true');\n expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Dark);\n expect(screen.getByTestId('layout-provider')).toHaveStyle(\n 'colorScheme: dark'\n );\n });\n\n it('provides fixedSize when specified and does not listen to resize', () => {\n renderLayoutProvider({ size: Size.TABLET });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n\n // Simulate resize\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });\n });\n // Size should remain fixed\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1); // onResize is debounced\n });\n\n it('applies lw-w-fit class when shouldFitContent is true', () => {\n renderLayoutProvider({ shouldFitContent: true });\n expect(screen.getByTestId('layout-provider')).toHaveClass('lw-w-fit');\n });\n\n it('removes padding when shouldRemovePadding is true and size is set', () => {\n renderLayoutProvider({ shouldRemovePadding: true });\n // Simulate resize to set a size, which would normally add padding\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH });\n });\n expect(screen.getByTestId('layout-provider')).not.toHaveClass(\n 'lw-p-[0.125rem]'\n );\n });\n\n it('does not apply padding if size is null, even if shouldRemovePadding is false', () => {\n renderLayoutProvider({ shouldRemovePadding: false });\n // Size is initially null, so no padding class should be applied yet\n expect(screen.getByTestId('layout-provider')).not.toHaveClass(\n 'lw-p-[0.125rem]'\n );\n });\n\n it('applies padding when size is set and shouldRemovePadding is false', () => {\n renderLayoutProvider({ shouldRemovePadding: false });\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH }); // This will set size to MOBILE\n });\n expect(screen.getByTestId('layout-provider')).toHaveClass(\n 'lw-p-[0.125rem]'\n );\n });\n\n describe('onResize behavior', () => {\n it('sets size to MOBILE when width is less than or equal to MOBILE_MAX_WIDTH', () => {\n renderLayoutProvider();\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);\n\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);\n });\n\n it('sets size to TABLET when width is between MOBILE_MAX_WIDTH and DESKTOP_MIN_WIDTH', () => {\n renderLayoutProvider();\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH + 1 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n\n act(() => {\n mockResizeCallback({ width: DESKTOP_MIN_WIDTH - 1 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);\n });\n\n it('sets size to DESKTOP when width is greater than or equal to DESKTOP_MIN_WIDTH', () => {\n renderLayoutProvider();\n act(() => {\n mockResizeCallback({ width: DESKTOP_MIN_WIDTH });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n\n act(() => {\n mockResizeCallback({ width: DESKTOP_MIN_WIDTH + 100 });\n });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n });\n\n it('does not update size on resize if fixedSize is provided', () => {\n renderLayoutProvider({ size: Size.DESKTOP });\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n\n act(() => {\n mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });\n });\n // Size should remain fixed\n expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);\n });\n });\n\n it('uses debounced callback for onResize', () => {\n renderLayoutProvider();\n expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1);\n expect(mockUseDebounceCallback).toHaveBeenCalledWith(\n expect.any(Function),\n 50,\n { leading: true }\n );\n });\n\n it('calls useResizeObserver with ref and onResize', () => {\n renderLayoutProvider();\n expect(mockUseResizeObserver).toHaveBeenCalledTimes(1);\n expect(mockUseResizeObserver).toHaveBeenCalledWith({\n ref: expect.any(Object), // React.RefObject\n onResize: expect.any(Function), // The debounced callback\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oanda/labs-widget-common",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.202",
|
|
4
4
|
"description": "Labs Widget Common",
|
|
5
5
|
"main": "dist/main/index.js",
|
|
6
6
|
"module": "dist/module/index.js",
|
|
@@ -21,5 +21,5 @@
|
|
|
21
21
|
"tailwind-merge": "2.2.2",
|
|
22
22
|
"usehooks-ts": "3.0.2"
|
|
23
23
|
},
|
|
24
|
-
"gitHead": "
|
|
24
|
+
"gitHead": "396b55c37d320c82e75cc732f9b79328b43532de"
|
|
25
25
|
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { act, render, screen } from '@testing-library/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { DESKTOP_MIN_WIDTH, MOBILE_MAX_WIDTH } from '../../constants';
|
|
5
|
+
import { Size, Theme } from '../../types';
|
|
6
|
+
import { LayoutContext } from './LayoutContext';
|
|
7
|
+
import type { LayoutWrapperProps } from './LayoutProvider';
|
|
8
|
+
import { LayoutProvider } from './LayoutProvider';
|
|
9
|
+
|
|
10
|
+
// Mock usehooks-ts
|
|
11
|
+
let mockResizeCallback: (entry: { width: number }) => void = () => {};
|
|
12
|
+
const mockUseResizeObserver = jest.fn(({ onResize }) => {
|
|
13
|
+
mockResizeCallback = onResize;
|
|
14
|
+
});
|
|
15
|
+
const mockUseDebounceCallback = jest.fn((callback) => callback);
|
|
16
|
+
|
|
17
|
+
jest.mock('usehooks-ts', () => ({
|
|
18
|
+
useResizeObserver: (props: any) => mockUseResizeObserver(props),
|
|
19
|
+
useDebounceCallback: (callback: any, _delay: any, _options: any) =>
|
|
20
|
+
mockUseDebounceCallback(callback),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
const TestConsumerComponent = () => {
|
|
24
|
+
const context = React.useContext(LayoutContext);
|
|
25
|
+
if (!context) return null;
|
|
26
|
+
return (
|
|
27
|
+
<div>
|
|
28
|
+
<span data-testid="size">{context.size}</span>
|
|
29
|
+
<span data-testid="isDark">{context.isDark.toString()}</span>
|
|
30
|
+
<span data-testid="theme">{context.theme}</span>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const renderLayoutProvider = (props?: Partial<LayoutWrapperProps>) => {
|
|
36
|
+
return render(
|
|
37
|
+
<LayoutProvider {...props}>
|
|
38
|
+
<TestConsumerComponent />
|
|
39
|
+
</LayoutProvider>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
describe('LayoutProvider', () => {
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
jest.clearAllMocks();
|
|
46
|
+
// Reset mockResizeCallback to a no-op function before each test
|
|
47
|
+
mockResizeCallback = () => {};
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('renders children and provides default context values', () => {
|
|
51
|
+
renderLayoutProvider();
|
|
52
|
+
expect(screen.getByTestId('layout-provider')).toBeInTheDocument();
|
|
53
|
+
expect(screen.getByTestId('size')).toHaveTextContent(''); // Initially null
|
|
54
|
+
expect(screen.getByTestId('isDark')).toHaveTextContent('false');
|
|
55
|
+
expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Light);
|
|
56
|
+
expect(screen.getByTestId('layout-provider')).toHaveClass(
|
|
57
|
+
'lw-p-[0.125rem]'
|
|
58
|
+
); // Padding by default when size is set
|
|
59
|
+
expect(screen.getByTestId('layout-provider')).not.toHaveClass('lw-w-fit');
|
|
60
|
+
expect(screen.getByTestId('layout-provider')).toHaveStyle(
|
|
61
|
+
'colorScheme: light'
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('provides dark theme context values when theme is Dark', () => {
|
|
66
|
+
renderLayoutProvider({ theme: Theme.Dark });
|
|
67
|
+
expect(screen.getByTestId('isDark')).toHaveTextContent('true');
|
|
68
|
+
expect(screen.getByTestId('theme')).toHaveTextContent(Theme.Dark);
|
|
69
|
+
expect(screen.getByTestId('layout-provider')).toHaveStyle(
|
|
70
|
+
'colorScheme: dark'
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('provides fixedSize when specified and does not listen to resize', () => {
|
|
75
|
+
renderLayoutProvider({ size: Size.TABLET });
|
|
76
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
77
|
+
|
|
78
|
+
// Simulate resize
|
|
79
|
+
act(() => {
|
|
80
|
+
mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });
|
|
81
|
+
});
|
|
82
|
+
// Size should remain fixed
|
|
83
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
84
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1); // onResize is debounced
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('applies lw-w-fit class when shouldFitContent is true', () => {
|
|
88
|
+
renderLayoutProvider({ shouldFitContent: true });
|
|
89
|
+
expect(screen.getByTestId('layout-provider')).toHaveClass('lw-w-fit');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('removes padding when shouldRemovePadding is true and size is set', () => {
|
|
93
|
+
renderLayoutProvider({ shouldRemovePadding: true });
|
|
94
|
+
// Simulate resize to set a size, which would normally add padding
|
|
95
|
+
act(() => {
|
|
96
|
+
mockResizeCallback({ width: MOBILE_MAX_WIDTH });
|
|
97
|
+
});
|
|
98
|
+
expect(screen.getByTestId('layout-provider')).not.toHaveClass(
|
|
99
|
+
'lw-p-[0.125rem]'
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('does not apply padding if size is null, even if shouldRemovePadding is false', () => {
|
|
104
|
+
renderLayoutProvider({ shouldRemovePadding: false });
|
|
105
|
+
// Size is initially null, so no padding class should be applied yet
|
|
106
|
+
expect(screen.getByTestId('layout-provider')).not.toHaveClass(
|
|
107
|
+
'lw-p-[0.125rem]'
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('applies padding when size is set and shouldRemovePadding is false', () => {
|
|
112
|
+
renderLayoutProvider({ shouldRemovePadding: false });
|
|
113
|
+
act(() => {
|
|
114
|
+
mockResizeCallback({ width: MOBILE_MAX_WIDTH }); // This will set size to MOBILE
|
|
115
|
+
});
|
|
116
|
+
expect(screen.getByTestId('layout-provider')).toHaveClass(
|
|
117
|
+
'lw-p-[0.125rem]'
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('onResize behavior', () => {
|
|
122
|
+
it('sets size to MOBILE when width is less than or equal to MOBILE_MAX_WIDTH', () => {
|
|
123
|
+
renderLayoutProvider();
|
|
124
|
+
act(() => {
|
|
125
|
+
mockResizeCallback({ width: MOBILE_MAX_WIDTH });
|
|
126
|
+
});
|
|
127
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);
|
|
128
|
+
|
|
129
|
+
act(() => {
|
|
130
|
+
mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });
|
|
131
|
+
});
|
|
132
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.MOBILE);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('sets size to TABLET when width is between MOBILE_MAX_WIDTH and DESKTOP_MIN_WIDTH', () => {
|
|
136
|
+
renderLayoutProvider();
|
|
137
|
+
act(() => {
|
|
138
|
+
mockResizeCallback({ width: MOBILE_MAX_WIDTH + 1 });
|
|
139
|
+
});
|
|
140
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
141
|
+
|
|
142
|
+
act(() => {
|
|
143
|
+
mockResizeCallback({ width: DESKTOP_MIN_WIDTH - 1 });
|
|
144
|
+
});
|
|
145
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.TABLET);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('sets size to DESKTOP when width is greater than or equal to DESKTOP_MIN_WIDTH', () => {
|
|
149
|
+
renderLayoutProvider();
|
|
150
|
+
act(() => {
|
|
151
|
+
mockResizeCallback({ width: DESKTOP_MIN_WIDTH });
|
|
152
|
+
});
|
|
153
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
154
|
+
|
|
155
|
+
act(() => {
|
|
156
|
+
mockResizeCallback({ width: DESKTOP_MIN_WIDTH + 100 });
|
|
157
|
+
});
|
|
158
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('does not update size on resize if fixedSize is provided', () => {
|
|
162
|
+
renderLayoutProvider({ size: Size.DESKTOP });
|
|
163
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
164
|
+
|
|
165
|
+
act(() => {
|
|
166
|
+
mockResizeCallback({ width: MOBILE_MAX_WIDTH - 100 });
|
|
167
|
+
});
|
|
168
|
+
// Size should remain fixed
|
|
169
|
+
expect(screen.getByTestId('size')).toHaveTextContent(Size.DESKTOP);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('uses debounced callback for onResize', () => {
|
|
174
|
+
renderLayoutProvider();
|
|
175
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledTimes(1);
|
|
176
|
+
expect(mockUseDebounceCallback).toHaveBeenCalledWith(
|
|
177
|
+
expect.any(Function),
|
|
178
|
+
50,
|
|
179
|
+
{ leading: true }
|
|
180
|
+
);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('calls useResizeObserver with ref and onResize', () => {
|
|
184
|
+
renderLayoutProvider();
|
|
185
|
+
expect(mockUseResizeObserver).toHaveBeenCalledTimes(1);
|
|
186
|
+
expect(mockUseResizeObserver).toHaveBeenCalledWith({
|
|
187
|
+
ref: expect.any(Object), // React.RefObject
|
|
188
|
+
onResize: expect.any(Function), // The debounced callback
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
});
|