Skip to content

Commit 9607033

Browse files
yurishkuroclaude
andauthored
test: Replace arrow ctor mocks with regular functions (#3693)
Vitest 4.x rejects arrow functions called with `new`. Replace `mockImplementation(() => ({...}))` with `mockImplementation(function() { return {...}; })` in all 6 files where the mock target is a constructor. Affected: FileReader (readJsonFile.test.js), ResizeObserver (ServicesView, TraceDiff), LayoutManager (Graph/index, TraceGraph), ScrollManager (TracePage/index). Also update ADR section 9 / PR table to mark H2b done. ## AI Usage in this PR (choose one) See [AI Usage Policy](https://github.com/jaegertracing/jaeger/blob/main/CONTRIBUTING_GUIDELINES.md#ai-usage-policy). - [ ] **None**: No AI tools were used in creating this PR - [ ] **Light**: AI provided minor assistance (formatting, simple suggestions) - [ ] **Moderate**: AI helped with code generation or debugging specific parts - [x] **Heavy**: AI generated most or all of the code changes Signed-off-by: Yuri Shkuro <github@ysh.us> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 402c7be commit 9607033

File tree

7 files changed

+53
-39
lines changed

7 files changed

+53
-39
lines changed

docs/adr/0007-vite-plus-migration.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,16 @@ requires `vi.resetModules()` + `await import()` and will be handled in H3:
375375
- `utils/tracking/ga-coverage.test.js`
376376
- `prefix-url-coverage.test.js`
377377

378-
#### PR H2b — Replace arrow function constructors with regular functions (~16 files)
378+
#### PR H2b — Replace arrow function constructors with regular functions ([#3693](https://github.com/jaegertracing/jaeger-ui/pull/3693))
379379

380380
`mockImplementation(() => ({...}))` fails when the mock is called with `new` in Vitest 4.x.
381-
Replacing with `mockImplementation(function() { return {...}; })` is safe under Jest too.
381+
Replaced with `mockImplementation(function() { return {...}; })` — safe under Jest too.
382+
383+
Six files had constructor mocks (identified by checking which `mockImplementation` targets are
384+
called with `new` in production code): `readJsonFile.test.js` (FileReader ×3),
385+
`Monitor/ServicesView/index.test.jsx` (ResizeObserver), `TraceDiff/TraceDiff.test.jsx` (ResizeObserver),
386+
`DeepDependencies/Graph/index.test.jsx` (LayoutManager), `TracePage/index.test.jsx` (ScrollManager ×3),
387+
`TracePage/TraceGraph/TraceGraph.test.jsx` (MockLayoutManager).
382388

383389
#### PR H2c — Introduce `mockDefault` helper in affected mock factories
384390

@@ -592,7 +598,7 @@ confirm no errors or unexpected HTML injection.
592598
| 🔶 F | Migrate Jest → Vitest in both packages; remove Babel test deps ([#3690](https://github.com/jaegertracing/jaeger-ui/pull/3690) plexus ✅, jaeger-ui pending) | Unknowns 3, 4, 5, 6 | Partial |
593599
| ✅ H1 | Rename `.test.js``.test.jsx` in jaeger-ui (121 files, pure rename) ([#3691](https://github.com/jaegertracing/jaeger-ui/pull/3691)) | None | Done |
594600
| ✅ H2a | Replace `require()` in test bodies with static `import` ([#3692](https://github.com/jaegertracing/jaeger-ui/pull/3692)) | None | Done |
595-
| H2b | Replace arrow function constructors with regular functions (~16 files) | None | After H1 |
601+
| H2b | Replace arrow function constructors with regular functions (6 files) ([#3693](https://github.com/jaegertracing/jaeger-ui/pull/3693)) | None | Done |
596602
| H2c | Introduce `mockDefault` helper in affected mock factories | None | After H1 |
597603
| H3 | Vitest switch for jaeger-ui | Unknowns 3, 4, 5, 6 | After H2a–c |
598604
| G | Update CLAUDE.md, README, CI workflows | None | After H3 |

packages/jaeger-ui/src/components/DeepDependencies/Graph/index.test.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ jest.mock('@jaegertracing/plexus', () => ({
1818
},
1919
}
2020
),
21-
LayoutManager: jest.fn().mockImplementation(() => ({
22-
stopAndRelease: jest.fn(),
23-
})),
21+
LayoutManager: jest.fn().mockImplementation(function () {
22+
return { stopAndRelease: jest.fn() };
23+
}),
2424
}));
2525

2626
jest.mock('./DdgNodeContent', () => ({

packages/jaeger-ui/src/components/Monitor/ServicesView/index.test.jsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@ import {
2222
} from '../../../reducers/metrics.mock';
2323
import * as track from './index.track';
2424

25-
global.ResizeObserver = jest.fn().mockImplementation(() => ({
26-
observe: jest.fn(),
27-
unobserve: jest.fn(),
28-
disconnect: jest.fn(),
29-
}));
25+
global.ResizeObserver = jest.fn().mockImplementation(function () {
26+
return { observe: jest.fn(), unobserve: jest.fn(), disconnect: jest.fn() };
27+
});
3028

3129
jest.mock('../../../utils/config/get-config', () => ({
3230
__esModule: true,

packages/jaeger-ui/src/components/TraceDiff/TraceDiff.test.jsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,11 +257,9 @@ describe('TraceDiff', () => {
257257
describe('TraceDiff--graphWrapper top offset', () => {
258258
it('applies top offset to graph wrapper based on header height', () => {
259259
const originalResizeObserver = window.ResizeObserver;
260-
window.ResizeObserver = jest.fn().mockImplementation(() => ({
261-
observe: jest.fn(),
262-
unobserve: jest.fn(),
263-
disconnect: jest.fn(),
264-
}));
260+
window.ResizeObserver = jest.fn().mockImplementation(function () {
261+
return { observe: jest.fn(), unobserve: jest.fn(), disconnect: jest.fn() };
262+
});
265263

266264
const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect;
267265
Element.prototype.getBoundingClientRect = jest.fn().mockImplementation(function () {

packages/jaeger-ui/src/components/TracePage/TraceGraph/TraceGraph.test.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ jest.mock('@jaegertracing/plexus', () => {
4545
scaleStrokeOpacity: () => ({ strokeOpacity: 1 }),
4646
};
4747

48-
const MockLayoutManager = jest.fn().mockImplementation(() => ({
49-
stopAndRelease: jest.fn(),
50-
}));
48+
const MockLayoutManager = jest.fn().mockImplementation(function () {
49+
return { stopAndRelease: jest.fn() };
50+
});
5151

5252
const mockCacheAs = (key, fn) => {
5353
const cachedFn = (...args) => fn(...args);

packages/jaeger-ui/src/components/TracePage/index.test.jsx

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,16 @@ jest.mock('./TraceLogsView/index', () => {
7171
});
7272

7373
jest.mock('./ScrollManager', () => {
74-
return jest.fn().mockImplementation(() => ({
75-
scrollToNextVisibleSpan: jest.fn(),
76-
scrollToPrevVisibleSpan: jest.fn(),
77-
setTrace: jest.fn(),
78-
destroy: jest.fn(),
79-
setAccessors: jest.fn(),
80-
scrollToFirstVisibleSpan: jest.fn(),
81-
}));
74+
return jest.fn().mockImplementation(function () {
75+
return {
76+
scrollToNextVisibleSpan: jest.fn(),
77+
scrollToPrevVisibleSpan: jest.fn(),
78+
setTrace: jest.fn(),
79+
destroy: jest.fn(),
80+
setAccessors: jest.fn(),
81+
scrollToFirstVisibleSpan: jest.fn(),
82+
};
83+
});
8284
});
8385

8486
jest.mock('./index.track');
@@ -412,14 +414,16 @@ describe('<TracePage>', () => {
412414
it('calls scrollManager.setTrace when trace data changes', () => {
413415
const setTraceMock = jest.fn();
414416

415-
ScrollManager.mockImplementation(() => ({
416-
scrollToNextVisibleSpan: jest.fn(),
417-
scrollToPrevVisibleSpan: jest.fn(),
418-
setAccessors: jest.fn(),
419-
scrollToFirstVisibleSpan: jest.fn(),
420-
destroy: jest.fn(),
421-
setTrace: setTraceMock,
422-
}));
417+
ScrollManager.mockImplementation(function () {
418+
return {
419+
scrollToNextVisibleSpan: jest.fn(),
420+
scrollToPrevVisibleSpan: jest.fn(),
421+
setAccessors: jest.fn(),
422+
scrollToFirstVisibleSpan: jest.fn(),
423+
destroy: jest.fn(),
424+
setTrace: setTraceMock,
425+
};
426+
});
423427

424428
const { rerender } = render(<TracePage {...defaultProps} trace={null} />);
425429
rerender(<TracePage {...defaultProps} trace={{ data: trace, state: fetchedState.DONE }} />);
@@ -438,7 +442,9 @@ describe('<TracePage>', () => {
438442
setTrace: jest.fn(),
439443
};
440444

441-
ScrollManager.mockImplementation(() => scrollManagerMock);
445+
ScrollManager.mockImplementation(function () {
446+
return scrollManagerMock;
447+
});
442448

443449
const resetShortcutsMock = jest.spyOn(keyboardShortcutsMod, 'reset');
444450
const cancelScrollMock = jest.spyOn(scrollPageMod, 'cancel');

packages/jaeger-ui/src/utils/readJsonFile.test.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ describe('fileReader.readJsonFile', () => {
105105
const file = new File([''], 'error.json');
106106
const mockReader = { readAsText: jest.fn(), onerror: null, error: new Error('Read error') };
107107

108-
fileReaderSpy = jest.spyOn(window, 'FileReader').mockImplementation(() => mockReader);
108+
fileReaderSpy = jest.spyOn(window, 'FileReader').mockImplementation(function () {
109+
return mockReader;
110+
});
109111
const promise = readJsonFile({ file });
110112

111113
mockReader.onerror();
@@ -117,7 +119,9 @@ describe('fileReader.readJsonFile', () => {
117119
const file = new File([''], 'abort.json');
118120
const mockReader = { readAsText: jest.fn(), onabort: null };
119121

120-
fileReaderSpy = jest.spyOn(window, 'FileReader').mockImplementation(() => mockReader);
122+
fileReaderSpy = jest.spyOn(window, 'FileReader').mockImplementation(function () {
123+
return mockReader;
124+
});
121125
const promise = readJsonFile({ file });
122126

123127
mockReader.onabort();
@@ -129,7 +133,9 @@ describe('fileReader.readJsonFile', () => {
129133
const file = new File(['{ "test": true }'], 'dummy.json');
130134
const mockReader = { readAsText: jest.fn(), onload: null, result: {} };
131135

132-
fileReaderSpy = jest.spyOn(window, 'FileReader').mockImplementation(() => mockReader);
136+
fileReaderSpy = jest.spyOn(window, 'FileReader').mockImplementation(function () {
137+
return mockReader;
138+
});
133139
const promise = readJsonFile({ file });
134140

135141
mockReader.onload();

0 commit comments

Comments
 (0)