Skip to content

Commit 6b7faf0

Browse files
committed
front: reduce and remove unnecessary timeouts for e2e tests
Signed-off-by: maymanaf <med.aymen.naf@gmail.com>
1 parent 7daea74 commit 6b7faf0

17 files changed

+114
-122
lines changed

front/playwright.config.ts

+10-8
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,33 @@ export default defineConfig({
1212
testDir: './tests',
1313

1414
/* Maximum time one test can run for. */
15-
timeout: process.env.CI ? 90 * 1000 : 180 * 1000, // 90 seconds in CI, otherwise 180 seconds
15+
timeout: 90_000,
1616
expect: {
1717
toHaveScreenshot: { maxDiffPixelRatio: 0.02 },
1818
/**
1919
* Maximum time expect() should wait for the condition to be met.
2020
*/
21-
timeout: process.env.CI ? 10 * 1000 : 30 * 1000, // 10 seconds in CI, otherwise 30 seconds
21+
timeout: 10_000,
2222
},
2323

2424
/* Run tests in files in parallel */
2525
fullyParallel: true,
2626
/*
2727
* Limit parallelism in CI based on CPU capacity,
2828
* running 50% of the available workers when in CI.
29-
* Otherwise, run tests with a single worker.
29+
* Otherwise, run tests with 2 workers.
3030
*/
31-
workers: process.env.CI ? '50%' : 1,
31+
workers: process.env.CI ? '50%' : 2,
3232
/* Fail the build on CI if you accidentally left test.only in the source code. */
3333
forbidOnly: !!process.env.CI,
34-
/* Retry up to 2 times on CI, and 1 time otherwise */
35-
retries: process.env.CI ? 2 : 1,
34+
/* Retry 1 time if a test fail */
35+
retries: 1,
3636
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
3737
use: {
38-
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
39-
actionTimeout: 0,
38+
/* Maximum time each navigation action can take */
39+
navigationTimeout: 30_000,
40+
/* Maximum time each action such as `click()` can take */
41+
actionTimeout: 15_000,
4042
/* Base URL to use in actions like `await page.goto('/')`. */
4143
baseURL: process.env.BASE_URL || 'http://localhost:4000',
4244

front/tests/003-study-management.spec.ts

+2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ test.describe('Validate the Study creation workflow', () => {
1616
let studyPage: StudyPage;
1717
let project: Project;
1818
let study: Study;
19+
1920
test.beforeAll(' Retrieve a project', async () => {
2021
project = await getProject();
2122
});
23+
2224
test.beforeEach(async ({ page }) => {
2325
studyPage = new StudyPage(page);
2426
});

front/tests/006-stdcm.spec.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@ import { handleAndVerifyInput, waitForInfraStateToBeCached } from './utils';
77
import { getInfra, setTowedRollingStock } from './utils/api-setup';
88
import type { ConsistFields } from './utils/types';
99

10-
test.use({
11-
launchOptions: {
12-
slowMo: 500, // Give the interface time to update between actions
13-
},
14-
});
15-
1610
test.describe('Verify stdcm simulation page', () => {
1711
test.slow(); // Mark test as slow due to multiple steps
1812
test.use({ viewport: { width: 1920, height: 1080 } });
@@ -54,7 +48,7 @@ test.describe('Verify stdcm simulation page', () => {
5448
// Retrieve OSRD language and navigate to STDCM page
5549
stdcmPage = new STDCMPage(page);
5650
await page.goto('/stdcm');
57-
await page.waitForLoadState('load', { timeout: 30 * 1000 });
51+
await page.waitForLoadState('networkidle');
5852
await stdcmPage.removeViteOverlay();
5953

6054
// Wait for infra to be in 'CACHED' state before proceeding

front/tests/008-train-schedule.spec.ts

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ test.describe('Verify train schedule elements and filters', () => {
2828
const NOT_HONORED_TRAINS = 3;
2929
const VALID_AND_HONORED_TRAINS = 14;
3030
const INVALID_AND_NOT_HONORED_TRAINS = 0;
31+
3132
test.beforeAll('Fetch project, study and scenario with train schedule', async () => {
3233
project = await getProject(trainScheduleProjectName);
3334
study = await getStudy(project.id, trainScheduleStudyName);

front/tests/011-op-times-and-stops-tab.spec.ts

-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ test.describe('Times and Stops Tab Verification', () => {
9393

9494
// Setup train configuration and schedule
9595
await operationalStudiesPage.clickOnAddTrainButton();
96-
await page.waitForTimeout(500); // Wait for any async actions to complete
9796
await operationalStudiesPage.setTrainStartTime('11:22:40');
9897
await rollingStockPage.selectRollingStock(dualModeRollingStockName);
9998
await operationalStudiesPage.setTrainScheduleName('Train-name-e2e-test');

front/tests/012-op-simulation-settings-tab.spec.ts

+4-7
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ test.describe('Simulation Settings Tab Verification', () => {
7171
let infra: Infra;
7272

7373
type TranslationKeys = keyof typeof enTranslations;
74-
let stabilityTimeout: number;
7574

7675
// Define CellData interface for table cell data
7776
interface CellData {
@@ -131,10 +130,10 @@ test.describe('Simulation Settings Tab Verification', () => {
131130
await waitForInfraStateToBeCached(infra.id);
132131
// Add a new train and set its properties
133132
await operationalStudiesPage.clickOnAddTrainButton();
134-
await operationalStudiesPage.setTrainStartTime('11:22:40');
135-
await rollingStockPage.selectRollingStock(improbableRollingStockName);
136-
await page.waitForTimeout(stabilityTimeout);
137133
await operationalStudiesPage.setTrainScheduleName('Train-name-e2e-test');
134+
await rollingStockPage.selectRollingStock(improbableRollingStockName);
135+
await operationalStudiesPage.setTrainStartTime('11:22:40');
136+
138137
// Perform pathfinding
139138
await operationalStudiesPage.clickOnRouteTab();
140139
await routePage.performPathfindingByTrigram('WS', 'SES', 'MWS');
@@ -143,6 +142,7 @@ test.describe('Simulation Settings Tab Verification', () => {
143142
await scrollContainer(page, '.time-stops-datasheet .dsg-container');
144143
}
145144
);
145+
146146
test.afterEach('Delete the created scenario', async () => {
147147
await deleteScenario(project.id, study.id, scenario.name);
148148
});
@@ -198,7 +198,6 @@ test.describe('Simulation Settings Tab Verification', () => {
198198
await operationalStudiesPage.clickOnSimulationSettingsTab();
199199
await opSimulationSettingsPage.deactivateElectricalProfile();
200200
await opTimetablePage.clickOnEditTrainSchedule();
201-
await page.waitForTimeout(stabilityTimeout); // Waiting for the timetable to update due to a slight latency
202201
await opTimetablePage.getTrainArrivalTime('11:52');
203202
await opTimetablePage.clickOnScenarioCollapseButton();
204203
await opOutputTablePage.verifyTimesStopsDataSheetVisibility();
@@ -266,7 +265,6 @@ test.describe('Simulation Settings Tab Verification', () => {
266265
await operationalStudiesPage.clickOnSimulationSettingsTab();
267266
await opSimulationSettingsPage.selectCodeCompoOption('__PLACEHOLDER__');
268267
await opTimetablePage.clickOnEditTrainSchedule();
269-
await page.waitForTimeout(stabilityTimeout);
270268
await opTimetablePage.getTrainArrivalTime('11:52');
271269
await opTimetablePage.clickOnScenarioCollapseButton();
272270
await opOutputTablePage.verifyTimesStopsDataSheetVisibility();
@@ -340,7 +338,6 @@ test.describe('Simulation Settings Tab Verification', () => {
340338
await operationalStudiesPage.clickOnSimulationSettingsTab();
341339
await opSimulationSettingsPage.activateMarecoMargin();
342340
await opTimetablePage.clickOnEditTrainSchedule();
343-
await page.waitForTimeout(stabilityTimeout);
344341
await opTimetablePage.getTrainArrivalTime('11:54');
345342
await opTimetablePage.clickOnScenarioCollapseButton();
346343
await opOutputTablePage.verifyTimesStopsDataSheetVisibility();

front/tests/013-stdcm-simulation-sheet.spec.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@ import { getInfra } from './utils/api-setup';
1313
import { findFirstPdf, verifySimulationContent } from './utils/simulationSheet';
1414
import type { ConsistFields, Simulation } from './utils/types';
1515

16-
test.use({
17-
launchOptions: {
18-
slowMo: 500, // Give the interface time to update between actions
19-
},
20-
});
21-
2216
test.describe('Verify stdcm simulation page', () => {
2317
test.describe.configure({ mode: 'serial' }); // Configure this block to run serially
2418
test.slow(); // Mark test as slow due to multiple steps
@@ -48,7 +42,7 @@ test.describe('Verify stdcm simulation page', () => {
4842
// Retrieve OSRD language and navigate to STDCM page
4943
stdcmPage = new STDCMPage(page);
5044
await page.goto('/stdcm');
51-
await page.waitForLoadState('domcontentloaded', { timeout: 30_000 });
45+
await page.waitForLoadState('networkidle');
5246
await stdcmPage.removeViteOverlay();
5347

5448
// Wait for infra to be in 'CACHED' state before proceeding

front/tests/assets/timeout-const.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const LOAD_PAGE_TIMEOUT = 30_000;
2+
export const SIMULATION_RESULT_TIMEOUT = 30_000;
3+
export const STDCM_SIMULATION_TIMEOUT = 30_000;
4+
export const EXPLICIT_UI_STABILITY_TIMEOUT = 1_000;

front/tests/pages/op-input-table-page-model.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class OperationalStudiesInputTablePage {
6161
.first();
6262
await rowLocator.waitFor({ state: 'attached' });
6363
const cell = rowLocator.locator('.dsg-cell').nth(columnIndex);
64-
await cell.waitFor({ state: 'visible', timeout: 5000 });
64+
await cell.waitFor();
6565
await cell.dblclick();
6666

6767
// Fill the input field based on the presence of a placeholder
@@ -107,7 +107,7 @@ class OperationalStudiesInputTablePage {
107107

108108
for (let rowIndex = 1; rowIndex < rowCount; rowIndex += 1) {
109109
const rowCells = this.tableRows.nth(rowIndex).locator('.dsg-cell .dsg-input');
110-
await rowCells.first().waitFor({ state: 'visible', timeout: 5000 });
110+
await rowCells.first().waitFor();
111111
const rowValues = await rowCells.evaluateAll((cells) =>
112112
cells.map((cell) => cell.getAttribute('value'))
113113
);

front/tests/pages/op-output-table-page-model.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class OperationalStudiesOutputTablePage extends OperationalStudiesTimetablePage
4747
// Iterate through each active row and extract data based on header mappings
4848
for (let rowIndex = 1; rowIndex < rowCount; rowIndex += 1) {
4949
const row = this.tableRows.nth(rowIndex);
50-
await row.waitFor({ state: 'visible' });
50+
await row.waitFor();
5151

5252
// Extract cells from the current row
5353
const cells = row.locator('.dsg-cell.dsg-cell-disabled');
@@ -144,11 +144,10 @@ class OperationalStudiesOutputTablePage extends OperationalStudiesTimetablePage
144144
expect(normalizedActualData).toEqual(normalizedExpectedData);
145145
}
146146

147-
// Wait for the Times and Stops simulation data sheet to be fully loaded with a specified timeout (default: 60 seconds)
148-
async verifyTimesStopsDataSheetVisibility(timeout = 60 * 1000): Promise<void> {
149-
await this.timesStopsDataSheet.waitFor({ state: 'visible', timeout });
150-
await this.page.waitForTimeout(1000); // Short delay for stabilization
151-
await this.timesStopsDataSheet.scrollIntoViewIfNeeded({ timeout });
147+
// Wait for the Times and Stops simulation data sheet to be fully loaded
148+
async verifyTimesStopsDataSheetVisibility(): Promise<void> {
149+
await this.timesStopsDataSheet.waitFor({ timeout: LOAD_PAGE_TIMEOUT });
150+
await this.timesStopsDataSheet.scrollIntoViewIfNeeded();
152151
}
153152
}
154153

front/tests/pages/op-route-page-model.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { expect, type Locator, type Page } from '@playwright/test';
22

33
import enTranslations from '../../public/locales/en/operationalStudies/manageTrainSchedule.json';
44
import frTranslations from '../../public/locales/fr/operationalStudies/manageTrainSchedule.json';
5-
import { clickWithDelay } from '../utils';
65

76
class RoutePage {
87
readonly page: Page;
@@ -51,6 +50,8 @@ class RoutePage {
5150

5251
readonly missingParamMessage: Locator;
5352

53+
readonly pathfindingLoader: Locator;
54+
5455
constructor(page: Page) {
5556
this.page = page;
5657

@@ -76,6 +77,7 @@ class RoutePage {
7677
this.viaModal = page.locator('.manage-vias-modal');
7778
this.closeViaModalButton = page.getByLabel('Close');
7879
this.missingParamMessage = page.getByTestId('missing-params-info');
80+
this.pathfindingLoader = page.locator('.dots-loader');
7981
}
8082

8183
// Get the name locator of a waypoint suggestion.
@@ -192,7 +194,7 @@ class RoutePage {
192194
const expectedDestinationTrigram =
193195
await this.getDestinationLocatorByTrigram(destinationTrigram).innerText();
194196
await this.clickSearchByTrigramSubmitButton();
195-
await this.page.waitForSelector('.dots-loader', { state: 'hidden' });
197+
await this.pathfindingLoader.waitFor({ state: 'hidden' });
196198
await expect(this.searchByTrigramContainer).not.toBeVisible();
197199
await expect(this.resultPathfindingDone).toBeVisible();
198200

@@ -209,29 +211,28 @@ class RoutePage {
209211
async clickOnDeleteOPButtons(selectedLanguage: string) {
210212
// Ensure all buttons are rendered and visible before proceeding
211213
await Promise.all([
212-
this.viaDeleteButton.waitFor({ state: 'visible' }),
213-
this.originDeleteButton.waitFor({ state: 'visible' }),
214-
this.destinationDeleteButton.waitFor({ state: 'visible' }),
214+
this.viaDeleteButton.waitFor(),
215+
this.originDeleteButton.waitFor(),
216+
this.destinationDeleteButton.waitFor(),
215217
]);
216218

217-
// Click the buttons sequentially with waits to ensure UI stability
218-
await clickWithDelay(this.viaDeleteButton);
219-
await clickWithDelay(this.originDeleteButton);
220-
await clickWithDelay(this.destinationDeleteButton);
219+
await this.viaDeleteButton.click();
220+
await this.originDeleteButton.click();
221+
await this.destinationDeleteButton.click();
221222
const translations = selectedLanguage === 'English' ? enTranslations : frTranslations;
222223
const expectedMessage = translations.pathfindingMissingParams.replace(
223224
': {{missingElements}}.',
224225
''
225226
);
226-
await this.missingParamMessage.waitFor({ state: 'visible' });
227+
await this.missingParamMessage.waitFor();
227228
const actualMessage = await this.missingParamMessage.innerText();
228229
expect(actualMessage).toContain(expectedMessage);
229230
}
230231

231232
// Click the add buttons for the specified via names.
232233
async clickOnViaAddButtons(...viaNames: string[]) {
233234
for (const viaName of viaNames) {
234-
await clickWithDelay(this.getAddButtonLocatorByViaName(viaName));
235+
await this.getAddButtonLocatorByViaName(viaName).click();
235236
await expect(this.getDeleteButtonLocatorByViaName(viaName)).toBeVisible();
236237
}
237238
}

0 commit comments

Comments
 (0)