Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

front: fix allowances do not reset when changing the path #6823

Merged
merged 1 commit into from
Mar 15, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@
"warningMessages": {
"electrification": "Electrification",
"powerRestrictionInvalidCombination": "{{powerRestrictionCode}} is incompatible with electrification {{electrification}} of the path between {{begin}}m and {{end}}m",
"missingPowerRestriction": "Missing power restriction between {{begin}}m and {{end}}m. "
"missingPowerRestriction": "Missing power restriction between {{begin}}m and {{end}}m.",
"pathfindingChange": "Pathfinding changed",
"marginsAndPowerRestrictionsReset": "Margins and power restrictions have been reset."
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@
"warningMessages": {
"electrification": "Électrification",
"powerRestrictionInvalidCombination": "Code {{powerRestrictionCode}} incompatible avec l'électrification à {{electrification}} de l'itinéraire entre {{begin}}m et {{end}}m. ",
"missingPowerRestriction": "Restriction de puissance manquante entre {{begin}}m et {{end}}m. "
"missingPowerRestriction": "Restriction de puissance manquante entre {{begin}}m et {{end}}m.",
"pathfindingChange": "Changement de chemin",
"marginsAndPowerRestrictionsReset": "Les marges et les restrictions de puissance ont été réinitialisées."
}
}
32 changes: 27 additions & 5 deletions front/src/common/Pathfinding/Pathfinding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import type { PathResponse, PathfindingRequest, PathfindingStep } from 'common/a
import { osrdEditoastApi } from 'common/api/osrdEditoastApi';
import { Spinner } from 'common/Loaders';
import { useOsrdConfActions, useOsrdConfSelectors } from 'common/osrdContext';
import { setFailure } from 'reducers/main';
import { setFailure, setWarning } from 'reducers/main';
import { useAppDispatch } from 'store';
import { isEmptyArray } from 'utils/array';
import { castErrorToFailure } from 'utils/error';
import { conditionalStringConcat, formatKmValue } from 'utils/strings';
import type { ArrayElement } from 'utils/types';
Expand Down Expand Up @@ -245,7 +246,7 @@ export function getPathfindingQuery({
return null;
}

function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
const Pathfinding = ({ zoomToFeature, path }: PathfindingProps) => {
const { t } = useTranslation(['operationalStudies/manageTrainSchedule']);
const [pathfindingRequest, setPathfindingRequest] =
useState<ReturnType<typeof postPathfinding>>();
Expand All @@ -258,6 +259,8 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
getRollingStockID,
getPathfindingID,
getGeojson,
getPowerRestrictionRanges,
getAllowances,
} = useOsrdConfSelectors();
const infraID = useSelector(getInfraID, isEqual);
const origin = useSelector(getOrigin, isEqual);
Expand All @@ -266,6 +269,8 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
const rollingStockID = useSelector(getRollingStockID, isEqual);
const pathfindingID = useSelector(getPathfindingID, isEqual);
const geojson = useSelector(getGeojson, isEqual);
const powerRestrictions = useSelector(getPowerRestrictionRanges, isEqual);
const allowances = useSelector(getAllowances, isEqual);
const initializerArgs = {
pathfindingID,
geojson,
Expand All @@ -291,8 +296,14 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
);
const [reloadInfra] = osrdEditoastApi.usePostInfraByIdLoadMutation();

const { replaceVias, updateItinerary, updatePathfindingID, updateSuggeredVias } =
useOsrdConfActions();
const {
replaceVias,
updateItinerary,
updatePathfindingID,
updateSuggeredVias,
updatePowerRestrictionRanges,
updateAllowances,
} = useOsrdConfActions();

useEffect(() => {
if (reloadCount <= 5 && infra && infra.state === 'TRANSIENT_ERROR') {
Expand Down Expand Up @@ -415,6 +426,17 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
dispatch(updatePathfindingID(itineraryCreated.id));
if (zoom) zoomToFeature(bbox(itineraryCreated.geographic));
pathfindingDispatch({ type: 'PATHFINDING_FINISHED' });

if (!isEmptyArray(powerRestrictions) || !isEmptyArray(allowances)) {
dispatch(updatePowerRestrictionRanges([]));
dispatch(updateAllowances([]));
dispatch(
setWarning({
title: t('warningMessages.pathfindingChange'),
text: t('warningMessages.marginsAndPowerRestrictionsReset'),
})
);
}
})
.catch((e) => {
if (e.error) {
Expand Down Expand Up @@ -571,6 +593,6 @@ function Pathfinding({ zoomToFeature, path }: PathfindingProps) {
)}
</div>
);
}
};

export default Pathfinding;
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,13 @@ const RollingStockCardButtons = ({
const rollingStockComfort = useSelector(getRollingStockComfort);
const [comfort, setComfort] = useState('STANDARD');

const {
updatePathfindingID,
updatePowerRestrictionRanges,
updateRollingStockComfort,
updateRollingStockID,
} = useOsrdConfActions();
const { updatePathfindingID, updateRollingStockComfort, updateRollingStockID } =
useOsrdConfActions();

const selectRollingStock = () => {
setOpenedRollingStockCardId(undefined);
dispatch(updateRollingStockComfort(comfort as RollingStockComfortType));
dispatch(updateRollingStockID(id));
dispatch(updatePowerRestrictionRanges([]));
dispatch(updatePathfindingID(undefined));
closeModal();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ const testCommonConfReducers = (slice: OperationalStudiesConfSlice | StdcmConfSl
defaultStore.dispatch(slice.actions.updatePathfindingID(newPathfindingID));
const state = defaultStore.getState()[slice.name];
expect(state.pathfindingID).toBe(newPathfindingID);
expect(state.powerRestrictionRanges).toStrictEqual([]);
});

it('should handle updateTimetableID', () => {
Expand Down
1 change: 0 additions & 1 deletion front/src/reducers/osrdconf/osrdConfCommon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ export function buildCommonConfReducers<S extends OsrdConfState>(): CommonConfRe
},
updatePathfindingID(state: Draft<S>, action: PayloadAction<S['pathfindingID']>) {
state.pathfindingID = action.payload;
state.powerRestrictionRanges = [];
},
updateTimetableID(state: Draft<S>, action: PayloadAction<S['timetableID']>) {
state.timetableID = action.payload;
Expand Down
14 changes: 13 additions & 1 deletion front/src/utils/__tests__/array.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import { splitArrayByFirstLetter } from 'utils/array';
import { isEmptyArray, splitArrayByFirstLetter } from 'utils/array';

describe('isEmptyArray', () => {
it('should return true', () => {
const array: string[] = [];
expect(isEmptyArray(array)).toBe(true);
});

it('should return false', () => {
const array: string[] = ['a', 'b'];
expect(isEmptyArray(array)).toBe(false);
});
});

describe('splitArrayByFirstLetter', () => {
it('should return two empty arrays', () => {
Expand Down
2 changes: 2 additions & 0 deletions front/src/utils/array.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export const isFirstOrLastElement = <T>(array: T[], element: T) =>
array[0] === element || array[array.length - 1] === element;

export const isEmptyArray = <T>(array: T[]) => array.length === 0;

/**
* 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.
*/
Expand Down
20 changes: 10 additions & 10 deletions front/tests/005-operational-studies.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ test.describe('Testing if all mandatory elements simulation configuration are lo
await playwrightRollingstockModalPage.getRollingStockInfoComfort().textContent()
).toMatch(/ConfortSStandard/i);

// ***************** Test choice Origin/Destination *****************
await scenarioPage.openTabByDataId('tab-pathfinding');
const itinerary = scenarioPage.getItineraryModule;
await expect(itinerary).toBeVisible();

await scenarioPage.getPathfindingByTriGramSearch('MWS', 'NES');

await scenarioPage.checkPathfindingDistance('33.950 km');

// TODO: move this test in his own file
// ***************** Test Composition Code *****************
await scenarioPage.openTabByDataId('tab-simulation-settings');
Expand All @@ -87,19 +96,10 @@ test.describe('Testing if all mandatory elements simulation configuration are lo
/Voyageurs - Automoteurs - E32C/i
);

// ***************** Test choice Origin/Destination *****************
await scenarioPage.openTabByDataId('tab-pathfinding');
const itinerary = scenarioPage.getItineraryModule;
await expect(itinerary).toBeVisible();

await scenarioPage.getPathfindingByTriGramSearch('MWS', 'NES');

await scenarioPage.checkPathfindingDistance('33.950 km');

// ***************** Test Add Train Schedule *****************
await scenarioPage.addTrainSchedule();
await scenarioPage.page.waitForSelector('.dots-loader', { state: 'hidden' });
await scenarioPage.checkToastSNCFTitle();
await scenarioPage.checkTrainHasBeenAdded();
await scenarioPage.returnSimulationResult();
await scenarioPage.checkNumberOfTrains(Number(trainCount));
});
Expand Down
2 changes: 1 addition & 1 deletion front/tests/assets/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export default async function createCompleteScenario(
// ***************** Create train *****************
await scenarioPage.addTrainSchedule();
await scenarioPage.page.waitForSelector('.dots-loader', { state: 'hidden' });
await scenarioPage.checkToastSNCFTitle();
await scenarioPage.checkTrainHasBeenAdded();
await scenarioPage.returnSimulationResult();
}

Expand Down
13 changes: 12 additions & 1 deletion front/tests/pages/base-page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Locator, Page } from '@playwright/test';
import { expect, type Locator, type Page } from '@playwright/test';

export default class BasePage {
public page: Page;
Expand All @@ -7,11 +7,14 @@ export default class BasePage {

protected viteOverlay: Locator;

readonly lastToast: Locator;

constructor(page: Page) {
this.page = page;

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

// Completly remove VITE button & sign
Expand All @@ -24,4 +27,12 @@ export default class BasePage {
async backToHomePage() {
await this.backToHomePageButton.click();
}

async checkLastToastBody(text: string | RegExp) {
await expect(this.lastToast.locator('.toast-body')).toHaveText(text);
}

async checkLastToastTitle(text: string | RegExp) {
await expect(this.lastToast.getByTestId('toast-SNCF-title')).toHaveText(text);
}
}
23 changes: 10 additions & 13 deletions front/tests/pages/scenario-page-model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { type Locator, type Page, expect } from '@playwright/test';

class PlaywrightScenarioPage {
import BasePage from './base-page';
import manageTrainScheduleTranslation from '../../public/locales/fr/operationalStudies/manageTrainSchedule.json';

const trainAddedTranslation = manageTrainScheduleTranslation.trainAdded;

class PlaywrightScenarioPage extends BasePage {
readonly getScenarioUpdateBtn: Locator;

readonly getScenarioDeleteConfirmBtn: Locator;
Expand Down Expand Up @@ -57,10 +62,6 @@ class PlaywrightScenarioPage {

readonly getReturnSimulationResultBtn: Locator;

readonly getToastSNCF: Locator;

readonly getToastSNCFTitle: Locator;

readonly getPathfindingState: Locator;

readonly getSearchByTrigramButton: Locator;
Expand Down Expand Up @@ -92,6 +93,8 @@ class PlaywrightScenarioPage {
readonly getSuccessBtn: Locator;

constructor(readonly page: Page) {
super(page);

this.getRollingStockSelector = page.getByTestId('rollingstock-selector-empty');
this.getScenarioUpdateBtn = page.getByTitle('Modifier le scénario');
this.getScenarioDeleteConfirmBtn = page
Expand Down Expand Up @@ -134,8 +137,6 @@ class PlaywrightScenarioPage {
.locator('.scenario-timetable-trains')
.locator('.scenario-timetable-train');
this.getReturnSimulationResultBtn = page.getByTestId('return-simulation-result');
this.getToastSNCF = page.getByTestId('toast-SNCF');
this.getToastSNCFTitle = this.getToastSNCF.getByTestId('toast-SNCF-title');
this.getPathfindingState = page.locator('.pathfinding-state-main-container');
this.getTimetableList = page.locator('.scenario-timetable-train-with-right-bar');
this.getTrainEditBtn = page.locator('.scenario-timetable-train-buttons-update');
Expand Down Expand Up @@ -241,12 +242,8 @@ class PlaywrightScenarioPage {
await this.getReturnSimulationResultBtn.click();
}

async checkToastSNCFTitle() {
await expect(this.getToastSNCFTitle).not.toBeEmpty();
}

async checkToastSNCFBody(text: string | RegExp) {
await expect(this.getToastSNCF.locator('.toast-body')).toHaveText(text);
async checkTrainHasBeenAdded() {
this.checkLastToastTitle(trainAddedTranslation);
}

getBtnByName(name: string | RegExp) {
Expand Down
Loading