Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions tests/ui/test-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,86 @@
// Entry point for Jest tests
import '@testing-library/jest-dom/jest-globals';

// Configure React 18 act environment for testing
globalThis.IS_REACT_ACT_ENVIRONMENT = true;

// Mock ResizeObserver which is required by @melloware/react-logviewer
// but not available in jsdom
global.ResizeObserver = class ResizeObserver {
constructor(callback) {
this.callback = callback;
}

observe() {}

unobserve() {}

disconnect() {}
};

// JSDOM doesn't implement scrollIntoView, so we mock it
Element.prototype.scrollIntoView = jest.fn();

// Suppress known act() warnings that don't affect test outcomes
// These are caused by:
// 1. React.lazy/Suspense async loading
// 2. Cross-test async timing in Jest's parallel execution
// 3. Third-party libraries (Popper.js, react-router) with async state updates
// 4. AuthService/Login async cleanup after tests complete
// Note: Some warnings may still appear in Jest's output due to its console capture timing
const suppressedPatterns = [
'suspended resource finished loading inside a test',
'An update to App inside a test was not wrapped in act',
'An update to Router inside a test was not wrapped in act',
'An update to Connect(',
];

/* eslint-disable no-console */
const originalConsoleError = console.error;
console.error = (...args) => {
const message = args
.map((arg) => (typeof arg === 'string' ? arg : String(arg)))
.join(' ');
if (suppressedPatterns.some((pattern) => message.includes(pattern))) {
return;
}
originalConsoleError.apply(console, args);
};

// Mock @restart/ui's usePopper to prevent async positioning updates that cause act() warnings
// React Bootstrap's DropdownMenu uses Popper.js which triggers async state updates outside React's control
// This mock provides enough functionality for tooltips and overlays to render while avoiding async warnings
jest.mock('@restart/ui/usePopper', () => {
// eslint-disable-next-line global-require
const React = require('react');
return function usePopper(_referenceElement, _popperElement, options) {
const [state] = React.useState({
placement: options?.placement || 'bottom',
styles: {
popper: {
position: 'absolute',
top: '0',
left: '0',
},
arrow: {},
},
attributes: {
popper: {
'data-popper-placement': options?.placement || 'bottom',
},
},
});

return {
...state,
update: jest.fn(() => Promise.resolve(state)),
forceUpdate: jest.fn(),
arrowStyles: {},
outOfBoundaries: false,
};
};
});

const mockBuildUrl = jest.fn((root, taskId, path) => {
return `${root}/${taskId}/artifacts/${path}`;
});
Expand Down
2 changes: 1 addition & 1 deletion ui/infra-compare/InfraCompare.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function InfraCompareView({
const [jobsNotDisplayed, setJobsNotDisplayed] = React.useState([]);

const getInterval = (oldTimestamp, newTimestamp) => {
const now = Date.now()/ 1000;
const now = Date.now() / 1000;
let timeRange = Math.min(oldTimestamp, newTimestamp);
timeRange = Math.round(now - timeRange);
const newTimeRange = phTimeRanges.find((time) => timeRange <= time.value);
Expand Down