Skip to content

Commit 61e741f

Browse files
committed
front: add stdcm simulation sheet e2e test
Signed-off-by: maymanaf <med.aymen.naf@gmail.com>
1 parent 3bc6d02 commit 61e741f

6 files changed

+285
-1
lines changed

front/package-lock.json

+37
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

front/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"maplibre-gl": "^4.0.0",
7070
"openapi-typescript-codegen": "^0.29.0",
7171
"party-js": "^2.2.0",
72+
"pdf-parse": "^1.1.1",
7273
"prop-types": "^15.8.1",
7374
"rc-slider": "^11.1.6",
7475
"react": "^18.2.0",
@@ -112,6 +113,7 @@
112113
"@types/jest": "^29.5.14",
113114
"@types/lodash": "^4.17.13",
114115
"@types/node": "^22",
116+
"@types/pdf-parse": "^1.1.4",
115117
"@types/react": "^18.2.53",
116118
"@types/react-beautiful-dnd": "^13.1.8",
117119
"@types/react-dom": "^18.2.18",

front/playwright.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default defineConfig({
2828
* running 50% of the available workers when in CI.
2929
* Otherwise, run tests with a single worker.
3030
*/
31-
workers: process.env.CI ? '50%' : 1,
31+
workers: process.env.CI ? '50%' : 3,
3232
/* Fail the build on CI if you accidentally left test.only in the source code. */
3333
forbidOnly: !!process.env.CI,
3434
/* Retry up to 2 times on CI, and 1 time otherwise */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import fs from 'fs';
2+
3+
import pdfParse from 'pdf-parse';
4+
5+
import simulationSheetDetails from './assets/simulationSheet-const';
6+
import HomePage from './pages/home-page-model';
7+
import test, { logger } from './test-logger';
8+
import { findFirstPdf, verifySimulationContent, type Simulation } from './utils/simulationSheet';
9+
10+
let OSRDLanguage: string;
11+
12+
test.beforeEach(
13+
'Navigate to Times and Stops tab with rolling stock and route set',
14+
async ({ page }) => {
15+
const homePage = new HomePage(page);
16+
await homePage.goToHomePage();
17+
OSRDLanguage = await homePage.getOSRDLanguage();
18+
}
19+
);
20+
21+
test('Verify PDF content', async ({ browserName }) => {
22+
/**
23+
* Finds the first `.pdf` file in the specified directory.
24+
* @param directory The directory to search in.
25+
* @returns The path of the first `.pdf` file or `null` if not found.
26+
*/
27+
28+
const downloadDir = `./tests/stdcm-results/${browserName}`;
29+
const pdfFilePath = findFirstPdf(downloadDir);
30+
31+
if (!pdfFilePath) {
32+
throw new Error(`No PDF files found in directory: ${downloadDir}`);
33+
}
34+
35+
// Read and parse the PDF
36+
const pdfBuffer = fs.readFileSync(pdfFilePath);
37+
const pdfData = await pdfParse(pdfBuffer);
38+
39+
// Dynamically create the expected simulation based on language
40+
const expectedSimulation: Simulation = simulationSheetDetails(OSRDLanguage);
41+
42+
// Verify PDF content
43+
const pdfText = pdfData.text;
44+
const isCorrect = verifySimulationContent(pdfText, expectedSimulation);
45+
46+
logger.info(isCorrect ? 'Simulation data is correct!' : 'Mismatch in simulation data.');
47+
});
+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import enTranslations from '../../public/locales/en/stdcm-simulation-report-sheet.json';
2+
import frTranslations from '../../public/locales/fr/stdcm-simulation-report-sheet.json';
3+
import type { Simulation } from '../utils/simulationSheet';
4+
5+
const simulationSheetDetails = (selectedLanguage: string): Simulation => {
6+
const translations = selectedLanguage === 'English' ? enTranslations : frTranslations;
7+
8+
return {
9+
header: {
10+
toolDescription: translations.warningMessage,
11+
documentTitle: translations.stdcm,
12+
creationDetails: {
13+
number: 'n°1224-352-455',
14+
date: translations.formattedDate
15+
.replace('{{day}}', '24')
16+
.replace('{{month}}', '12')
17+
.replace('{{year}}', '2024')
18+
.replace('{{hours}}', '12')
19+
.replace('{{minutes}}', '53'),
20+
time: '12:53',
21+
},
22+
},
23+
responsiblePerson: {
24+
role: 'Super Fret',
25+
name: 'Jane Smith',
26+
phone: '01 23 45 67 89',
27+
email: 'john.doe@example.com',
28+
},
29+
applicationDate: translations.applicationDate,
30+
referenceTrack: translations.referencePath.replace('XXXXXX', '1224'),
31+
trainDetails: {
32+
compositionCode: translations.speedLimitByTag,
33+
towedMaterial: translations.towedMaterial,
34+
maxSpeed: translations.maxSpeed.replace('{{value}}', '180 km/h'),
35+
maxTonnage: translations.maxWeight.replace('{{value}}', '400 t'),
36+
referenceEngine: translations.referenceEngine,
37+
maxLength: translations.maxLength.replace('{{value}}', '300 m'),
38+
},
39+
requestedRoute: [
40+
{
41+
stopNumber: 1,
42+
station: 'North_West_station',
43+
type: 'BV',
44+
arrivalTime: '20:21',
45+
departureTime: '20:21',
46+
reason: translations.serviceStop,
47+
},
48+
{
49+
stopNumber: 2,
50+
station: 'Mid_West_station',
51+
type: 'BV',
52+
reason: translations.passageStop,
53+
},
54+
{
55+
stopNumber: 3,
56+
station: 'South_station',
57+
type: 'BV',
58+
arrivalTime: translations.asap,
59+
departureTime: translations.asap,
60+
reason: translations.serviceStop,
61+
},
62+
],
63+
simulationDetails: {
64+
referenceTrackNumber: translations.referencePath.replace('XXXXXX', 'YYYYYY'),
65+
viewSimulationLink: translations.viewSimulation,
66+
totalDistance: '51 km',
67+
simulationPath: [
68+
{
69+
stopNumber: 1,
70+
station: 'North_West_station',
71+
type: 'BV',
72+
arrivalTime: '20:21',
73+
tonnage: translations.weight.replace('{{value}}', '400 t'),
74+
},
75+
{
76+
stopNumber: 2,
77+
station: 'Mid_West_station',
78+
type: 'BV',
79+
departureTime: '20:41',
80+
},
81+
{
82+
stopNumber: 3,
83+
station: 'Mid_East_station',
84+
type: 'BV',
85+
departureTime: '20:46',
86+
},
87+
{
88+
stopNumber: 4,
89+
station: 'North_station',
90+
type: 'BV',
91+
departureTime: '20:52',
92+
},
93+
{
94+
stopNumber: 5,
95+
station: 'South_station',
96+
type: 'BV',
97+
departureTime: '20:56',
98+
},
99+
],
100+
disclaimer: translations.withoutWarranty,
101+
},
102+
};
103+
};
104+
export default simulationSheetDetails;

front/tests/utils/simulationSheet.ts

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
4+
export interface Simulation {
5+
header: {
6+
toolDescription: string;
7+
documentTitle: string;
8+
creationDetails: {
9+
number: string;
10+
date: string;
11+
time: string;
12+
};
13+
};
14+
responsiblePerson: {
15+
role: string;
16+
name: string;
17+
phone: string;
18+
email: string;
19+
};
20+
applicationDate: string;
21+
referenceTrack: string;
22+
trainDetails: {
23+
compositionCode: string;
24+
towedMaterial: string | null;
25+
maxSpeed: string;
26+
maxTonnage: string;
27+
referenceEngine: string | null;
28+
maxLength: string;
29+
};
30+
requestedRoute: Array<{
31+
stopNumber: number;
32+
station: string;
33+
type: string;
34+
arrivalTime?: string;
35+
departureTime?: string;
36+
reason?: string;
37+
}>;
38+
simulationDetails: {
39+
referenceTrackNumber: string;
40+
viewSimulationLink: string;
41+
totalDistance: string;
42+
simulationPath: Array<{
43+
stopNumber: number;
44+
station: string;
45+
type: string;
46+
arrivalTime?: string;
47+
passageTime?: string;
48+
departureTime?: string;
49+
tonnage?: string;
50+
referenceEngine?: string | null;
51+
signal?: string | null;
52+
crossedTrain?: string | null;
53+
}>;
54+
disclaimer: string;
55+
};
56+
}
57+
58+
export function findFirstPdf(directory: string): string | null {
59+
try {
60+
const files = fs.readdirSync(directory);
61+
const pdfFile = files.find((file) => file.endsWith('.pdf'));
62+
return pdfFile ? path.resolve(directory, pdfFile) : null;
63+
} catch (error) {
64+
console.error(`Error reading directory ${directory}:`, error);
65+
return null;
66+
}
67+
}
68+
69+
/**
70+
* Verifies the PDF content against the expected simulation.
71+
* @param pdfText The text extracted from the PDF.
72+
* @param expectedSimulation The expected simulation data.
73+
* @returns Whether the content matches the expected simulation.
74+
*/
75+
export function verifySimulationContent(pdfText: string, expectedSimulation: Simulation): boolean {
76+
const textChecks = [
77+
expectedSimulation.header.toolDescription,
78+
expectedSimulation.header.documentTitle,
79+
expectedSimulation.header.creationDetails.number,
80+
expectedSimulation.header.creationDetails.date,
81+
expectedSimulation.header.creationDetails.time,
82+
expectedSimulation.applicationDate,
83+
expectedSimulation.referenceTrack,
84+
expectedSimulation.trainDetails.compositionCode,
85+
expectedSimulation.trainDetails.maxSpeed,
86+
expectedSimulation.trainDetails.maxTonnage,
87+
expectedSimulation.trainDetails.maxLength,
88+
...expectedSimulation.requestedRoute.map((route) => route.station),
89+
...expectedSimulation.simulationDetails.simulationPath.map((p) => p.station),
90+
expectedSimulation.simulationDetails.disclaimer,
91+
];
92+
93+
return textChecks.every((check) => pdfText.includes(check));
94+
}

0 commit comments

Comments
 (0)