Skip to content

Commit 10255dc

Browse files
committed
added tests for performance
1 parent 6fe1268 commit 10255dc

File tree

2 files changed

+250
-1
lines changed

2 files changed

+250
-1
lines changed

src/app/FrontendTypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export interface PerfData {
2222
export interface PerformanceVisxProps {
2323
width: number;
2424
height: number;
25-
snapshots: [];
25+
snapshots: any[];
2626
hierarchy: any;
2727
}
2828

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
import '@testing-library/jest-dom';
2+
import React from 'react';
3+
import { render, screen, fireEvent } from '@testing-library/react';
4+
import { Provider } from 'react-redux';
5+
import { MemoryRouter } from 'react-router-dom';
6+
import configureStore from 'redux-mock-store';
7+
8+
import BarGraph from '../components/StateRoute/PerformanceVisx/BarGraph';
9+
import PerformanceVisx from '../components/StateRoute/PerformanceVisx/PerformanceVisx';
10+
11+
// Mock ResizeObserver
12+
class ResizeObserver {
13+
observe() {}
14+
unobserve() {}
15+
disconnect() {}
16+
}
17+
18+
// Mock VisxTooltip Portal
19+
jest.mock('@visx/tooltip', () => ({
20+
...jest.requireActual('@visx/tooltip'),
21+
useTooltipInPortal: () => ({
22+
tooltipLeft: 0,
23+
tooltipTop: 0,
24+
tooltipData: null,
25+
TooltipInPortal: ({ children }) => children,
26+
containerRef: { current: null },
27+
}),
28+
}));
29+
30+
// Mock window.ResizeObserver
31+
window.ResizeObserver = ResizeObserver;
32+
33+
// Mock createPortal since JSDOM doesn't support it
34+
jest.mock('react-dom', () => ({
35+
...jest.requireActual('react-dom'),
36+
createPortal: (node) => node,
37+
}));
38+
39+
// Mock SVG elements that JSDOM doesn't support
40+
const createElementNSOrig = global.document.createElementNS;
41+
global.document.createElementNS = function (namespaceURI, qualifiedName) {
42+
if (namespaceURI === 'http://www.w3.org/2000/svg' && qualifiedName === 'svg') {
43+
const element = createElementNSOrig.apply(this, arguments);
44+
element.createSVGRect = function () {};
45+
return element;
46+
}
47+
return createElementNSOrig.apply(this, arguments);
48+
};
49+
50+
// Mock getComputedStyle for SVG elements
51+
window.getComputedStyle = (element) => {
52+
// Create an object with string index signatures
53+
const cssProperties = Array.from({ length: 1000 }).reduce<{ [key: string]: string }>(
54+
(acc, _, index) => {
55+
acc[index.toString()] = '';
56+
return acc;
57+
},
58+
{},
59+
);
60+
61+
const cssStyleDeclaration: CSSStyleDeclaration = {
62+
getPropertyValue: (prop: string) => '',
63+
item: (index: number) => '',
64+
removeProperty: (property: string) => '',
65+
setProperty: (property: string, value: string) => {},
66+
parentRule: null,
67+
length: 0,
68+
[Symbol.iterator]: function* () {},
69+
...cssProperties,
70+
} as CSSStyleDeclaration;
71+
72+
return cssStyleDeclaration;
73+
};
74+
75+
// Suppress specific console warnings
76+
const originalError = console.error;
77+
console.error = (...args) => {
78+
if (args[0].includes('Warning: ReactDOM.render is no longer supported')) {
79+
return;
80+
}
81+
originalError.call(console, ...args);
82+
};
83+
84+
const mockStore = configureStore([]);
85+
86+
// Test fixtures
87+
const mockBarGraphProps = {
88+
width: 800,
89+
height: 600,
90+
data: {
91+
barStack: [
92+
{
93+
snapshotId: 'snapshot1',
94+
'Component-1': 100,
95+
'Component-2': 150,
96+
},
97+
{
98+
snapshotId: 'snapshot2',
99+
'Component-1': 120,
100+
'Component-2': 140,
101+
},
102+
],
103+
componentData: {
104+
'Component-1': {
105+
stateType: 'stateless',
106+
renderFrequency: 2,
107+
totalRenderTime: 220,
108+
rtid: 'rt1',
109+
information: {},
110+
},
111+
'Component-2': {
112+
stateType: 'stateful',
113+
renderFrequency: 2,
114+
totalRenderTime: 290,
115+
rtid: 'rt2',
116+
information: {},
117+
},
118+
},
119+
maxTotalRender: 290,
120+
},
121+
comparison: [],
122+
setRoute: jest.fn(),
123+
allRoutes: ['/home', '/about'],
124+
filteredSnapshots: [],
125+
setSnapshot: jest.fn(),
126+
snapshot: 'All Snapshots',
127+
};
128+
129+
const mockPerformanceVisxProps = {
130+
width: 800,
131+
height: 600,
132+
snapshots: [
133+
{
134+
name: 'Root',
135+
branch: '1',
136+
route: { url: 'http://localhost:3000/home' },
137+
children: [
138+
{
139+
name: 'Component1',
140+
componentData: {
141+
actualDuration: '100.5',
142+
props: { test: 'prop' },
143+
},
144+
children: [],
145+
rtid: 'rt1',
146+
state: 'stateless',
147+
},
148+
],
149+
},
150+
],
151+
hierarchy: {
152+
name: 'Root',
153+
branch: '1',
154+
children: [],
155+
},
156+
};
157+
158+
const mockReduxState = {
159+
main: {
160+
tabs: {
161+
0: { title: 'Test Tab' },
162+
},
163+
currentTab: 0,
164+
currentTabInApp: 'performance',
165+
},
166+
};
167+
168+
describe('Performance Components', () => {
169+
let store;
170+
171+
beforeEach(() => {
172+
store = mockStore(mockReduxState);
173+
Storage.prototype.getItem = jest.fn(() => null);
174+
Storage.prototype.setItem = jest.fn();
175+
});
176+
177+
describe('BarGraph Component', () => {
178+
const renderBarGraph = () => {
179+
return render(
180+
<Provider store={store}>
181+
{/* @ts-ignore */}
182+
<BarGraph {...mockBarGraphProps} />
183+
</Provider>,
184+
);
185+
};
186+
187+
it('renders without crashing', () => {
188+
const { container } = renderBarGraph();
189+
expect(screen.getByText('Route:')).toBeInTheDocument();
190+
expect(screen.getByText('Snapshot:')).toBeInTheDocument();
191+
expect(container.querySelector('svg')).toBeInTheDocument();
192+
});
193+
194+
it('displays correct axis labels', () => {
195+
renderBarGraph();
196+
expect(screen.getByText('Rendering Time (ms)')).toBeInTheDocument();
197+
expect(screen.getByText('Snapshot ID')).toBeInTheDocument();
198+
});
199+
200+
it('handles route selection', () => {
201+
renderBarGraph();
202+
const routeSelect = screen.getByLabelText('Route:');
203+
fireEvent.change(routeSelect, { target: { value: '/home' } });
204+
expect(mockBarGraphProps.setRoute).toHaveBeenCalledWith('/home');
205+
});
206+
207+
it('handles snapshot selection', () => {
208+
renderBarGraph();
209+
const snapshotSelect = screen.getByLabelText('Snapshot:');
210+
fireEvent.change(snapshotSelect, { target: { value: 'snapshot1' } });
211+
expect(mockBarGraphProps.setSnapshot).toHaveBeenCalledWith('snapshot1');
212+
});
213+
214+
it('renders correct number of bars', () => {
215+
const { container } = renderBarGraph();
216+
const bars = container.querySelectorAll('rect[width]');
217+
// Each snapshot has 2 components, so we expect 4 bars total
218+
expect(bars.length).toBe(5);
219+
});
220+
});
221+
222+
describe('PerformanceVisx Component', () => {
223+
const renderPerformanceVisx = () => {
224+
return render(
225+
<Provider store={store}>
226+
<MemoryRouter>
227+
<PerformanceVisx {...mockPerformanceVisxProps} />
228+
</MemoryRouter>
229+
</Provider>,
230+
);
231+
};
232+
233+
it('renders without crashing', () => {
234+
const { container } = renderPerformanceVisx();
235+
expect(container.querySelector('svg')).toBeInTheDocument();
236+
});
237+
238+
it('dispatches setCurrentTabInApp on mount', () => {
239+
renderPerformanceVisx();
240+
const actions = store.getActions();
241+
expect(actions).toEqual([{ type: 'main/setCurrentTabInApp', payload: 'performance' }]);
242+
});
243+
244+
it('processes route data correctly', () => {
245+
renderPerformanceVisx();
246+
expect(screen.getByText('/home')).toBeInTheDocument();
247+
});
248+
});
249+
});

0 commit comments

Comments
 (0)