Skip to content

Commit dfe8d14

Browse files
committed
front: fix allowances do not reset when changing the path
1 parent 8433802 commit dfe8d14

File tree

12 files changed

+83
-42
lines changed

12 files changed

+83
-42
lines changed

front/public/locales/en/operationalStudies/manageTrainSchedule.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@
116116
"warningMessages": {
117117
"electrification": "Electrification",
118118
"powerRestrictionInvalidCombination": "{{powerRestrictionCode}} is incompatible with electrification {{electrification}} of the path between {{begin}}m and {{end}}m",
119-
"missingPowerRestriction": "Missing power restriction between {{begin}}m and {{end}}m. "
119+
"missingPowerRestriction": "Missing power restriction between {{begin}}m and {{end}}m.",
120+
"pathfindingChange": "Pathfinding changed",
121+
"marginsAndPowerRestrictionsReset": "Margins and power restrictions have been reset."
120122
}
121123
}

front/public/locales/fr/operationalStudies/manageTrainSchedule.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@
116116
"warningMessages": {
117117
"electrification": "Électrification",
118118
"powerRestrictionInvalidCombination": "Code {{powerRestrictionCode}} incompatible avec l'électrification à {{electrification}} de l'itinéraire entre {{begin}}m et {{end}}m. ",
119-
"missingPowerRestriction": "Restriction de puissance manquante entre {{begin}}m et {{end}}m. "
119+
"missingPowerRestriction": "Restriction de puissance manquante entre {{begin}}m et {{end}}m.",
120+
"pathfindingChange": "Changement de chemin",
121+
"marginsAndPowerRestrictionsReset": "Les marges et les restrictions de puissance ont été réinitialisées."
120122
}
121123
}

front/src/common/Pathfinding/Pathfinding.tsx

+27-5
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ import type { PathResponse, PathfindingRequest, PathfindingStep } from 'common/a
1414
import { osrdEditoastApi } from 'common/api/osrdEditoastApi';
1515
import { Spinner } from 'common/Loaders';
1616
import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext';
17-
import { setFailure } from 'reducers/main';
17+
import { setFailure, setWarning } from 'reducers/main';
1818
import { useAppDispatch } from 'store';
19+
import { isEmptyArray } from 'utils/array';
1920
import { castErrorToFailure } from 'utils/error';
2021
import { conditionalStringConcat, formatKmValue } from 'utils/strings';
2122
import type { ArrayElement } from 'utils/types';
@@ -245,7 +246,7 @@ export function getPathfindingQuery({
245246
return null;
246247
}
247248

248-
function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
249+
const Pathfinding = ({ zoomToFeature, path }: PathfindingProps) => {
249250
const { t } = useTranslation(['operationalStudies/manageTrainSchedule']);
250251
const [pathfindingRequest, setPathfindingRequest] =
251252
useState<ReturnType<typeof postPathfinding>>();
@@ -258,6 +259,8 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
258259
getRollingStockID,
259260
getPathfindingID,
260261
getGeojson,
262+
getPowerRestrictionRanges,
263+
getAllowances,
261264
} = useOsrdConfSelectors();
262265
const infraID = useSelector(getInfraID, isEqual);
263266
const origin = useSelector(getOrigin, isEqual);
@@ -266,6 +269,8 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
266269
const rollingStockID = useSelector(getRollingStockID, isEqual);
267270
const pathfindingID = useSelector(getPathfindingID, isEqual);
268271
const geojson = useSelector(getGeojson, isEqual);
272+
const powerRestrictions = useSelector(getPowerRestrictionRanges, isEqual);
273+
const allowances = useSelector(getAllowances, isEqual);
269274
const initializerArgs = {
270275
pathfindingID,
271276
geojson,
@@ -291,8 +296,14 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
291296
);
292297
const [reloadInfra] = osrdEditoastApi.usePostInfraByIdLoadMutation();
293298

294-
const { replaceVias, updateItinerary, updatePathfindingID, updateSuggeredVias } =
295-
useOsrdConfActions();
299+
const {
300+
replaceVias,
301+
updateItinerary,
302+
updatePathfindingID,
303+
updateSuggeredVias,
304+
updatePowerRestrictionRanges,
305+
updateAllowances,
306+
} = useOsrdConfActions();
296307

297308
useEffect(() => {
298309
if (reloadCount <= 5 && infra && infra.state === 'TRANSIENT_ERROR') {
@@ -415,6 +426,17 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
415426
dispatch(updatePathfindingID(itineraryCreated.id));
416427
if (zoom) zoomToFeature(bbox(itineraryCreated.geographic));
417428
pathfindingDispatch({ type: 'PATHFINDING_FINISHED' });
429+
430+
if (!isEmptyArray(powerRestrictions) || !isEmptyArray(allowances)) {
431+
dispatch(updatePowerRestrictionRanges([]));
432+
dispatch(updateAllowances([]));
433+
dispatch(
434+
setWarning({
435+
title: t('warningMessages.pathfindingChange'),
436+
text: t('warningMessages.marginsAndPowerRestrictionsReset'),
437+
})
438+
);
439+
}
418440
})
419441
.catch((e) => {
420442
if (e.error) {
@@ -571,6 +593,6 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
571593
)}
572594
</div>
573595
);
574-
}
596+
};
575597

576598
export default Pathfinding;

front/src/modules/rollingStock/components/RollingStockCard/RollingStockCardButtons.tsx

+2-7
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,13 @@ const RollingStockCardButtons = ({
3030
const rollingStockComfort = useSelector(getRollingStockComfort);
3131
const [comfort, setComfort] = useState('STANDARD');
3232

33-
const {
34-
updatePathfindingID,
35-
updatePowerRestrictionRanges,
36-
updateRollingStockComfort,
37-
updateRollingStockID,
38-
} = useOsrdConfActions();
33+
const { updatePathfindingID, updateRollingStockComfort, updateRollingStockID } =
34+
useOsrdConfActions();
3935

4036
const selectRollingStock = () => {
4137
setOpenedRollingStockCardId(undefined);
4238
dispatch(updateRollingStockComfort(comfort as RollingStockComfortType));
4339
dispatch(updateRollingStockID(id));
44-
dispatch(updatePowerRestrictionRanges([]));
4540
dispatch(updatePathfindingID(undefined));
4641
closeModal();
4742
};

front/src/reducers/osrdconf/osrdConfCommon/__tests__/utils.ts

-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ const testCommonConfReducers = (slice: OperationalStudiesConfSlice | StdcmConfSl
146146
defaultStore.dispatch(slice.actions.updatePathfindingID(newPathfindingID));
147147
const state = defaultStore.getState()[slice.name];
148148
expect(state.pathfindingID).toBe(newPathfindingID);
149-
expect(state.powerRestrictionRanges).toStrictEqual([]);
150149
});
151150

152151
it('should handle updateTimetableID', () => {

front/src/reducers/osrdconf/osrdConfCommon/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ export function buildCommonConfReducers<S extends OsrdConfState>(): CommonConfRe
137137
},
138138
updatePathfindingID(state: Draft<S>, action: PayloadAction<S['pathfindingID']>) {
139139
state.pathfindingID = action.payload;
140-
state.powerRestrictionRanges = [];
141140
},
142141
updateTimetableID(state: Draft<S>, action: PayloadAction<S['timetableID']>) {
143142
state.timetableID = action.payload;

front/src/utils/__tests__/array.spec.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
1-
import { splitArrayByFirstLetter } from 'utils/array';
1+
import { isEmptyArray, splitArrayByFirstLetter } from 'utils/array';
2+
3+
describe('isEmptyArray', () => {
4+
it('should return true', () => {
5+
const array: string[] = [];
6+
expect(isEmptyArray(array)).toBe(true);
7+
});
8+
9+
it('should return false', () => {
10+
const array: string[] = ['a', 'b'];
11+
expect(isEmptyArray(array)).toBe(false);
12+
});
13+
});
214

315
describe('splitArrayByFirstLetter', () => {
416
it('should return two empty arrays', () => {

front/src/utils/array.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
export const isFirstOrLastElement = <T>(array: T[], element: T) =>
22
array[0] === element || array[array.length - 1] === element;
33

4+
export const isEmptyArray = <T>(array: T[]) => array.length === 0;
5+
46
/**
57
* Take an array of strings, sort it and split it in two : one array of letter starting strings and one with digit or special characters starting strings.
68
*/

front/tests/005-operational-studies.spec.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ test.describe('Testing if all mandatory elements simulation configuration are lo
7474
await playwrightRollingstockModalPage.getRollingStockInfoComfort().textContent()
7575
).toMatch(/ConfortSStandard/i);
7676

77+
// ***************** Test choice Origin/Destination *****************
78+
await scenarioPage.openTabByDataId('tab-pathfinding');
79+
const itinerary = scenarioPage.getItineraryModule;
80+
await expect(itinerary).toBeVisible();
81+
82+
await scenarioPage.getPathfindingByTriGramSearch('MWS', 'NES');
83+
84+
await scenarioPage.checkPathfindingDistance('33.950 km');
85+
7786
// TODO: move this test in his own file
7887
// ***************** Test Composition Code *****************
7988
await scenarioPage.openTabByDataId('tab-simulation-settings');
@@ -87,19 +96,10 @@ test.describe('Testing if all mandatory elements simulation configuration are lo
8796
/Voyageurs - Automoteurs - E32C/i
8897
);
8998

90-
// ***************** Test choice Origin/Destination *****************
91-
await scenarioPage.openTabByDataId('tab-pathfinding');
92-
const itinerary = scenarioPage.getItineraryModule;
93-
await expect(itinerary).toBeVisible();
94-
95-
await scenarioPage.getPathfindingByTriGramSearch('MWS', 'NES');
96-
97-
await scenarioPage.checkPathfindingDistance('33.950 km');
98-
9999
// ***************** Test Add Train Schedule *****************
100100
await scenarioPage.addTrainSchedule();
101101
await scenarioPage.page.waitForSelector('.dots-loader', { state: 'hidden' });
102-
await scenarioPage.checkToastSNCFTitle();
102+
await scenarioPage.checkTrainHasBeenAdded();
103103
await scenarioPage.returnSimulationResult();
104104
await scenarioPage.checkNumberOfTrains(Number(trainCount));
105105
});

front/tests/assets/utils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export default async function createCompleteScenario(
136136
// ***************** Create train *****************
137137
await scenarioPage.addTrainSchedule();
138138
await scenarioPage.page.waitForSelector('.dots-loader', { state: 'hidden' });
139-
await scenarioPage.checkToastSNCFTitle();
139+
await scenarioPage.checkTrainHasBeenAdded();
140140
await scenarioPage.returnSimulationResult();
141141
}
142142

front/tests/pages/base-page.ts

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

33
export default class BasePage {
44
public page: Page;
@@ -7,11 +7,14 @@ export default class BasePage {
77

88
protected viteOverlay: Locator;
99

10+
readonly lastToast: Locator;
11+
1012
constructor(page: Page) {
1113
this.page = page;
1214

1315
this.backToHomePageButton = page.locator('.mastheader-logo');
1416
this.viteOverlay = page.locator('vite-plugin-checker-error-overlay');
17+
this.lastToast = page.getByTestId('toast-SNCF').last();
1518
}
1619

1720
// Completly remove VITE button & sign
@@ -24,4 +27,12 @@ export default class BasePage {
2427
async backToHomePage() {
2528
await this.backToHomePageButton.click();
2629
}
30+
31+
async checkLastToastBody(text: string | RegExp) {
32+
await expect(this.lastToast.locator('.toast-body')).toHaveText(text);
33+
}
34+
35+
async checkLastToastTitle(text: string | RegExp) {
36+
await expect(this.lastToast.getByTestId('toast-SNCF-title')).toHaveText(text);
37+
}
2738
}

front/tests/pages/scenario-page-model.ts

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

3-
class PlaywrightScenarioPage {
3+
import BasePage from './base-page';
4+
import manageTrainScheduleTranslation from '../../public/locales/fr/operationalStudies/manageTrainSchedule.json';
5+
6+
const trainAddedTranslation = manageTrainScheduleTranslation.trainAdded;
7+
8+
class PlaywrightScenarioPage extends BasePage {
49
readonly getScenarioUpdateBtn: Locator;
510

611
readonly getScenarioDeleteConfirmBtn: Locator;
@@ -57,10 +62,6 @@ class PlaywrightScenarioPage {
5762

5863
readonly getReturnSimulationResultBtn: Locator;
5964

60-
readonly getToastSNCF: Locator;
61-
62-
readonly getToastSNCFTitle: Locator;
63-
6465
readonly getPathfindingState: Locator;
6566

6667
readonly getSearchByTrigramButton: Locator;
@@ -92,6 +93,8 @@ class PlaywrightScenarioPage {
9293
readonly getSuccessBtn: Locator;
9394

9495
constructor(readonly page: Page) {
96+
super(page);
97+
9598
this.getRollingStockSelector = page.getByTestId('rollingstock-selector-empty');
9699
this.getScenarioUpdateBtn = page.getByTitle('Modifier le scénario');
97100
this.getScenarioDeleteConfirmBtn = page
@@ -134,8 +137,6 @@ class PlaywrightScenarioPage {
134137
.locator('.scenario-timetable-trains')
135138
.locator('.scenario-timetable-train');
136139
this.getReturnSimulationResultBtn = page.getByTestId('return-simulation-result');
137-
this.getToastSNCF = page.getByTestId('toast-SNCF');
138-
this.getToastSNCFTitle = this.getToastSNCF.getByTestId('toast-SNCF-title');
139140
this.getPathfindingState = page.locator('.pathfinding-state-main-container');
140141
this.getTimetableList = page.locator('.scenario-timetable-train-with-right-bar');
141142
this.getTrainEditBtn = page.locator('.scenario-timetable-train-buttons-update');
@@ -241,12 +242,8 @@ class PlaywrightScenarioPage {
241242
await this.getReturnSimulationResultBtn.click();
242243
}
243244

244-
async checkToastSNCFTitle() {
245-
await expect(this.getToastSNCFTitle).not.toBeEmpty();
246-
}
247-
248-
async checkToastSNCFBody(text: string | RegExp) {
249-
await expect(this.getToastSNCF.locator('.toast-body')).toHaveText(text);
245+
async checkTrainHasBeenAdded() {
246+
this.checkLastToastTitle(trainAddedTranslation);
250247
}
251248

252249
getBtnByName(name: string | RegExp) {

0 commit comments

Comments
 (0)