@rakeyshgidwani/roger-ui-bank-theme-stan-design 0.1.7 → 0.1.8
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 +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.esm.js +3 -11
- package/dist/index.js +3 -11
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/index.ts +5 -15
- package/dist/setupTests.d.ts +0 -124
- package/dist/setupTests.esm.js +0 -122
- package/dist/setupTests.js +0 -122
- package/src/setupTests.ts +0 -124
- package/src/stories/README.md +0 -39
- package/src/stories/components/ThemeDebugger.tsx +0 -143
- package/src/stories/index.ts +0 -29
- package/src/stories/storybook-theme-imports.css +0 -51
- package/src/test-utils/index.ts +0 -7
- package/src/test-utils/theme-testing.tsx +0 -219
- package/src/testing/test-automation.ts +0 -627
- package/src/testing/test-utils.tsx +0 -367
|
@@ -1,367 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Testing Utilities for Component Testing Framework
|
|
3
|
-
* Provides comprehensive testing helpers for visual regression, theme switching,
|
|
4
|
-
* state testing, responsive testing, and accessibility testing
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import React from 'react';
|
|
8
|
-
import { render, RenderOptions, RenderResult } from '@testing-library/react';
|
|
9
|
-
import { ThemeProvider } from '../themes/ThemeProvider';
|
|
10
|
-
// Note: Components are imported in tests where needed
|
|
11
|
-
|
|
12
|
-
// Theme names available for testing
|
|
13
|
-
export type ThemeName = 'default' | 'stan-design' | 'harvey';
|
|
14
|
-
|
|
15
|
-
// Extended render options for comprehensive testing
|
|
16
|
-
interface ExtendedRenderOptions extends Omit<RenderOptions, 'wrapper'> {
|
|
17
|
-
theme?: ThemeName;
|
|
18
|
-
wrapper?: React.ComponentType<{ children: React.ReactNode }>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Custom render function with theme provider wrapper
|
|
23
|
-
*/
|
|
24
|
-
export function renderWithTheme(
|
|
25
|
-
ui: React.ReactElement,
|
|
26
|
-
options: ExtendedRenderOptions = {}
|
|
27
|
-
): RenderResult {
|
|
28
|
-
const { theme, wrapper: Wrapper, ...renderOptions } = options;
|
|
29
|
-
|
|
30
|
-
function ThemeWrapper({ children }: { children: React.ReactNode }) {
|
|
31
|
-
const content = theme ? (
|
|
32
|
-
<ThemeProvider defaultTheme={theme}>{children}</ThemeProvider>
|
|
33
|
-
) : (
|
|
34
|
-
children
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
return Wrapper ? <Wrapper>{content}</Wrapper> : <>{content}</>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return render(ui, { wrapper: ThemeWrapper, ...renderOptions });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Test all theme variants of a component
|
|
45
|
-
*/
|
|
46
|
-
export function testAllThemes(
|
|
47
|
-
component: React.ReactElement,
|
|
48
|
-
testFn: (theme: ThemeName, result: RenderResult) => void
|
|
49
|
-
) {
|
|
50
|
-
const themes: ThemeName[] = ['default', 'stan-design', 'harvey'];
|
|
51
|
-
|
|
52
|
-
themes.forEach((theme) => {
|
|
53
|
-
describe(`with ${theme} theme`, () => {
|
|
54
|
-
const result = renderWithTheme(component, { theme });
|
|
55
|
-
testFn(theme, result);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Viewport sizes for responsive testing
|
|
62
|
-
*/
|
|
63
|
-
export const viewports = {
|
|
64
|
-
mobile: { width: 375, height: 667 },
|
|
65
|
-
tablet: { width: 768, height: 1024 },
|
|
66
|
-
desktop: { width: 1024, height: 768 },
|
|
67
|
-
wide: { width: 1440, height: 900 },
|
|
68
|
-
ultrawide: { width: 1920, height: 1080 },
|
|
69
|
-
} as const;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Set viewport size for responsive testing
|
|
73
|
-
*/
|
|
74
|
-
export function setViewport(size: keyof typeof viewports) {
|
|
75
|
-
const { width, height } = viewports[size];
|
|
76
|
-
|
|
77
|
-
// Mock window dimensions
|
|
78
|
-
Object.defineProperty(window, 'innerWidth', {
|
|
79
|
-
writable: true,
|
|
80
|
-
configurable: true,
|
|
81
|
-
value: width,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
Object.defineProperty(window, 'innerHeight', {
|
|
85
|
-
writable: true,
|
|
86
|
-
configurable: true,
|
|
87
|
-
value: height,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Trigger resize event
|
|
91
|
-
window.dispatchEvent(new Event('resize'));
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Test component across all viewport sizes
|
|
96
|
-
*/
|
|
97
|
-
export function testAllViewports(
|
|
98
|
-
component: React.ReactElement,
|
|
99
|
-
testFn: (viewport: keyof typeof viewports, result: RenderResult) => void
|
|
100
|
-
) {
|
|
101
|
-
Object.keys(viewports).forEach((viewport) => {
|
|
102
|
-
const viewportKey = viewport as keyof typeof viewports;
|
|
103
|
-
|
|
104
|
-
describe(`at ${viewport} viewport`, () => {
|
|
105
|
-
beforeEach(() => {
|
|
106
|
-
setViewport(viewportKey);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
const result = render(component);
|
|
110
|
-
testFn(viewportKey, result);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Component states for state testing
|
|
117
|
-
*/
|
|
118
|
-
export const componentStates = [
|
|
119
|
-
'default',
|
|
120
|
-
'hover',
|
|
121
|
-
'focus',
|
|
122
|
-
'active',
|
|
123
|
-
'disabled',
|
|
124
|
-
'loading',
|
|
125
|
-
'error',
|
|
126
|
-
] as const;
|
|
127
|
-
|
|
128
|
-
export type ComponentState = typeof componentStates[number];
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Apply state to an element for testing
|
|
132
|
-
*/
|
|
133
|
-
export function applyState(element: HTMLElement, state: ComponentState) {
|
|
134
|
-
switch (state) {
|
|
135
|
-
case 'hover':
|
|
136
|
-
element.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
|
|
137
|
-
break;
|
|
138
|
-
case 'focus':
|
|
139
|
-
element.focus();
|
|
140
|
-
break;
|
|
141
|
-
case 'active':
|
|
142
|
-
element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
|
|
143
|
-
break;
|
|
144
|
-
case 'disabled':
|
|
145
|
-
if ('disabled' in element) {
|
|
146
|
-
(element as any).disabled = true;
|
|
147
|
-
} else {
|
|
148
|
-
element.setAttribute('aria-disabled', 'true');
|
|
149
|
-
}
|
|
150
|
-
break;
|
|
151
|
-
case 'loading':
|
|
152
|
-
element.setAttribute('aria-busy', 'true');
|
|
153
|
-
break;
|
|
154
|
-
case 'error':
|
|
155
|
-
element.setAttribute('aria-invalid', 'true');
|
|
156
|
-
break;
|
|
157
|
-
default:
|
|
158
|
-
// Default state - no modifications needed
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Test all component states
|
|
165
|
-
*/
|
|
166
|
-
export function testAllStates(
|
|
167
|
-
getElement: () => HTMLElement,
|
|
168
|
-
testFn: (state: ComponentState, element: HTMLElement) => void
|
|
169
|
-
) {
|
|
170
|
-
componentStates.forEach((state) => {
|
|
171
|
-
describe(`in ${state} state`, () => {
|
|
172
|
-
const element = getElement();
|
|
173
|
-
applyState(element, state);
|
|
174
|
-
testFn(state, element);
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Mock CSS media queries for responsive testing
|
|
181
|
-
*/
|
|
182
|
-
export function mockMediaQuery(query: string, matches: boolean = true) {
|
|
183
|
-
const mockMediaQuery = {
|
|
184
|
-
matches,
|
|
185
|
-
media: query,
|
|
186
|
-
onchange: null,
|
|
187
|
-
addListener: jest.fn(),
|
|
188
|
-
removeListener: jest.fn(),
|
|
189
|
-
addEventListener: jest.fn(),
|
|
190
|
-
removeEventListener: jest.fn(),
|
|
191
|
-
dispatchEvent: jest.fn(),
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
Object.defineProperty(window, 'matchMedia', {
|
|
195
|
-
writable: true,
|
|
196
|
-
value: jest.fn().mockImplementation(() => mockMediaQuery),
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
return mockMediaQuery;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Performance testing utilities
|
|
204
|
-
*/
|
|
205
|
-
export const performanceUtils = {
|
|
206
|
-
/**
|
|
207
|
-
* Measure component render time
|
|
208
|
-
*/
|
|
209
|
-
measureRenderTime: (renderFn: () => RenderResult): number => {
|
|
210
|
-
const start = performance.now();
|
|
211
|
-
renderFn();
|
|
212
|
-
const end = performance.now();
|
|
213
|
-
return end - start;
|
|
214
|
-
},
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Test render performance across multiple runs
|
|
218
|
-
*/
|
|
219
|
-
testRenderPerformance: (
|
|
220
|
-
renderFn: () => RenderResult,
|
|
221
|
-
iterations: number = 10,
|
|
222
|
-
maxTime: number = 50 // ms
|
|
223
|
-
): { average: number; max: number; passed: boolean } => {
|
|
224
|
-
const times: number[] = [];
|
|
225
|
-
|
|
226
|
-
for (let i = 0; i < iterations; i++) {
|
|
227
|
-
const time = performanceUtils.measureRenderTime(renderFn);
|
|
228
|
-
times.push(time);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const average = times.reduce((sum, time) => sum + time, 0) / times.length;
|
|
232
|
-
const max = Math.max(...times);
|
|
233
|
-
const passed = max <= maxTime;
|
|
234
|
-
|
|
235
|
-
return { average, max, passed };
|
|
236
|
-
},
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Accessibility testing utilities
|
|
241
|
-
*/
|
|
242
|
-
export const a11yUtils = {
|
|
243
|
-
/**
|
|
244
|
-
* Check if element has proper ARIA labels
|
|
245
|
-
*/
|
|
246
|
-
hasAriaLabel: (element: HTMLElement): boolean => {
|
|
247
|
-
return Boolean(
|
|
248
|
-
element.getAttribute('aria-label') ||
|
|
249
|
-
element.getAttribute('aria-labelledby') ||
|
|
250
|
-
element.getAttribute('aria-describedby')
|
|
251
|
-
);
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Check if element is keyboard accessible
|
|
256
|
-
*/
|
|
257
|
-
isKeyboardAccessible: (element: HTMLElement): boolean => {
|
|
258
|
-
const tabIndex = element.getAttribute('tabindex');
|
|
259
|
-
const isInteractive = ['button', 'input', 'select', 'textarea', 'a'].includes(
|
|
260
|
-
element.tagName.toLowerCase()
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
return (
|
|
264
|
-
isInteractive ||
|
|
265
|
-
(tabIndex !== null && parseInt(tabIndex) >= 0) ||
|
|
266
|
-
element.hasAttribute('role')
|
|
267
|
-
);
|
|
268
|
-
},
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Check if element has sufficient color contrast
|
|
272
|
-
* Note: This is a simplified check - full contrast checking requires advanced algorithms
|
|
273
|
-
*/
|
|
274
|
-
hasSufficientContrast: (element: HTMLElement): boolean => {
|
|
275
|
-
const styles = window.getComputedStyle(element);
|
|
276
|
-
const color = styles.color;
|
|
277
|
-
const backgroundColor = styles.backgroundColor;
|
|
278
|
-
|
|
279
|
-
// This is a simplified check - in a real implementation,
|
|
280
|
-
// you would use a proper contrast ratio calculation
|
|
281
|
-
return color !== backgroundColor;
|
|
282
|
-
},
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Visual regression testing utilities
|
|
287
|
-
*/
|
|
288
|
-
export const visualRegressionUtils = {
|
|
289
|
-
/**
|
|
290
|
-
* Create a snapshot test for visual regression
|
|
291
|
-
*/
|
|
292
|
-
expectComponentSnapshot: (component: React.ReactElement, name?: string) => {
|
|
293
|
-
const { container } = renderWithTheme(component, { theme: 'default' });
|
|
294
|
-
expect(container.firstChild).toMatchSnapshot(name);
|
|
295
|
-
},
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Test component visual consistency across themes
|
|
299
|
-
*/
|
|
300
|
-
expectThemeConsistency: (component: React.ReactElement) => {
|
|
301
|
-
const themes: ThemeName[] = ['default', 'stan-design', 'harvey'];
|
|
302
|
-
|
|
303
|
-
themes.forEach((theme) => {
|
|
304
|
-
const { container } = renderWithTheme(component, { theme });
|
|
305
|
-
expect(container.firstChild).toMatchSnapshot(`theme-${theme}`);
|
|
306
|
-
});
|
|
307
|
-
},
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Test component visual consistency across states
|
|
311
|
-
*/
|
|
312
|
-
expectStateConsistency: (
|
|
313
|
-
getComponent: (state: ComponentState) => React.ReactElement
|
|
314
|
-
) => {
|
|
315
|
-
componentStates.forEach((state) => {
|
|
316
|
-
const component = getComponent(state);
|
|
317
|
-
const { container } = render(component);
|
|
318
|
-
expect(container.firstChild).toMatchSnapshot(`state-${state}`);
|
|
319
|
-
});
|
|
320
|
-
},
|
|
321
|
-
};
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Cross-browser testing utilities
|
|
325
|
-
*/
|
|
326
|
-
export const crossBrowserUtils = {
|
|
327
|
-
/**
|
|
328
|
-
* Mock different user agents for browser testing
|
|
329
|
-
*/
|
|
330
|
-
mockUserAgent: (userAgent: string) => {
|
|
331
|
-
Object.defineProperty(navigator, 'userAgent', {
|
|
332
|
-
writable: true,
|
|
333
|
-
value: userAgent,
|
|
334
|
-
});
|
|
335
|
-
},
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Test component across different browsers
|
|
339
|
-
*/
|
|
340
|
-
testAcrossBrowsers: (
|
|
341
|
-
component: React.ReactElement,
|
|
342
|
-
testFn: (browser: string, result: RenderResult) => void
|
|
343
|
-
) => {
|
|
344
|
-
const browsers = {
|
|
345
|
-
chrome: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
|
|
346
|
-
firefox: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0',
|
|
347
|
-
safari: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
|
|
348
|
-
edge: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59',
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
Object.entries(browsers).forEach(([browser, userAgent]) => {
|
|
352
|
-
describe(`in ${browser}`, () => {
|
|
353
|
-
beforeEach(() => {
|
|
354
|
-
crossBrowserUtils.mockUserAgent(userAgent);
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
const result = render(component);
|
|
358
|
-
testFn(browser, result);
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
},
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
// Re-export testing library utilities
|
|
365
|
-
export * from '@testing-library/react';
|
|
366
|
-
export * from '@testing-library/user-event';
|
|
367
|
-
export { default as userEvent } from '@testing-library/user-event';
|