@pie-lib/test-utils 0.22.1 → 0.22.2-next.164

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.
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.createCustomElement = createCustomElement;
8
+ exports.dispatchCustomEvent = dispatchCustomEvent;
9
+ exports.isCustomElementDefined = isCustomElementDefined;
10
+ exports.renderWebComponent = renderWebComponent;
11
+ exports.waitForCustomElement = waitForCustomElement;
12
+ exports.waitForEvent = waitForEvent;
13
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
16
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
17
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
18
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
19
+ // Note: These helpers are for light DOM web components (no Shadow DOM)
20
+ // Standard React Testing Library queries work directly on these components
21
+ /**
22
+ * Wait for a custom element to be defined
23
+ * Custom elements are registered asynchronously
24
+ *
25
+ * @param {string} tagName - Custom element tag name (e.g., 'my-component')
26
+ * @param {number} timeout - Timeout in milliseconds
27
+ * @returns {Promise<void>}
28
+ *
29
+ * @example
30
+ * await waitForCustomElement('pie-chart');
31
+ * const chart = document.createElement('pie-chart');
32
+ *
33
+ * @example
34
+ * await waitForCustomElement('my-component', 5000);
35
+ */
36
+ function waitForCustomElement(_x) {
37
+ return _waitForCustomElement.apply(this, arguments);
38
+ }
39
+ /**
40
+ * Render a web component and wait for it to be ready
41
+ * Handles the full lifecycle: wait for definition, create, append, wait for render
42
+ *
43
+ * @param {string} tagName - Custom element tag name
44
+ * @param {Object} attributes - Attributes to set on the element
45
+ * @param {Object} properties - Properties to set on the element
46
+ * @param {HTMLElement} container - Container to append to (defaults to document.body)
47
+ * @returns {Promise<HTMLElement>} The custom element
48
+ *
49
+ * @example
50
+ * const chart = await renderWebComponent('pie-chart', {
51
+ * type: 'bar',
52
+ * 'data-testid': 'my-chart'
53
+ * });
54
+ *
55
+ * @example
56
+ * const button = await renderWebComponent('custom-button',
57
+ * { 'aria-label': 'Submit' },
58
+ * { onClick: jest.fn() }
59
+ * );
60
+ */
61
+ function _waitForCustomElement() {
62
+ _waitForCustomElement = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(tagName) {
63
+ var timeout,
64
+ _args = arguments;
65
+ return _regenerator["default"].wrap(function (_context) {
66
+ while (1) switch (_context.prev = _context.next) {
67
+ case 0:
68
+ timeout = _args.length > 1 && _args[1] !== undefined ? _args[1] : 3000;
69
+ if (!customElements.get(tagName)) {
70
+ _context.next = 1;
71
+ break;
72
+ }
73
+ return _context.abrupt("return");
74
+ case 1:
75
+ return _context.abrupt("return", new Promise(function (resolve, reject) {
76
+ var timer = setTimeout(function () {
77
+ reject(new Error("Custom element '".concat(tagName, "' not defined within ").concat(timeout, "ms. ") + 'Make sure the element is registered with customElements.define().'));
78
+ }, timeout);
79
+ customElements.whenDefined(tagName).then(function () {
80
+ clearTimeout(timer);
81
+ resolve();
82
+ });
83
+ }));
84
+ case 2:
85
+ case "end":
86
+ return _context.stop();
87
+ }
88
+ }, _callee);
89
+ }));
90
+ return _waitForCustomElement.apply(this, arguments);
91
+ }
92
+ function renderWebComponent(_x2) {
93
+ return _renderWebComponent.apply(this, arguments);
94
+ }
95
+ /**
96
+ * Dispatch a custom event on an element
97
+ * Web components often use custom events for communication
98
+ *
99
+ * @param {HTMLElement} element - Element to dispatch event from
100
+ * @param {string} eventName - Event name (e.g., 'change', 'custom-event')
101
+ * @param {*} detail - Event detail data
102
+ * @param {Object} options - Event options (bubbles, composed, etc.)
103
+ *
104
+ * @example
105
+ * dispatchCustomEvent(chart, 'data-changed', { value: [1, 2, 3] });
106
+ *
107
+ * @example
108
+ * dispatchCustomEvent(button, 'custom-click', null, { bubbles: false });
109
+ */
110
+ function _renderWebComponent() {
111
+ _renderWebComponent = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2(tagName) {
112
+ var attributes,
113
+ properties,
114
+ container,
115
+ element,
116
+ _args2 = arguments;
117
+ return _regenerator["default"].wrap(function (_context2) {
118
+ while (1) switch (_context2.prev = _context2.next) {
119
+ case 0:
120
+ attributes = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : {};
121
+ properties = _args2.length > 2 && _args2[2] !== undefined ? _args2[2] : {};
122
+ container = _args2.length > 3 && _args2[3] !== undefined ? _args2[3] : document.body;
123
+ _context2.next = 1;
124
+ return waitForCustomElement(tagName);
125
+ case 1:
126
+ element = document.createElement(tagName); // Set attributes (strings)
127
+ Object.entries(attributes).forEach(function (_ref3) {
128
+ var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
129
+ key = _ref4[0],
130
+ value = _ref4[1];
131
+ element.setAttribute(key, value);
132
+ });
133
+
134
+ // Set properties (objects, functions, etc.)
135
+ Object.entries(properties).forEach(function (_ref5) {
136
+ var _ref6 = (0, _slicedToArray2["default"])(_ref5, 2),
137
+ key = _ref6[0],
138
+ value = _ref6[1];
139
+ element[key] = value;
140
+ });
141
+ container.appendChild(element);
142
+
143
+ // Wait for component to render (custom elements may be async)
144
+ _context2.next = 2;
145
+ return new Promise(function (resolve) {
146
+ return setTimeout(resolve, 0);
147
+ });
148
+ case 2:
149
+ return _context2.abrupt("return", element);
150
+ case 3:
151
+ case "end":
152
+ return _context2.stop();
153
+ }
154
+ }, _callee2);
155
+ }));
156
+ return _renderWebComponent.apply(this, arguments);
157
+ }
158
+ function dispatchCustomEvent(element, eventName) {
159
+ var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
160
+ var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
161
+ var event = new CustomEvent(eventName, _objectSpread({
162
+ detail: detail,
163
+ bubbles: true,
164
+ composed: true
165
+ }, options));
166
+ element.dispatchEvent(event);
167
+ return event;
168
+ }
169
+
170
+ /**
171
+ * Listen for a custom event and return a promise that resolves when fired
172
+ * Useful for testing event emissions
173
+ *
174
+ * @param {HTMLElement} element - Element to listen to
175
+ * @param {string} eventName - Event name to wait for
176
+ * @param {number} timeout - Timeout in milliseconds
177
+ * @returns {Promise<CustomEvent>} Promise that resolves with the event
178
+ *
179
+ * @example
180
+ * const promise = waitForEvent(chart, 'data-loaded');
181
+ * chart.loadData();
182
+ * const event = await promise;
183
+ * expect(event.detail).toEqual({ loaded: true });
184
+ *
185
+ * @example
186
+ * await waitForEvent(component, 'ready', 5000);
187
+ */
188
+ function waitForEvent(element, eventName) {
189
+ var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 3000;
190
+ return new Promise(function (resolve, reject) {
191
+ var timer = setTimeout(function () {
192
+ element.removeEventListener(eventName, _handler);
193
+ reject(new Error("Event '".concat(eventName, "' not fired within ").concat(timeout, "ms")));
194
+ }, timeout);
195
+ var _handler = function handler(event) {
196
+ clearTimeout(timer);
197
+ element.removeEventListener(eventName, _handler);
198
+ resolve(event);
199
+ };
200
+ element.addEventListener(eventName, _handler);
201
+ });
202
+ }
203
+
204
+ /**
205
+ * Check if a custom element is defined
206
+ * Useful for verifying element registration
207
+ *
208
+ * @param {string} tagName - Custom element tag name
209
+ * @returns {boolean} True if element is defined
210
+ *
211
+ * @example
212
+ * if (isCustomElementDefined('pie-chart')) {
213
+ * // Element is ready to use
214
+ * }
215
+ */
216
+ function isCustomElementDefined(tagName) {
217
+ return typeof customElements !== 'undefined' && customElements.get(tagName) !== undefined;
218
+ }
219
+
220
+ /**
221
+ * Helper to create and configure a custom element
222
+ * For light DOM web components that render React
223
+ *
224
+ * @param {string} tagName - Custom element tag name
225
+ * @param {Object} props - Props to pass to the element
226
+ * @returns {HTMLElement} The custom element
227
+ *
228
+ * @example
229
+ * const chart = createCustomElement('pie-chart', {
230
+ * data: [1, 2, 3],
231
+ * type: 'bar'
232
+ * });
233
+ * document.body.appendChild(chart);
234
+ */
235
+ function createCustomElement(tagName) {
236
+ var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
237
+ var element = document.createElement(tagName);
238
+
239
+ // Set properties directly on the element
240
+ Object.entries(props).forEach(function (_ref) {
241
+ var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
242
+ key = _ref2[0],
243
+ value = _ref2[1];
244
+ element[key] = value;
245
+ });
246
+ return element;
247
+ }
248
+ //# sourceMappingURL=web-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-components.js","names":["waitForCustomElement","_x","_waitForCustomElement","apply","arguments","_asyncToGenerator2","_regenerator","mark","_callee","tagName","timeout","_args","wrap","_context","prev","next","length","undefined","customElements","get","abrupt","Promise","resolve","reject","timer","setTimeout","Error","concat","whenDefined","then","clearTimeout","stop","renderWebComponent","_x2","_renderWebComponent","_callee2","attributes","properties","container","element","_args2","_context2","document","body","createElement","Object","entries","forEach","_ref3","_ref4","_slicedToArray2","key","value","setAttribute","_ref5","_ref6","appendChild","dispatchCustomEvent","eventName","detail","options","event","CustomEvent","_objectSpread","bubbles","composed","dispatchEvent","waitForEvent","removeEventListener","handler","addEventListener","isCustomElementDefined","createCustomElement","props","_ref","_ref2"],"sources":["../src/web-components.js"],"sourcesContent":["// Note: These helpers are for light DOM web components (no Shadow DOM)\n// Standard React Testing Library queries work directly on these components\n\n/**\n * Wait for a custom element to be defined\n * Custom elements are registered asynchronously\n *\n * @param {string} tagName - Custom element tag name (e.g., 'my-component')\n * @param {number} timeout - Timeout in milliseconds\n * @returns {Promise<void>}\n *\n * @example\n * await waitForCustomElement('pie-chart');\n * const chart = document.createElement('pie-chart');\n *\n * @example\n * await waitForCustomElement('my-component', 5000);\n */\nexport async function waitForCustomElement(tagName, timeout = 3000) {\n if (customElements.get(tagName)) {\n return;\n }\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(\n new Error(\n `Custom element '${tagName}' not defined within ${timeout}ms. ` +\n 'Make sure the element is registered with customElements.define().'\n )\n );\n }, timeout);\n\n customElements.whenDefined(tagName).then(() => {\n clearTimeout(timer);\n resolve();\n });\n });\n}\n\n/**\n * Render a web component and wait for it to be ready\n * Handles the full lifecycle: wait for definition, create, append, wait for render\n *\n * @param {string} tagName - Custom element tag name\n * @param {Object} attributes - Attributes to set on the element\n * @param {Object} properties - Properties to set on the element\n * @param {HTMLElement} container - Container to append to (defaults to document.body)\n * @returns {Promise<HTMLElement>} The custom element\n *\n * @example\n * const chart = await renderWebComponent('pie-chart', {\n * type: 'bar',\n * 'data-testid': 'my-chart'\n * });\n *\n * @example\n * const button = await renderWebComponent('custom-button',\n * { 'aria-label': 'Submit' },\n * { onClick: jest.fn() }\n * );\n */\nexport async function renderWebComponent(\n tagName,\n attributes = {},\n properties = {},\n container = document.body\n) {\n await waitForCustomElement(tagName);\n\n const element = document.createElement(tagName);\n\n // Set attributes (strings)\n Object.entries(attributes).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n\n // Set properties (objects, functions, etc.)\n Object.entries(properties).forEach(([key, value]) => {\n element[key] = value;\n });\n\n container.appendChild(element);\n\n // Wait for component to render (custom elements may be async)\n await new Promise((resolve) => setTimeout(resolve, 0));\n\n return element;\n}\n\n/**\n * Dispatch a custom event on an element\n * Web components often use custom events for communication\n *\n * @param {HTMLElement} element - Element to dispatch event from\n * @param {string} eventName - Event name (e.g., 'change', 'custom-event')\n * @param {*} detail - Event detail data\n * @param {Object} options - Event options (bubbles, composed, etc.)\n *\n * @example\n * dispatchCustomEvent(chart, 'data-changed', { value: [1, 2, 3] });\n *\n * @example\n * dispatchCustomEvent(button, 'custom-click', null, { bubbles: false });\n */\nexport function dispatchCustomEvent(\n element,\n eventName,\n detail = null,\n options = {}\n) {\n const event = new CustomEvent(eventName, {\n detail,\n bubbles: true,\n composed: true, // Allow event to cross shadow DOM boundary\n ...options,\n });\n\n element.dispatchEvent(event);\n return event;\n}\n\n/**\n * Listen for a custom event and return a promise that resolves when fired\n * Useful for testing event emissions\n *\n * @param {HTMLElement} element - Element to listen to\n * @param {string} eventName - Event name to wait for\n * @param {number} timeout - Timeout in milliseconds\n * @returns {Promise<CustomEvent>} Promise that resolves with the event\n *\n * @example\n * const promise = waitForEvent(chart, 'data-loaded');\n * chart.loadData();\n * const event = await promise;\n * expect(event.detail).toEqual({ loaded: true });\n *\n * @example\n * await waitForEvent(component, 'ready', 5000);\n */\nexport function waitForEvent(element, eventName, timeout = 3000) {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n element.removeEventListener(eventName, handler);\n reject(\n new Error(`Event '${eventName}' not fired within ${timeout}ms`)\n );\n }, timeout);\n\n const handler = (event) => {\n clearTimeout(timer);\n element.removeEventListener(eventName, handler);\n resolve(event);\n };\n\n element.addEventListener(eventName, handler);\n });\n}\n\n/**\n * Check if a custom element is defined\n * Useful for verifying element registration\n *\n * @param {string} tagName - Custom element tag name\n * @returns {boolean} True if element is defined\n *\n * @example\n * if (isCustomElementDefined('pie-chart')) {\n * // Element is ready to use\n * }\n */\nexport function isCustomElementDefined(tagName) {\n return typeof customElements !== 'undefined' && customElements.get(tagName) !== undefined;\n}\n\n/**\n * Helper to create and configure a custom element\n * For light DOM web components that render React\n *\n * @param {string} tagName - Custom element tag name\n * @param {Object} props - Props to pass to the element\n * @returns {HTMLElement} The custom element\n *\n * @example\n * const chart = createCustomElement('pie-chart', {\n * data: [1, 2, 3],\n * type: 'bar'\n * });\n * document.body.appendChild(chart);\n */\nexport function createCustomElement(tagName, props = {}) {\n const element = document.createElement(tagName);\n\n // Set properties directly on the element\n Object.entries(props).forEach(([key, value]) => {\n element[key] = value;\n });\n\n return element;\n}\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pie-lib/test-utils",
3
- "version": "0.22.1",
4
- "description": "",
3
+ "version": "0.22.2-next.164+09821f09",
4
+ "description": "Testing utilities for pie-lib packages with React Testing Library and MUI support",
5
5
  "main": "lib/index.js",
6
6
  "module": "src/index.js",
7
7
  "publishConfig": {
@@ -10,9 +10,17 @@
10
10
  "author": "",
11
11
  "license": "ISC",
12
12
  "peerDependencies": {
13
- "enzyme": "^3.8.0",
14
- "react": "^16.8.1"
13
+ "@mui/material": "^7.3.4",
14
+ "@testing-library/react": "^16.3.0",
15
+ "react": "^18.2.0",
16
+ "react-dom": "^18.2.0"
15
17
  },
16
- "gitHead": "ce0ec7134200c51f3a3301257be3e707054b36ca",
18
+ "dependencies": {
19
+ "@emotion/react": "^11.14.0",
20
+ "@emotion/styled": "^11.11.0",
21
+ "@testing-library/jest-dom": "^5.16.5",
22
+ "@testing-library/user-event": "^14.5.2"
23
+ },
24
+ "gitHead": "09821f09cfcaee178971c57f4134645350be2222",
17
25
  "scripts": {}
18
26
  }
@@ -1,45 +1,92 @@
1
1
  import * as React from 'react';
2
- import { shallowChild } from '../index';
3
- import Enzyme from 'enzyme';
4
- import Adapter from 'enzyme-adapter-react-16';
5
-
6
- Enzyme.configure({ adapter: new Adapter() });
7
-
8
- describe('test-utils', () => {
9
- describe('shallowChild', () => {
10
- function simpleHoC(WrappedComponent) {
11
- return class extends React.Component {
12
- render() {
13
- return (
14
- <div>
15
- <WrappedComponent oneMoreProp="hello" {...this.props} />
16
- </div>
17
- );
18
- }
19
- };
20
- }
21
-
22
- class SimpleComponent extends React.Component {
23
- render() {
24
- return <span>My simple component will get wrapped</span>;
25
- }
26
- }
27
-
28
- it('moves past HoC and returns shallow rendered component using enzyme', () => {
29
- const wrapper = shallowChild(simpleHoC(SimpleComponent), null, 1);
30
- const shallowComponent = wrapper();
31
-
32
- expect(shallowComponent.find(SimpleComponent).length).toEqual(1);
33
- expect(shallowComponent.props().children.props.oneMoreProp).toEqual('hello');
34
- expect(shallowComponent.html().includes('span')).toEqual(true);
35
- });
36
-
37
- it('overwrites specific props when passed into the closure', () => {
38
- const wrapper = shallowChild(simpleHoC(SimpleComponent), null, 1);
39
- const shallowComponent = wrapper({ oneMoreProp: 'helloToo' });
40
-
41
- expect(shallowComponent.find(SimpleComponent).length).toEqual(1);
42
- expect(shallowComponent.props().children.props.oneMoreProp).toEqual('helloToo');
2
+ import { renderWithTheme, renderWithProviders, screen, createTestTheme } from '../index';
3
+ import { Button } from '@mui/material';
4
+
5
+ describe('@pie-lib/test-utils', () => {
6
+ describe('renderWithTheme', () => {
7
+ it('renders a component with default MUI theme', () => {
8
+ renderWithTheme(<Button>Click me</Button>);
9
+ expect(screen.getByRole('button')).toBeInTheDocument();
10
+ expect(screen.getByText('Click me')).toBeInTheDocument();
11
+ });
12
+
13
+ it('renders a component with custom theme', () => {
14
+ const customTheme = createTestTheme({
15
+ palette: {
16
+ primary: {
17
+ main: '#ff0000',
18
+ },
19
+ },
20
+ });
21
+
22
+ renderWithTheme(<Button color="primary">Themed Button</Button>, {
23
+ theme: customTheme,
24
+ });
25
+
26
+ expect(screen.getByRole('button')).toBeInTheDocument();
27
+ });
28
+
29
+ it('accepts additional render options', () => {
30
+ const { container } = renderWithTheme(<Button>Test</Button>, {
31
+ container: document.body,
32
+ });
33
+
34
+ expect(container).toBe(document.body);
35
+ });
36
+ });
37
+
38
+ describe('renderWithProviders', () => {
39
+ it('renders with theme provider by default', () => {
40
+ renderWithProviders(<Button>Provided Button</Button>);
41
+ expect(screen.getByRole('button')).toBeInTheDocument();
42
+ });
43
+
44
+ it('renders with additional providers', () => {
45
+ const TestProvider = ({ children }) => (
46
+ <div data-testid="test-provider">{children}</div>
47
+ );
48
+
49
+ renderWithProviders(<Button>Multi Provider</Button>, {
50
+ providers: [TestProvider],
51
+ });
52
+
53
+ expect(screen.getByTestId('test-provider')).toBeInTheDocument();
54
+ expect(screen.getByRole('button')).toBeInTheDocument();
55
+ });
56
+ });
57
+
58
+ describe('createTestTheme', () => {
59
+ it('creates a theme with custom options', () => {
60
+ const theme = createTestTheme({
61
+ palette: {
62
+ mode: 'dark',
63
+ primary: {
64
+ main: '#90caf9',
65
+ },
66
+ },
67
+ });
68
+
69
+ expect(theme.palette.mode).toBe('dark');
70
+ expect(theme.palette.primary.main).toBe('#90caf9');
71
+ });
72
+
73
+ it('creates a theme with default options when none provided', () => {
74
+ const theme = createTestTheme();
75
+ expect(theme.palette).toBeDefined();
76
+ expect(theme.spacing).toBeDefined();
77
+ });
78
+ });
79
+
80
+ describe('RTL re-exports', () => {
81
+ it('exports screen utility', () => {
82
+ renderWithTheme(<div>Test Content</div>);
83
+ expect(screen.getByText('Test Content')).toBeInTheDocument();
84
+ });
85
+
86
+ it('exports render function', async () => {
87
+ const { render, screen: screenImport } = await import('../index');
88
+ render(<div>Direct Render</div>);
89
+ expect(screenImport.getByText('Direct Render')).toBeInTheDocument();
43
90
  });
44
91
  });
45
92
  });
@@ -0,0 +1,116 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { Keys, pressKey, typeAndSubmit, clearAndType, navigateWithKeys } from '../keyboard';
4
+
5
+ describe('Keyboard helpers', () => {
6
+ describe('Keys constant', () => {
7
+ it('exports common key codes', () => {
8
+ expect(Keys.ENTER).toBe(13);
9
+ expect(Keys.ESCAPE).toBe(27);
10
+ expect(Keys.SPACE).toBe(32);
11
+ expect(Keys.TAB).toBe(9);
12
+ expect(Keys.ARROW_DOWN).toBe(40);
13
+ });
14
+ });
15
+
16
+ describe('pressKey', () => {
17
+ it('dispatches keyboard event with keyCode', () => {
18
+ const onKeyDown = jest.fn();
19
+ render(<input onKeyDown={onKeyDown} />);
20
+ const input = screen.getByRole('textbox');
21
+
22
+ pressKey(input, Keys.ENTER);
23
+
24
+ expect(onKeyDown).toHaveBeenCalled();
25
+ const event = onKeyDown.mock.calls[0][0];
26
+ expect(event.keyCode).toBe(13);
27
+ });
28
+
29
+ it('dispatches different event types', () => {
30
+ const onKeyUp = jest.fn();
31
+ render(<input onKeyUp={onKeyUp} />);
32
+ const input = screen.getByRole('textbox');
33
+
34
+ pressKey(input, Keys.ESCAPE, 'keyup');
35
+
36
+ expect(onKeyUp).toHaveBeenCalled();
37
+ const event = onKeyUp.mock.calls[0][0];
38
+ expect(event.keyCode).toBe(27);
39
+ });
40
+
41
+ it('passes additional options', () => {
42
+ const onKeyDown = jest.fn();
43
+ render(<input onKeyDown={onKeyDown} />);
44
+ const input = screen.getByRole('textbox');
45
+
46
+ pressKey(input, Keys.ENTER, 'keydown', { ctrlKey: true });
47
+
48
+ const event = onKeyDown.mock.calls[0][0];
49
+ expect(event.ctrlKey).toBe(true);
50
+ });
51
+ });
52
+
53
+ describe('typeAndSubmit', () => {
54
+ it('types text and presses Enter', async () => {
55
+ const onKeyDown = jest.fn();
56
+ render(<input onKeyDown={onKeyDown} />);
57
+ const input = screen.getByRole('textbox');
58
+
59
+ await typeAndSubmit(input, 'hello');
60
+
61
+ expect(input).toHaveValue('hello');
62
+ expect(onKeyDown).toHaveBeenCalled();
63
+ // Check that the last keyDown event was Enter
64
+ const lastEvent = onKeyDown.mock.calls[onKeyDown.mock.calls.length - 1][0];
65
+ expect(lastEvent.keyCode).toBe(Keys.ENTER);
66
+ });
67
+ });
68
+
69
+ describe('clearAndType', () => {
70
+ it('clears existing value and types new text', async () => {
71
+ render(<input defaultValue="old value" />);
72
+ const input = screen.getByRole('textbox');
73
+
74
+ await clearAndType(input, 'new value');
75
+
76
+ expect(input).toHaveValue('new value');
77
+ });
78
+ });
79
+
80
+ describe('navigateWithKeys', () => {
81
+ it('navigates down with arrow keys', () => {
82
+ const onKeyDown = jest.fn();
83
+ render(<div role="listbox" onKeyDown={onKeyDown} />);
84
+ const listbox = screen.getByRole('listbox');
85
+
86
+ navigateWithKeys(listbox, 3, 'vertical');
87
+
88
+ expect(onKeyDown).toHaveBeenCalledTimes(3);
89
+ const events = onKeyDown.mock.calls.map((call) => call[0].keyCode);
90
+ expect(events).toEqual([Keys.ARROW_DOWN, Keys.ARROW_DOWN, Keys.ARROW_DOWN]);
91
+ });
92
+
93
+ it('navigates up with negative steps', () => {
94
+ const onKeyDown = jest.fn();
95
+ render(<div role="listbox" onKeyDown={onKeyDown} />);
96
+ const listbox = screen.getByRole('listbox');
97
+
98
+ navigateWithKeys(listbox, -2, 'vertical');
99
+
100
+ expect(onKeyDown).toHaveBeenCalledTimes(2);
101
+ const events = onKeyDown.mock.calls.map((call) => call[0].keyCode);
102
+ expect(events).toEqual([Keys.ARROW_UP, Keys.ARROW_UP]);
103
+ });
104
+
105
+ it('navigates horizontally', () => {
106
+ const onKeyDown = jest.fn();
107
+ render(<div role="tablist" onKeyDown={onKeyDown} />);
108
+ const tablist = screen.getByRole('tablist');
109
+
110
+ navigateWithKeys(tablist, 2, 'horizontal');
111
+
112
+ const events = onKeyDown.mock.calls.map((call) => call[0].keyCode);
113
+ expect(events).toEqual([Keys.ARROW_RIGHT, Keys.ARROW_RIGHT]);
114
+ });
115
+ });
116
+ });