Doubles frontend test findBy* timeouts to reduce CI flakiness
Continuous Integration / config (pull_request) Successful in 10s
Continuous Integration / backend-build (pull_request) Successful in 4m48s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m33s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m47s
Continuous Integration / backend-test (pull_request) Successful in 5m17s
Continuous Integration / frontend-build (pull_request) Successful in 2m13s
Continuous Integration / frontend-test (pull_request) Successful in 4m22s
Continuous Integration / frontend-lint (pull_request) Successful in 2m0s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m18s
Deploy (SCP) / deploy (pull_request) Successful in 1m28s
Continuous Integration / deploy-test (pull_request) Successful in 1m29s
Continuous Integration / config (pull_request) Successful in 10s
Continuous Integration / backend-build (pull_request) Successful in 4m48s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m33s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m47s
Continuous Integration / backend-test (pull_request) Successful in 5m17s
Continuous Integration / frontend-build (pull_request) Successful in 2m13s
Continuous Integration / frontend-test (pull_request) Successful in 4m22s
Continuous Integration / frontend-lint (pull_request) Successful in 2m0s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m18s
Deploy (SCP) / deploy (pull_request) Successful in 1m28s
Continuous Integration / deploy-test (pull_request) Successful in 1m29s
5000ms was occasionally too tight on the self-hosted Actions runner for lazy-loaded routes gated behind an async setup-status check (observed on SettingsPage.test.tsx, passed reliably locally). Bumps to 10000ms across all nine test files using that pattern, and raises vite.config.ts's global testTimeout from 15000 to 20000 to keep headroom above it.
This commit is contained in:
@@ -16,7 +16,7 @@ beforeEach(() => {
|
|||||||
async function openDialog() {
|
async function openDialog() {
|
||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/cms');
|
renderApp('/cms');
|
||||||
await screen.findByTestId('cms-add-button', {}, { timeout: 5000 });
|
await screen.findByTestId('cms-add-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(screen.getByTestId('cms-add-button'));
|
await userEvent.click(screen.getByTestId('cms-add-button'));
|
||||||
expect(screen.getByTestId('add-cms-name')).toBeInTheDocument();
|
expect(screen.getByTestId('add-cms-name')).toBeInTheDocument();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ beforeEach(() => {
|
|||||||
async function openSetStatusDialog() {
|
async function openSetStatusDialog() {
|
||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/cms');
|
renderApp('/cms');
|
||||||
const triggers = await screen.findAllByTestId('cms-instance-actions-trigger', {}, { timeout: 5000 });
|
const triggers = await screen.findAllByTestId('cms-instance-actions-trigger', {}, { timeout: 10000 });
|
||||||
await userEvent.click(triggers[0]);
|
await userEvent.click(triggers[0]);
|
||||||
await userEvent.click(await screen.findByTestId('cms-instance-set-status'));
|
await userEvent.click(await screen.findByTestId('cms-instance-set-status'));
|
||||||
expect(screen.getByTestId('set-status-select')).toBeInTheDocument();
|
expect(screen.getByTestId('set-status-select')).toBeInTheDocument();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ beforeEach(() => {
|
|||||||
async function openDialog() {
|
async function openDialog() {
|
||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/users');
|
renderApp('/users');
|
||||||
await screen.findByTestId('users-invite-button', {}, { timeout: 5000 });
|
await screen.findByTestId('users-invite-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(screen.getByTestId('users-invite-button'));
|
await userEvent.click(screen.getByTestId('users-invite-button'));
|
||||||
expect(screen.getByTestId('invite-dialog-email')).toBeInTheDocument();
|
expect(screen.getByTestId('invite-dialog-email')).toBeInTheDocument();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,21 +12,21 @@ describe('AccessDeniedPage', () => {
|
|||||||
it('renders the 403 title and message', async () => {
|
it('renders the 403 title and message', async () => {
|
||||||
renderApp('/403');
|
renderApp('/403');
|
||||||
|
|
||||||
expect(await screen.findByTestId('access-denied-title', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('access-denied-title', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('access-denied-message')).toBeInTheDocument();
|
expect(screen.getByTestId('access-denied-message')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the back to dashboard button', async () => {
|
it('renders the back to dashboard button', async () => {
|
||||||
renderApp('/403');
|
renderApp('/403');
|
||||||
|
|
||||||
expect(await screen.findByTestId('access-denied-back-button', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('access-denied-back-button', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates to login when back button is clicked as guest', async () => {
|
it('navigates to login when back button is clicked as guest', async () => {
|
||||||
mockGuest();
|
mockGuest();
|
||||||
renderApp('/403');
|
renderApp('/403');
|
||||||
|
|
||||||
const button = await screen.findByTestId('access-denied-back-button', {}, { timeout: 5000 });
|
const button = await screen.findByTestId('access-denied-back-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(button);
|
await userEvent.click(button);
|
||||||
|
|
||||||
expect(await screen.findByTestId('login-form-submit-button')).toBeInTheDocument();
|
expect(await screen.findByTestId('login-form-submit-button')).toBeInTheDocument();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ describe('CmsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/cms');
|
renderApp('/cms');
|
||||||
|
|
||||||
expect(await screen.findByTestId('cms-title', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('cms-title', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('cms-add-button')).toBeInTheDocument();
|
expect(screen.getByTestId('cms-add-button')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ describe('CmsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/cms');
|
renderApp('/cms');
|
||||||
|
|
||||||
const rows = await screen.findAllByTestId('cms-instance-row', {}, { timeout: 5000 });
|
const rows = await screen.findAllByTestId('cms-instance-row', {}, { timeout: 10000 });
|
||||||
expect(rows.length).toBe(2);
|
expect(rows.length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ describe('CmsPage', () => {
|
|||||||
server.use(http.get(CMS_URL, () => HttpResponse.json([])));
|
server.use(http.get(CMS_URL, () => HttpResponse.json([])));
|
||||||
renderApp('/cms');
|
renderApp('/cms');
|
||||||
|
|
||||||
expect(await screen.findByTestId('cms-empty-state', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('cms-empty-state', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('cms-empty-add-button')).toBeInTheDocument();
|
expect(screen.getByTestId('cms-empty-add-button')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ describe('CmsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/cms');
|
renderApp('/cms');
|
||||||
|
|
||||||
await screen.findByTestId('cms-add-button', {}, { timeout: 5000 });
|
await screen.findByTestId('cms-add-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(screen.getByTestId('cms-add-button'));
|
await userEvent.click(screen.getByTestId('cms-add-button'));
|
||||||
|
|
||||||
expect(await screen.findByTestId('add-cms-name')).toBeInTheDocument();
|
expect(await screen.findByTestId('add-cms-name')).toBeInTheDocument();
|
||||||
@@ -55,7 +55,7 @@ describe('CmsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/cms');
|
renderApp('/cms');
|
||||||
|
|
||||||
await screen.findByTestId('cms-add-button', {}, { timeout: 5000 });
|
await screen.findByTestId('cms-add-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(screen.getByTestId('cms-add-button'));
|
await userEvent.click(screen.getByTestId('cms-add-button'));
|
||||||
|
|
||||||
await userEvent.type(screen.getByTestId('add-cms-name'), 'New CMS');
|
await userEvent.type(screen.getByTestId('add-cms-name'), 'New CMS');
|
||||||
@@ -63,7 +63,7 @@ describe('CmsPage', () => {
|
|||||||
await userEvent.type(screen.getByTestId('add-cms-apikey-input'), 'secret-key');
|
await userEvent.type(screen.getByTestId('add-cms-apikey-input'), 'secret-key');
|
||||||
await userEvent.click(screen.getByTestId('add-cms-submit'));
|
await userEvent.click(screen.getByTestId('add-cms-submit'));
|
||||||
|
|
||||||
const rows = await screen.findAllByTestId('cms-instance-row', {}, { timeout: 5000 });
|
const rows = await screen.findAllByTestId('cms-instance-row', {}, { timeout: 10000 });
|
||||||
expect(rows.length).toBe(3);
|
expect(rows.length).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -12,21 +12,21 @@ describe('NotFoundPage', () => {
|
|||||||
it('renders for an unknown route', async () => {
|
it('renders for an unknown route', async () => {
|
||||||
renderApp('/this-route-does-not-exist');
|
renderApp('/this-route-does-not-exist');
|
||||||
|
|
||||||
expect(await screen.findByTestId('not-found-title', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('not-found-title', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('not-found-message')).toBeInTheDocument();
|
expect(screen.getByTestId('not-found-message')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders the back to dashboard button', async () => {
|
it('renders the back to dashboard button', async () => {
|
||||||
renderApp('/some/nonexistent/path');
|
renderApp('/some/nonexistent/path');
|
||||||
|
|
||||||
expect(await screen.findByTestId('not-found-back-button', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('not-found-back-button', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('navigates to login when back button is clicked as guest', async () => {
|
it('navigates to login when back button is clicked as guest', async () => {
|
||||||
mockGuest();
|
mockGuest();
|
||||||
renderApp('/this-does-not-exist');
|
renderApp('/this-does-not-exist');
|
||||||
|
|
||||||
const button = await screen.findByTestId('not-found-back-button', {}, { timeout: 5000 });
|
const button = await screen.findByTestId('not-found-back-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(button);
|
await userEvent.click(button);
|
||||||
|
|
||||||
expect(await screen.findByTestId('login-form-submit-button')).toBeInTheDocument();
|
expect(await screen.findByTestId('login-form-submit-button')).toBeInTheDocument();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ describe('ProfilePage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/profile');
|
renderApp('/profile');
|
||||||
|
|
||||||
expect(await screen.findByTestId('profile-title', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('profile-title', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('profile-name-input')).toBeInTheDocument();
|
expect(screen.getByTestId('profile-name-input')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('profile-email-input')).toBeInTheDocument();
|
expect(screen.getByTestId('profile-email-input')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('profile-role-badge')).toBeInTheDocument();
|
expect(screen.getByTestId('profile-role-badge')).toBeInTheDocument();
|
||||||
@@ -61,7 +61,7 @@ describe('ProfilePage', () => {
|
|||||||
await userEvent.type(nameInput, 'New Name');
|
await userEvent.type(nameInput, 'New Name');
|
||||||
await userEvent.click(screen.getByTestId('profile-save-button'));
|
await userEvent.click(screen.getByTestId('profile-save-button'));
|
||||||
|
|
||||||
expect(await screen.findByText(/profile updated/i, {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByText(/profile updated/i, {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows validation error for invalid email', async () => {
|
it('shows validation error for invalid email', async () => {
|
||||||
|
|||||||
@@ -16,21 +16,21 @@ describe('SettingsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
expect(await screen.findByTestId('settings-title', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('settings-title', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows the current availability status badge', async () => {
|
it('shows the current availability status badge', async () => {
|
||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
expect(await screen.findByTestId('availability-badge', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('availability-badge', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders all three availability mode buttons', async () => {
|
it('renders all three availability mode buttons', async () => {
|
||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
await screen.findByTestId('availability-mode-selector', {}, { timeout: 5000 });
|
await screen.findByTestId('availability-mode-selector', {}, { timeout: 10000 });
|
||||||
expect(screen.getByTestId('mode-option-Available')).toBeInTheDocument();
|
expect(screen.getByTestId('mode-option-Available')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('mode-option-Maintenance')).toBeInTheDocument();
|
expect(screen.getByTestId('mode-option-Maintenance')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('mode-option-NotAvailable')).toBeInTheDocument();
|
expect(screen.getByTestId('mode-option-NotAvailable')).toBeInTheDocument();
|
||||||
@@ -40,7 +40,7 @@ describe('SettingsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
await screen.findByTestId('availability-mode-selector', {}, { timeout: 5000 });
|
await screen.findByTestId('availability-mode-selector', {}, { timeout: 10000 });
|
||||||
const maintenanceBtn = screen.getByTestId('mode-option-Maintenance');
|
const maintenanceBtn = screen.getByTestId('mode-option-Maintenance');
|
||||||
await userEvent.click(maintenanceBtn);
|
await userEvent.click(maintenanceBtn);
|
||||||
|
|
||||||
@@ -51,10 +51,10 @@ describe('SettingsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
await screen.findByTestId('availability-save-button', {}, { timeout: 5000 });
|
await screen.findByTestId('availability-save-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(screen.getByTestId('availability-save-button'));
|
await userEvent.click(screen.getByTestId('availability-save-button'));
|
||||||
|
|
||||||
expect(await screen.findByText(/availability updated/i, {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByText(/availability updated/i, {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows error toast when save fails', async () => {
|
it('shows error toast when save fails', async () => {
|
||||||
@@ -66,10 +66,10 @@ describe('SettingsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
await screen.findByTestId('availability-save-button', {}, { timeout: 5000 });
|
await screen.findByTestId('availability-save-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(screen.getByTestId('availability-save-button'));
|
await userEvent.click(screen.getByTestId('availability-save-button'));
|
||||||
|
|
||||||
expect(await screen.findByText(/something went wrong/i, {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByText(/something went wrong/i, {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('disables the availability controls and shows a banner when master-controlled', async () => {
|
it('disables the availability controls and shows a banner when master-controlled', async () => {
|
||||||
@@ -86,7 +86,7 @@ describe('SettingsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
expect(await screen.findByTestId('availability-master-controlled-banner', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('availability-master-controlled-banner', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('mode-option-Available')).toBeDisabled();
|
expect(screen.getByTestId('mode-option-Available')).toBeDisabled();
|
||||||
expect(screen.getByTestId('mode-option-Maintenance')).toBeDisabled();
|
expect(screen.getByTestId('mode-option-Maintenance')).toBeDisabled();
|
||||||
expect(screen.getByTestId('mode-option-NotAvailable')).toBeDisabled();
|
expect(screen.getByTestId('mode-option-NotAvailable')).toBeDisabled();
|
||||||
@@ -98,7 +98,7 @@ describe('SettingsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
await screen.findByTestId('availability-save-button', {}, { timeout: 5000 });
|
await screen.findByTestId('availability-save-button', {}, { timeout: 10000 });
|
||||||
expect(screen.queryByTestId('availability-master-controlled-banner')).not.toBeInTheDocument();
|
expect(screen.queryByTestId('availability-master-controlled-banner')).not.toBeInTheDocument();
|
||||||
expect(screen.getByTestId('availability-save-button')).not.toBeDisabled();
|
expect(screen.getByTestId('availability-save-button')).not.toBeDisabled();
|
||||||
});
|
});
|
||||||
@@ -112,17 +112,17 @@ describe('SettingsPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
await screen.findByTestId('availability-save-button', {}, { timeout: 5000 });
|
await screen.findByTestId('availability-save-button', {}, { timeout: 10000 });
|
||||||
await userEvent.click(screen.getByTestId('availability-save-button'));
|
await userEvent.click(screen.getByTestId('availability-save-button'));
|
||||||
|
|
||||||
expect(await screen.findByText(/master cms controls this status/i, {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByText(/master cms controls this status/i, {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders all placeholder sections', async () => {
|
it('renders all placeholder sections', async () => {
|
||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/settings');
|
renderApp('/settings');
|
||||||
|
|
||||||
await screen.findByTestId('settings-title', {}, { timeout: 5000 });
|
await screen.findByTestId('settings-title', {}, { timeout: 10000 });
|
||||||
expect(screen.getByTestId('placeholder-settings.modules.title')).toBeInTheDocument();
|
expect(screen.getByTestId('placeholder-settings.modules.title')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('placeholder-settings.systemConfig.title')).toBeInTheDocument();
|
expect(screen.getByTestId('placeholder-settings.systemConfig.title')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('placeholder-settings.branding.title')).toBeInTheDocument();
|
expect(screen.getByTestId('placeholder-settings.branding.title')).toBeInTheDocument();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ describe('UsersPage', () => {
|
|||||||
mockAuthenticated();
|
mockAuthenticated();
|
||||||
renderApp('/users');
|
renderApp('/users');
|
||||||
|
|
||||||
expect(await screen.findByTestId('users-page', {}, { timeout: 5000 })).toBeInTheDocument();
|
expect(await screen.findByTestId('users-page', {}, { timeout: 10000 })).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('users-invite-button')).toBeInTheDocument();
|
expect(screen.getByTestId('users-invite-button')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default defineConfig(({ command }) => ({
|
|||||||
globals: true,
|
globals: true,
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
setupFiles: ['./src/test/setup.ts'],
|
setupFiles: ['./src/test/setup.ts'],
|
||||||
testTimeout: 15000,
|
testTimeout: 20000,
|
||||||
css: true,
|
css: true,
|
||||||
coverage: {
|
coverage: {
|
||||||
provider: 'v8',
|
provider: 'v8',
|
||||||
|
|||||||
Reference in New Issue
Block a user