diff --git a/front/src/modules/rollingStock/components/RollingStockSelector/SearchRollingStock.tsx b/front/src/modules/rollingStock/components/RollingStockSelector/SearchRollingStock.tsx
index 8c988af148a..4f612fcaff8 100644
--- a/front/src/modules/rollingStock/components/RollingStockSelector/SearchRollingStock.tsx
+++ b/front/src/modules/rollingStock/components/RollingStockSelector/SearchRollingStock.tsx
@@ -114,7 +114,7 @@ const SearchRollingStock = ({
-
+
{filteredRollingStockList.length > 0
? `${filteredRollingStockList.length} ${t('resultsFound')}`
: t('noResultFound')}
diff --git a/front/tests/008-allowances.spec.ts b/front/tests/008-allowances.spec.ts
index 12449995bd1..3bba4106aec 100644
--- a/front/tests/008-allowances.spec.ts
+++ b/front/tests/008-allowances.spec.ts
@@ -1,7 +1,7 @@
import { test } from '@playwright/test';
import { v4 as uuidv4 } from 'uuid';
-import createCompleteScenario, { allowancesManagement } from './assets/utils';
+import createCompleteScenario, { allowancesManagement } from './assets/scenario-utlis';
import PlaywrightScenarioPage from './pages/scenario-page-model';
let scenarioName: string;
diff --git a/front/tests/009-rollingstock-editor.spec.ts b/front/tests/009-rollingstock-editor.spec.ts
index 8799aec2234..fd327231fc4 100644
--- a/front/tests/009-rollingstock-editor.spec.ts
+++ b/front/tests/009-rollingstock-editor.spec.ts
@@ -4,11 +4,13 @@ import path from 'path';
import { test, expect } from '@playwright/test';
import {
- findAndDeleteRollingStock,
+ findAndDeleteRollingStocks,
generateUniqueName,
verifyAndCheckInputById,
fillAndCheckInputById,
+ addRollingStock,
} from './assets/utils';
+import RollingStockSelectorPage from './pages/rolling-stock-selector-page';
import PlaywrightRollingstockEditorPage from './pages/rollingstock-editor-page-model';
// Correct path to load rolling stock details from JSON
@@ -16,7 +18,14 @@ const rollingstockDetailsPath = path.resolve(
__dirname,
'../tests/assets/rollingStock/rollingstockDetails.json'
);
+// Correct path to load electrical and themal rolling stock from JSON
+const rollingstockPath = path.resolve(
+ __dirname,
+ '../tests/assets/rollingStock/thermal-electric_rolling_stock.json'
+);
const rollingstockDetails = JSON.parse(fs.readFileSync(rollingstockDetailsPath, 'utf-8'));
+const rollingStockJson = JSON.parse(fs.readFileSync(rollingstockPath, 'utf8'));
+const thermalElectricRollingStockName = 'thermal-electric_rolling_stock';
test.describe('Rollingstock editor page', () => {
let uniqueRollingStockName: string;
@@ -29,16 +38,22 @@ test.describe('Rollingstock editor page', () => {
uniqueDeletedRollingStockName = await generateUniqueName('D_RSN');
// Check and delete the specified rolling stocks if they exist
- await findAndDeleteRollingStock(uniqueRollingStockName);
- await findAndDeleteRollingStock(uniqueUpdatedRollingStockName);
- await findAndDeleteRollingStock(uniqueDeletedRollingStockName);
+ await findAndDeleteRollingStocks([
+ uniqueRollingStockName,
+ uniqueUpdatedRollingStockName,
+ uniqueDeletedRollingStockName,
+ thermalElectricRollingStockName,
+ ]);
});
test.afterEach(async () => {
// Clean up by deleting the created or updated rolling stock
- await findAndDeleteRollingStock(uniqueRollingStockName);
- await findAndDeleteRollingStock(uniqueUpdatedRollingStockName);
- await findAndDeleteRollingStock(uniqueDeletedRollingStockName);
+ await findAndDeleteRollingStocks([
+ uniqueRollingStockName,
+ uniqueUpdatedRollingStockName,
+ uniqueDeletedRollingStockName,
+ thermalElectricRollingStockName,
+ ]);
});
test('should correctly create a new rolling stock', async ({ page }) => {
@@ -189,4 +204,92 @@ test.describe('Rollingstock editor page', () => {
rollingStockEditorPage.page.getByTestId(uniqueDeletedRollingStockName)
).toBeHidden();
});
+ test('should correctly filter a rolling stock', async ({ page }) => {
+ const rollingStockEditorPage = new PlaywrightRollingstockEditorPage(page);
+ const rollingStockSelectorPage = new RollingStockSelectorPage(page);
+ // Navigate to rolling stock editor page
+ await rollingStockEditorPage.navigateToPage();
+
+ // Extract and check the initial count of rolling stock
+ const initialRollingStockFoundNumber =
+ await rollingStockSelectorPage.getRollingStockSearchNumber();
+
+ // Perform a filtering action for electric rolling stock
+ await rollingStockSelectorPage.electricRollingStockFilter();
+
+ // Verify that filtering reduces the count and all the RS have electic icons
+ expect(await rollingStockSelectorPage.getElectricRollingStockIcons.count()).toEqual(
+ await rollingStockSelectorPage.getRollingStockSearchNumber()
+ );
+
+ // Clear electric filter
+ await rollingStockSelectorPage.electricRollingStockFilter();
+
+ // Perform a filtering action for thermal rolling stock
+ await rollingStockSelectorPage.thermalRollingStockFilter();
+
+ // Verify that filtering reduces the count and all the RS have thermal icons
+ expect(await rollingStockSelectorPage.getThermalRollingStockIcons.count()).toEqual(
+ await rollingStockSelectorPage.getRollingStockSearchNumber()
+ );
+
+ // Perform a filtering action for combined thermal-electric rolling stock
+ await rollingStockSelectorPage.electricRollingStockFilter();
+
+ // Verify that filtering reduces the count and all the RS have thermal and electric icons
+ expect(await rollingStockSelectorPage.getThermalElectricRollingStockIcons.count()).toEqual(
+ await rollingStockSelectorPage.getRollingStockSearchNumber()
+ );
+
+ // Clear filters
+ await rollingStockSelectorPage.electricRollingStockFilter();
+ await rollingStockSelectorPage.thermalRollingStockFilter();
+
+ // Verify that the count of rolling stock is back to the initial number
+ expect(await rollingStockSelectorPage.getRollingStockList.count()).toEqual(
+ initialRollingStockFoundNumber
+ );
+ });
+
+ test('should correctly search for a rolling stock', async ({ page }) => {
+ const rollingStockEditorPage = new PlaywrightRollingstockEditorPage(page);
+ const rollingStockSelectorPage = new RollingStockSelectorPage(page);
+ // Add a rolling stock via postAPI
+ await addRollingStock(thermalElectricRollingStockName, rollingStockJson);
+
+ // Navigate to rolling stock editor page
+ await rollingStockEditorPage.navigateToPage();
+
+ // Extract and check the initial count of rolling stock
+ const initialRollingStockFoundNumber =
+ await rollingStockSelectorPage.getRollingStockSearchNumber();
+
+ // Search for the specific rolling stock
+ await rollingStockEditorPage.searchRollingStock(thermalElectricRollingStockName);
+ expect(
+ rollingStockEditorPage.page.getByTestId(
+ `rollingstock-thermal-${thermalElectricRollingStockName}`
+ )
+ ).toBeDefined();
+
+ // Verify that the first rolling stock has the thermal and electric icon
+ await expect(rollingStockSelectorPage.getThermalRollingStockFirstIcon).toBeVisible();
+ await expect(rollingStockSelectorPage.getElectricRollingStockFirstIcon).toBeVisible();
+
+ // Clear the search
+ await rollingStockEditorPage.clearSearchRollingStock();
+
+ // Verify that the count of rolling stock is back to the initial number
+ expect(await rollingStockSelectorPage.getRollingStockList.count()).toEqual(
+ initialRollingStockFoundNumber
+ );
+ // Search for a non existing rolling stock
+ await rollingStockEditorPage.searchRollingStock(
+ `${thermalElectricRollingStockName}-no-results`
+ );
+
+ // Verify that the count of rolling stock is 0 (No results Found)
+ await expect(rollingStockSelectorPage.getNoRollingStockResult).toBeVisible();
+ expect(await rollingStockSelectorPage.getRollingStockSearchNumber()).toEqual(0);
+ });
});
diff --git a/front/tests/assets/rollingStock/thermal-electric_rolling_stock.json b/front/tests/assets/rollingStock/thermal-electric_rolling_stock.json
new file mode 100644
index 00000000000..33b21da0a70
--- /dev/null
+++ b/front/tests/assets/rollingStock/thermal-electric_rolling_stock.json
@@ -0,0 +1,447 @@
+{
+ "railjson_version": "3.2",
+ "name": "thermal-electric_rolling_stock",
+ "effort_curves": {
+ "modes": {
+ "25000V": {
+ "curves": [
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "25000V",
+ "power_restriction_code": "C1"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 450000.0, 445235.2941176471, 440470.5882352941, 435705.8823529412,
+ 430411.7647058823, 423264.70588235295, 416117.6470588235, 408970.5882352941,
+ 398484.1628959276, 383823.5294117647, 369162.89592760184, 348806.7226890756,
+ 328386.55462184874, 288330.8823529411, 210904.411764706, 192705.88235294115,
+ 186352.9411764706, 180000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "25000V",
+ "power_restriction_code": "C2"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 400000.0, 395764.705882353, 391529.4117647059, 387294.11764705885,
+ 382588.2352941177, 376235.29411764705, 369882.3529411765, 363529.4117647059,
+ 354208.1447963801, 341176.4705882353, 328144.7963800905, 310050.42016806727,
+ 291899.1596638655, 256294.11764705877, 187470.5882352942, 171294.11764705885,
+ 165647.05882352943, 160000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "22500V",
+ "power_restriction_code": "C1"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 405000.0, 400711.7647058824, 396423.5294117647, 392135.2941176471,
+ 387370.5882352941, 380938.2352941177, 374505.8823529412, 368073.5294117647,
+ 358635.74660633487, 345441.17647058825, 332246.6063348417, 313926.0504201681,
+ 295547.8991596639, 259497.794117647, 189813.9705882354, 173435.29411764705,
+ 167717.64705882355, 162000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "22500V",
+ "power_restriction_code": "C2"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 360000.0, 356188.2352941177, 352376.4705882353, 348564.705882353, 344329.4117647059,
+ 338611.7647058824, 332894.11764705885, 327176.4705882353, 318787.3303167421,
+ 307058.82352941175, 295330.3167420815, 279045.3781512605, 262709.243697479,
+ 230664.7058823529, 168723.52941176482, 154164.70588235295, 149082.35294117648,
+ 144000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "20000V",
+ "power_restriction_code": "C1"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 360000.0, 356188.2352941177, 352376.4705882353, 348564.70588235295,
+ 344329.4117647059, 338611.76470588235, 332894.11764705885, 327176.4705882353,
+ 318787.33031674207, 307058.8235294118, 295330.3167420815, 279045.37815126055,
+ 262709.24369747896, 230664.7058823529, 168723.5294117648, 154164.70588235295,
+ 149082.35294117648, 144000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "20000V",
+ "power_restriction_code": "C2"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 320000.0, 316611.7647058824, 313223.52941176476, 309835.2941176471,
+ 306070.58823529416, 300988.23529411765, 295905.8823529412, 290823.52941176476,
+ 283366.51583710406, 272941.17647058825, 262515.83710407245, 248040.33613445383,
+ 233519.32773109243, 205035.29411764705, 149976.4705882354, 137035.29411764708,
+ 132517.64705882355, 128000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": null,
+ "power_restriction_code": "C1"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 450000.0, 445235.2941176471, 440470.5882352941, 435705.8823529412,
+ 430411.7647058823, 423264.70588235295, 416117.6470588235, 408970.5882352941,
+ 398484.1628959276, 383823.5294117647, 369162.89592760184, 348806.7226890756,
+ 328386.55462184874, 288330.8823529411, 210904.411764706, 192705.88235294115,
+ 186352.9411764706, 180000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": null,
+ "power_restriction_code": "C2"
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 400000.0, 395764.705882353, 391529.4117647059, 387294.11764705885,
+ 382588.2352941177, 376235.29411764705, 369882.3529411765, 363529.4117647059,
+ 354208.1447963801, 341176.4705882353, 328144.7963800905, 310050.42016806727,
+ 291899.1596638655, 256294.11764705877, 187470.5882352942, 171294.11764705885,
+ 165647.05882352943, 160000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "25000V",
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 500000.0, 494705.8823529412, 489411.7647058823, 484117.6470588235,
+ 478235.29411764705, 470294.1176470588, 462352.9411764706, 454411.7647058823,
+ 442760.1809954751, 426470.5882352941, 410180.9954751131, 387563.025210084,
+ 364873.9495798319, 320367.64705882344, 234338.23529411777, 214117.64705882352,
+ 207058.82352941175, 200000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "22500V",
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 450000.0, 445235.2941176471, 440470.5882352941, 435705.8823529412,
+ 430411.7647058823, 423264.70588235295, 416117.6470588235, 408970.5882352941,
+ 398484.1628959276, 383823.5294117647, 369162.89592760184, 348806.7226890756,
+ 328386.55462184874, 288330.8823529411, 210904.411764706, 192705.88235294115,
+ 186352.9411764706, 180000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": "20000V",
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.294117647058823, 10.588235294117649, 15.882352941176473, 21.176470588235293,
+ 26.470588235294116, 31.764705882352946, 37.05882352941176, 42.35294117647059,
+ 47.64705882352941, 52.94117647058823, 58.23529411764706, 63.52941176470589,
+ 68.82352941176471, 74.11764705882352, 79.41176470588235, 84.70588235294117, 90.0
+ ],
+ "max_efforts": [
+ 400000.0, 395764.705882353, 391529.4117647059, 387294.11764705885,
+ 382588.2352941177, 376235.29411764705, 369882.3529411765, 363529.4117647059,
+ 354208.1447963801, 341176.4705882353, 328144.7963800905, 310050.42016806727,
+ 291899.1596638655, 256294.11764705877, 187470.5882352942, 171294.11764705885,
+ 165647.05882352943, 160000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": null,
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.277777777777778, 10.555555555555555, 15.833333333333332, 21.11111111111111,
+ 26.38888888888889, 31.666666666666664, 36.94444444444444, 42.22222222222222,
+ 47.77777777777778, 53.05555555555556, 58.33333333333333, 63.61111111111111,
+ 68.88888888888889, 74.16666666666667, 79.44444444444444, 84.72222222222221, 90.0
+ ],
+ "max_efforts": [
+ 500000.0, 494705.8823529412, 489411.7647058823, 484117.6470588235,
+ 478235.29411764705, 470294.1176470588, 462352.9411764706, 454411.7647058823,
+ 442760.1809954751, 426470.5882352941, 410180.9954751131, 387563.025210084,
+ 364873.9495798319, 320367.64705882344, 234338.23529411777, 214117.64705882352,
+ 207058.82352941175, 200000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "AC",
+ "electrical_profile_level": null,
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.277777777777778, 10.555555555555555, 15.833333333333332, 21.11111111111111,
+ 26.38888888888889, 31.666666666666664, 36.94444444444444, 42.22222222222222,
+ 47.77777777777778, 53.05555555555556, 58.33333333333333, 63.61111111111111,
+ 68.88888888888889, 74.16666666666667, 79.44444444444444, 84.72222222222221, 90.0
+ ],
+ "max_efforts": [
+ 510000.0, 504705.8823529412, 499411.7647058823, 494117.6470588235,
+ 488235.29411764705, 480294.1176470588, 472352.9411764706, 464411.7647058823,
+ 452760.1809954751, 436470.5882352941, 420180.9954751131, 397563.025210084,
+ 374873.9495798319, 330367.64705882344, 244338.23529411777, 224117.64705882352,
+ 217058.82352941175, 210000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "HEATING",
+ "electrical_profile_level": null,
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 5.277777777777778, 10.555555555555555, 15.833333333333332, 21.11111111111111,
+ 26.38888888888889, 31.666666666666664, 36.94444444444444, 42.22222222222222,
+ 47.77777777777778, 53.05555555555556, 58.33333333333333, 63.61111111111111,
+ 68.88888888888889, 74.16666666666667, 79.44444444444444, 84.72222222222221, 90.0
+ ],
+ "max_efforts": [
+ 490000.0, 484705.8823529412, 469411.7647058823, 474117.6470588235,
+ 468235.29411764705, 460294.1176470588, 452352.9411764706, 444411.7647058823,
+ 452760.1809954751, 416470.5882352941, 400180.9954751131, 377563.025210084,
+ 354873.9495798319, 310367.64705882344, 224338.23529411777, 204117.64705882352,
+ 197058.82352941175, 199000.0
+ ]
+ }
+ }
+ ],
+ "default_curve": {
+ "speeds": [
+ 0.0, 5.277777777777778, 10.555555555555555, 15.833333333333332, 21.11111111111111,
+ 26.38888888888889, 31.666666666666664, 36.94444444444444, 42.22222222222222,
+ 47.77777777777778, 53.05555555555556, 58.33333333333333, 63.61111111111111,
+ 68.88888888888889, 74.16666666666667, 79.44444444444444, 84.72222222222221, 90.0
+ ],
+ "max_efforts": [
+ 500000.0, 494705.8823529412, 489411.7647058823, 484117.6470588235, 478235.29411764705,
+ 470294.1176470588, 462352.9411764706, 454411.7647058823, 442760.1809954751,
+ 426470.5882352941, 410180.9954751131, 387563.025210084, 364873.9495798319,
+ 320367.64705882344, 234338.23529411777, 214117.64705882352, 207058.82352941175, 200000.0
+ ]
+ },
+ "is_electric": true
+ },
+ "thermal": {
+ "curves": [
+ {
+ "cond": {
+ "comfort": "STANDARD",
+ "electrical_profile_level": null,
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 2.7777777777777777, 5.555555555555555, 8.333333333333334, 11.11111111111111,
+ 13.88888888888889, 16.666666666666668, 19.444444444444443, 22.22222222222222, 25.0,
+ 27.77777777777778, 30.555555555555554, 33.333333333333336
+ ],
+ "max_efforts": [
+ 126000.0, 126000.0, 126000.0, 102750.0, 80340.0, 65379.99999999999, 54900.0,
+ 47210.0, 41360.0, 36790.0, 33120.0, 30110.0, 27600.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "AC",
+ "electrical_profile_level": null,
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 1.3888888888888888, 5.555555555555555, 8.333333333333334, 11.11111111111111,
+ 13.88888888888889, 16.666666666666668, 19.444444444444443, 22.77777777777778, 25.0,
+ 27.77777777777778, 30.555555555555554, 33.333333333333336
+ ],
+ "max_efforts": [
+ 235000.0, 232500.0, 224000.0, 219000.0, 213500.0, 208000.0, 203000.0, 198000.0,
+ 192000.0, 175000.0, 157500.0, 143000.0, 131000.0
+ ]
+ }
+ },
+ {
+ "cond": {
+ "comfort": "HEATING",
+ "electrical_profile_level": null,
+ "power_restriction_code": null
+ },
+ "curve": {
+ "speeds": [
+ 0.0, 1.3888888888888888, 5.555555555555555, 8.333333333333334, 11.11111111111111,
+ 13.88888888888889, 16.666666666666668, 19.444444444444443, 22.77777777777778, 25.0,
+ 27.77777777777778, 30.555555555555554
+ ],
+ "max_efforts": [
+ 235000.0, 232500.0, 224000.0, 219000.0, 213500.0, 208000.0, 203000.0, 198000.0,
+ 192000.0, 175000.0, 157500.0, 143000.0
+ ]
+ }
+ }
+ ],
+ "default_curve": {
+ "speeds": [
+ 0.0, 2.7777777777777777, 5.555555555555555, 8.333333333333334, 11.11111111111111,
+ 13.88888888888889, 16.666666666666668, 19.444444444444443, 22.22222222222222, 25.0,
+ 27.77777777777778, 30.555555555555554, 33.333333333333336
+ ],
+ "max_efforts": [
+ 126000.0, 126000.0, 126000.0, 102750.0, 80340.0, 65379.99999999999, 54900.0, 47210.0,
+ 41360.0, 36790.0, 33120.0, 30110.0, 27600.0
+ ]
+ },
+ "is_electric": false
+ }
+ },
+ "default_mode": "thermal"
+ },
+ "metadata": {
+ "detail": "thermo-electric",
+ "family": "",
+ "type": "",
+ "grouping": "",
+ "series": "",
+ "subseries": "",
+ "unit": "",
+ "number": "",
+ "reference": "thermo-electric"
+ },
+ "length": 350.0,
+ "max_speed": 44.44444444444444,
+ "startup_time": 12.0,
+ "startup_acceleration": 0.06,
+ "comfort_acceleration": 0.54,
+ "gamma": {
+ "type": "CONST",
+ "value": 0.5
+ },
+ "inertia_coefficient": 1.05,
+ "base_power_class": "5",
+ "mass": 900000.0,
+ "rolling_resistance": {
+ "type": "davis",
+ "A": 4400.0,
+ "B": 195.67674,
+ "C": 12.00002688
+ },
+ "loading_gauge": "G1",
+ "power_restrictions": {
+ "C2": "1",
+ "C1": "3"
+ },
+ "energy_sources": [],
+ "locked": false,
+ "electrical_power_startup_time": 6.0,
+ "raise_pantograph_time": 16.0,
+ "version": 1,
+ "supported_signaling_systems": ["BAL", "BAPR", "TVM300", "TVM430"],
+ "liveries": []
+}
diff --git a/front/tests/assets/scenario-utlis.ts b/front/tests/assets/scenario-utlis.ts
new file mode 100644
index 00000000000..f28bc6b2953
--- /dev/null
+++ b/front/tests/assets/scenario-utlis.ts
@@ -0,0 +1,95 @@
+import { type Page, expect } from '@playwright/test';
+import { v4 as uuidv4 } from 'uuid';
+
+import scenarioData from './operationStudies/scenario.json';
+import { getInfra, getProject, getRollingStock, getStudy, postApiRequest } from './utils';
+import { PlaywrightHomePage } from '../pages/home-page-model';
+import RollingStockSelectorPage from '../pages/rolling-stock-selector-page';
+import PlaywrightScenarioPage from '../pages/scenario-page-model';
+
+// Scenario creation
+export default async function createCompleteScenario(
+ page: Page,
+ trainScheduleName: string,
+ trainCount: string,
+ delta: string
+) {
+ const smallInfra = await getInfra();
+ const project = await getProject();
+ const study = await getStudy(project.id);
+ const rollingStock = await getRollingStock();
+
+ const scenario = await postApiRequest(
+ `/api/projects/${project.id}/studies/${study.id}/scenarios`,
+ {
+ ...scenarioData,
+ name: `${scenarioData.name} ${uuidv4()}`,
+ study_id: study.id,
+ infra_id: smallInfra.id,
+ }
+ );
+
+ const playwrightHomePage = new PlaywrightHomePage(page);
+ const scenarioPage = new PlaywrightScenarioPage(page);
+
+ await page.goto(
+ `/operational-studies/projects/${project.id}/studies/${study.id}/scenarios/${scenario.id}`
+ );
+
+ await playwrightHomePage.page.getByTestId('scenarios-add-train-schedule-button').click();
+
+ await scenarioPage.setTrainScheduleName(trainScheduleName);
+ await scenarioPage.setNumberOfTrains(trainCount);
+ await scenarioPage.setDelta(delta);
+
+ // ***************** Select Rolling Stock *****************
+ const playwrightRollingstockModalPage = new RollingStockSelectorPage(playwrightHomePage.page);
+ await playwrightRollingstockModalPage.openRollingstockModal();
+
+ await playwrightRollingstockModalPage.searchRollingstock('rollingstock_1500_25000_test_e2e');
+
+ const rollingstockCard = playwrightRollingstockModalPage.getRollingstockCardByTestID(
+ `rollingstock-${rollingStock.name}`
+ );
+
+ await rollingstockCard.click();
+ await rollingstockCard.locator('button').click();
+
+ // ***************** Select Origin/Destination *****************
+ await scenarioPage.openTabByDataId('tab-pathfinding');
+ await scenarioPage.getPathfindingByTriGramSearch('MWS', 'NES');
+
+ // ***************** Create train *****************
+ await scenarioPage.addTrainSchedule();
+ await scenarioPage.page.waitForSelector('.dots-loader', { state: 'hidden' });
+ await scenarioPage.checkTrainHasBeenAdded();
+ await scenarioPage.returnSimulationResult();
+}
+
+// Allowances management
+
+export async function allowancesManagement(
+ scenarioPage: PlaywrightScenarioPage,
+ scenarioName: string,
+ allowanceType: 'standard' | 'engineering'
+) {
+ await expect(scenarioPage.getTimetableList).toBeVisible();
+
+ await scenarioPage.getBtnByName(scenarioName).hover();
+ await scenarioPage.page.getByTestId('edit-train').click();
+
+ await scenarioPage.openAllowancesModule();
+ await expect(scenarioPage.getAllowancesModule).toBeVisible();
+
+ if (allowanceType === 'standard') {
+ await scenarioPage.setStandardAllowance();
+ } else {
+ await scenarioPage.setEngineeringAllowance();
+ await scenarioPage.clickSuccessBtn();
+ await expect(scenarioPage.getAllowancesEngineeringSettings).toHaveAttribute('disabled');
+ }
+
+ await scenarioPage.page.getByTestId('submit-edit-train-schedule').click();
+ await scenarioPage.page.waitForSelector('.scenario-details-name');
+ expect(await scenarioPage.isAllowanceWorking()).toEqual(true);
+}
diff --git a/front/tests/assets/utils.ts b/front/tests/assets/utils.ts
index f0a2e117eb4..6ced3ad24b4 100644
--- a/front/tests/assets/utils.ts
+++ b/front/tests/assets/utils.ts
@@ -3,10 +3,6 @@ import { v4 as uuidv4 } from 'uuid';
import type { Project, Scenario, Study, RollingStock, Infra } from 'common/api/osrdEditoastApi';
-import scenarioData from './operationStudies/scenario.json';
-import { PlaywrightHomePage } from '../pages/home-page-model';
-import RollingStockSelectorPage from '../pages/rolling-stock-selector-page';
-import PlaywrightScenarioPage from '../pages/scenario-page-model';
// API requests
const getApiContext = async () =>
@@ -78,17 +74,25 @@ export const getRollingStock = async () => {
) as RollingStock;
return rollingStock;
};
-
+// Add a rolling Stock
+export async function addRollingStock(rollingStockName: string, rollingStockJson: JSON) {
+ await postApiRequest('/api/rolling_stock/', {
+ ...rollingStockJson,
+ name: rollingStockName,
+ });
+}
// Find and delete rolling stock with the given name
-export async function findAndDeleteRollingStock(rollingStockName: string) {
+export async function findAndDeleteRollingStocks(rollingStockNames: string[]) {
const rollingStocks = await getApiRequest(`/api/light_rolling_stock/`, { page_size: 500 });
- const rollingStockToDeleteCreated = rollingStocks.results.find(
- (r: RollingStock) => r.name === rollingStockName
- );
- if (rollingStockToDeleteCreated) {
- await deleteApiRequest(`/api/rolling_stock/${rollingStockToDeleteCreated.id}/`);
- }
+ const deleteRequests = rollingStockNames.map(async (name) => {
+ const rollingStockToDelete = rollingStocks.results.find((r: RollingStock) => r.name === name);
+ if (rollingStockToDelete) {
+ await deleteApiRequest(`/api/rolling_stock/${rollingStockToDelete.id}/`);
+ }
+ });
+
+ await Promise.all(deleteRequests);
}
// Fill and check input by ID
@@ -125,91 +129,9 @@ export const generateUniqueName = async (baseName: string) => {
const uuidSegment = uuidv4().slice(0, 6);
return `${baseName}-${uuidSegment}`;
};
-// Scenario creation
-export default async function createCompleteScenario(
- page: Page,
- trainScheduleName: string,
- trainCount: string,
- delta: string
-) {
- const smallInfra = (await getInfra()) as Infra;
- const project = await getProject();
- const study = await getStudy(project.id);
- const rollingStock = await getRollingStock();
-
- const scenario = await postApiRequest(
- `/api/projects/${project.id}/studies/${study.id}/scenarios`,
- {
- ...scenarioData,
- name: `${scenarioData.name} ${uuidv4()}`,
- study_id: study.id,
- infra_id: smallInfra.id,
- }
- );
-
- const playwrightHomePage = new PlaywrightHomePage(page);
- const scenarioPage = new PlaywrightScenarioPage(page);
-
- await page.goto(
- `/operational-studies/projects/${project.id}/studies/${study.id}/scenarios/${scenario.id}`
- );
-
- await playwrightHomePage.page.getByTestId('scenarios-add-train-schedule-button').click();
-
- await scenarioPage.setTrainScheduleName(trainScheduleName);
- await scenarioPage.setNumberOfTrains(trainCount);
- await scenarioPage.setDelta(delta);
-
- // ***************** Select Rolling Stock *****************
- const playwrightRollingstockModalPage = new RollingStockSelectorPage(playwrightHomePage.page);
- await playwrightRollingstockModalPage.openRollingstockModal();
-
- await playwrightRollingstockModalPage.searchRollingstock('rollingstock_1500_25000_test_e2e');
-
- const rollingstockCard = playwrightRollingstockModalPage.getRollingstockCardByTestID(
- `rollingstock-${rollingStock.name}`
- );
-
- await rollingstockCard.click();
- await rollingstockCard.locator('button').click();
-
- // ***************** Select Origin/Destination *****************
- await scenarioPage.openTabByDataId('tab-pathfinding');
- await scenarioPage.getPathfindingByTriGramSearch('MWS', 'NES');
-
- // ***************** Create train *****************
- await scenarioPage.addTrainSchedule();
- await scenarioPage.page.waitForSelector('.dots-loader', { state: 'hidden' });
- await scenarioPage.checkTrainHasBeenAdded();
- await scenarioPage.returnSimulationResult();
-}
-
-// Allowances management
-
-export async function allowancesManagement(
- scenarioPage: PlaywrightScenarioPage,
- scenarioName: string,
- allowanceType: 'standard' | 'engineering'
-) {
- await expect(scenarioPage.getTimetableList).toBeVisible();
-
- await scenarioPage.getBtnByName(scenarioName).hover();
- await scenarioPage.page.getByTestId('edit-train').click();
-
- await scenarioPage.openAllowancesModule();
- await expect(scenarioPage.getAllowancesModule).toBeVisible();
-
- if (allowanceType === 'standard') {
- await scenarioPage.setStandardAllowance();
- } else {
- await scenarioPage.setEngineeringAllowance();
- await scenarioPage.clickSuccessBtn();
- await expect(scenarioPage.getAllowancesEngineeringSettings).toHaveAttribute('disabled');
- }
-
- await scenarioPage.page.getByTestId('submit-edit-train-schedule').click();
- await scenarioPage.page.waitForSelector('.scenario-details-name');
- expect(await scenarioPage.isAllowanceWorking()).toEqual(true);
- // TODO: check if the allowances are taken into account in the scenario page (waiting for issue # 6695 to be fixed)
+// Extracts the first sequence of digits found in the input string and returns it as a number or return 0 if no digits found
+export async function extractNumberFromString(input: string): Promise {
+ const match = input.match(/\d+/);
+ return match ? parseInt(match[0], 10) : 0;
}
diff --git a/front/tests/pages/rolling-stock-selector-page.ts b/front/tests/pages/rolling-stock-selector-page.ts
index 68c5f9bf6a4..7bad7b71369 100644
--- a/front/tests/pages/rolling-stock-selector-page.ts
+++ b/front/tests/pages/rolling-stock-selector-page.ts
@@ -1,9 +1,7 @@
import { type Locator, type Page, expect } from '@playwright/test';
import BasePage from './base-page';
-import rollingstockTranslation from '../../public/locales/fr/rollingstock.json';
-
-const electricCheckboxTranslation = rollingstockTranslation.electric;
+import { extractNumberFromString } from '../assets/utils';
export default class RollingStockSelectorPage extends BasePage {
readonly rollingStockSelectorButton: Locator;
@@ -16,15 +14,31 @@ export default class RollingStockSelectorPage extends BasePage {
readonly rollingStockListItem: Locator;
- readonly getRollingStockSearch: Locator;
-
- readonly getRollingStockSearchFilter: Locator;
+ readonly getRollingStockModalSearch: Locator;
readonly rollingStockMiniCards: Locator;
readonly getRollingstockSpanNames: Locator;
- readonly electricalCheckbox: Locator;
+ readonly getElectricRollingStockFilter: Locator;
+
+ readonly getThermalRollingStockFilter: Locator;
+
+ readonly getRollingStockSearchResult: Locator;
+
+ readonly getThermalRollingStockIcons: Locator;
+
+ readonly getElectricRollingStockIcons: Locator;
+
+ readonly getElectricRollingStockFirstIcon: Locator;
+
+ readonly getThermalRollingStockFirstIcon: Locator;
+
+ readonly getRollingStockList: Locator;
+
+ readonly getThermalElectricRollingStockIcons: Locator;
+
+ readonly getNoRollingStockResult: Locator;
constructor(page: Page) {
super(page);
@@ -35,13 +49,23 @@ export default class RollingStockSelectorPage extends BasePage {
this.rollingStockListItem = page.locator('.rollingstock-container');
this.getResultsFound = page.locator('.modal-dialog').locator('small').first();
- this.getRollingStockSearch = this.rollingStockSelectorModal.locator('#searchfilter');
- this.getRollingStockSearchFilter = page.locator('.rollingstock-search-filters');
+ this.getRollingStockModalSearch = this.rollingStockSelectorModal.locator('#searchfilter');
this.rollingStockMiniCards = page.locator('.rollingstock-selector-minicard');
this.getRollingstockSpanNames = page.locator('.rollingstock-minicard-name');
- this.electricalCheckbox = this.rollingStockSelectorModal.locator('label').filter({
- hasText: electricCheckboxTranslation,
- });
+ this.getElectricRollingStockFilter = page.locator('label[for="elec"]');
+ this.getThermalRollingStockFilter = page.locator('label[for="thermal"]');
+ this.getRollingStockSearchResult = page.getByTestId('search-results-text');
+ this.getThermalRollingStockIcons = page.locator('.rollingstock-footer-specs .text-pink');
+ this.getElectricRollingStockIcons = page.locator('.rollingstock-footer-specs .text-primary');
+ this.getThermalElectricRollingStockIcons = page
+ .locator('.rollingstock-footer-specs .rollingstock-tractionmode:has(.text-pink)')
+ .filter({
+ has: page.locator('.text-primary'),
+ });
+ this.getElectricRollingStockFirstIcon = this.getElectricRollingStockIcons.first();
+ this.getThermalRollingStockFirstIcon = this.getThermalRollingStockIcons.first();
+ this.getRollingStockList = page.locator('.rollingstock-editor-list .rollingstock-title');
+ this.getNoRollingStockResult = page.locator('.rollingstock-empty');
}
async openRollingstockModal() {
@@ -54,11 +78,11 @@ export default class RollingStockSelectorPage extends BasePage {
}
async searchRollingstock(rollingstockName: string) {
- await this.getRollingStockSearch.fill(rollingstockName);
+ await this.getRollingStockModalSearch.fill(rollingstockName);
}
async selectRollingStock(rollingStockName: string) {
- await this.getRollingStockSearch.fill(rollingStockName);
+ await this.getRollingStockModalSearch.fill(rollingStockName);
const rollingstockItem = this.rollingStockList.getByTestId(`rollingstock-${rollingStockName}`);
await rollingstockItem.click();
await rollingstockItem.locator('.rollingstock-footer-buttons > button').click();
@@ -79,4 +103,19 @@ export default class RollingStockSelectorPage extends BasePage {
async closeRollingstockModal() {
await this.rollingStockSelectorModal.locator('.close').click();
}
+
+ // Select Combustion engine RS filter
+ async thermalRollingStockFilter() {
+ await this.getThermalRollingStockFilter.click();
+ }
+
+ // Select Electic RS filter
+ async electricRollingStockFilter() {
+ await this.getElectricRollingStockFilter.click();
+ }
+
+ // Get the number of RS from the search result text
+ async getRollingStockSearchNumber(): Promise {
+ return extractNumberFromString(await this.getRollingStockSearchResult.innerText());
+ }
}
diff --git a/front/tests/pages/rollingstock-editor-page-model.ts b/front/tests/pages/rollingstock-editor-page-model.ts
index ad41570d65e..4168e21b24e 100644
--- a/front/tests/pages/rollingstock-editor-page-model.ts
+++ b/front/tests/pages/rollingstock-editor-page-model.ts
@@ -71,6 +71,8 @@ export default class PlaywrightRollingstockEditorPage extends PlaywrightCommonPa
// Navigate to the Rolling Stock Editor Page
async navigateToPage() {
await this.page.goto('/rolling-stock-editor/');
+ // Wait for the page to reach the network idle state
+ await this.page.waitForLoadState('networkidle');
await this.removeViteOverlay();
}
@@ -162,6 +164,7 @@ export default class PlaywrightRollingstockEditorPage extends PlaywrightCommonPa
}
// Set spreadsheet row value
+ // TODO: Refactor to eliminate ESLint errors
async setSpreadsheetRow(data: { row: number; velocity: string; effort: string }[]) {
for (const { row, effort, velocity } of data) {
const velocityCell = this.getVelocityCellByRow(row);
@@ -222,6 +225,7 @@ export default class PlaywrightRollingstockEditorPage extends PlaywrightCommonPa
.getByTitle(powerRestrictionValue, { exact: true })
.click();
}
+ // TODO: Refactor to eliminate ESLint errors
for (const rowData of data) {
const rowIndex = data.indexOf(rowData) + 1;
const velocityCell = this.getVelocityCellByRow(rowIndex);
@@ -242,7 +246,7 @@ export default class PlaywrightRollingstockEditorPage extends PlaywrightCommonPa
.getByRole('button', { name: powerRestrictionValue })
.click();
}
-
+ // TODO: Refactor to eliminate ESLint errors
for (const rowData of expectedData) {
const rowIndex = expectedData.indexOf(rowData) + 1;
const velocityCell = await this.getVelocityCellByRowValue(rowIndex);