Skip to content

Commit d022d0b

Browse files
committed
Create a tram stop
- User Story 72788 - Implement transport mode logic to stop creation - Bus and Tram stop is now configured - Add e2e tests for creating tram stops
1 parent ba5f061 commit d022d0b

36 files changed

Lines changed: 547 additions & 142 deletions

cypress/e2e/map/createStop.cy.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
ReusableComponentsVehicleModeEnum,
44
StopAreaInput,
55
StopRegistryGeoJsonType,
6+
StopRegistryTransportModeType,
67
timingPlaces,
78
} from '@hsl/jore4-test-db-manager/dist/CypressSpecExports';
89
import { Tag } from '../../enums';
@@ -28,16 +29,40 @@ const testStopLabels = {
2829
testLabel1: 'T0001',
2930
stopAreaPrivateCode: '123456',
3031
stopAreaName: 'Test area',
32+
tramLabel: 'T1001',
33+
tramStopAreaPrivateCode: 'Y1238',
34+
tramStopAreaName: 'Tram',
3135
manualCoordinatesLabel: 'T0002',
3236
endDateLabel: 'T0003',
3337
timingPlaceLabel: 'T0004',
3438
};
3539

3640
const dbResources = { timingPlaces };
3741

42+
const tramStopLocation = {
43+
lat: 60.15737558915313,
44+
lng: 24.91175322455062,
45+
};
46+
3847
const stopAreaInput: Array<StopAreaInput> = [
3948
{
4049
StopArea: {
50+
transportMode: StopRegistryTransportModeType.Tram,
51+
name: { lang: 'fin', value: testStopLabels.tramStopAreaName },
52+
privateCode: {
53+
type: 'HSL/TEST',
54+
value: testStopLabels.tramStopAreaPrivateCode,
55+
},
56+
geometry: {
57+
coordinates: [24.93648964, 60.15551145],
58+
type: StopRegistryGeoJsonType.Point,
59+
},
60+
},
61+
organisations: null,
62+
},
63+
{
64+
StopArea: {
65+
transportMode: StopRegistryTransportModeType.Bus,
4166
name: { lang: 'fin', value: testStopLabels.stopAreaName },
4267
privateCode: {
4368
type: 'HSL/TEST',
@@ -89,6 +114,7 @@ describe('Stop creation tests', rootOpts, () => {
89114
xPercentage: 40,
90115
yPercentage: 55,
91116
},
117+
vehicleMode: ReusableComponentsVehicleModeEnum.Bus,
92118
});
93119

94120
MapPage.gqlStopShouldBeCreatedSuccessfully();
@@ -102,6 +128,29 @@ describe('Stop creation tests', rootOpts, () => {
102128
).should('exist');
103129
});
104130

131+
it('Should create tram stop', () => {
132+
MapPage.createStopAtLocation({
133+
stopFormInfo: {
134+
publicCode: testStopLabels.tramLabel,
135+
stopPlace: testStopLabels.tramStopAreaPrivateCode,
136+
latitude: String(tramStopLocation.lat),
137+
longitude: String(tramStopLocation.lng),
138+
validityStartISODate: '2022-01-01',
139+
priority: Priority.Standard,
140+
reasonForChange: 'Initial creation',
141+
},
142+
clickRelativePoint: {
143+
xPercentage: 50,
144+
yPercentage: 50,
145+
},
146+
vehicleMode: ReusableComponentsVehicleModeEnum.Tram,
147+
});
148+
149+
MapPage.gqlStopShouldBeCreatedSuccessfully();
150+
151+
MapPage.checkStopSubmitSuccessToast();
152+
});
153+
105154
it(
106155
'Should create stop and change observation date',
107156
{ scrollBehavior: 'bottom' },

cypress/e2e/map/editStop.cy.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,16 @@ describe('Stop editing tests', { tags: [Tag.Stops, Tag.Map] }, () => {
106106

107107
Map.stopPopUp.getMoveButton().click();
108108

109+
cy.intercept('POST', '/api/graphql/v1/graphql?q=QueryClosestLink').as(
110+
'gqlQueryClosestLink',
111+
);
112+
109113
// Point where the stop is moved on the map. Moving the stop here gives it the endCoordinates.
110114
// Map view zoom level should not be changed in the test since it would naturally affect this test location.
111115
Map.clickRelativePoint(71, 35);
112116

117+
expectGraphQLCallToSucceed('@gqlQueryClosestLink');
118+
113119
ConfirmationDialog.getConfirmButton().click();
114120

115121
expectGraphQLCallToSucceed('@gqlEditStop');
@@ -236,8 +242,15 @@ describe('Stop editing tests', { tags: [Tag.Stops, Tag.Map] }, () => {
236242
Map.stopPopUp.getEditButton().click();
237243

238244
StopForm.fillBaseForm(updatedStopInfo);
245+
246+
cy.intercept('POST', '/api/graphql/v1/graphql?q=QueryClosestLink').as(
247+
'gqlQueryClosestLink',
248+
);
249+
239250
StopForm.save();
240251

252+
expectGraphQLCallToSucceed('@gqlQueryClosestLink');
253+
241254
ConfirmationDialog.getConfirmButton().click();
242255

243256
expectGraphQLCallToSucceed('@gqlEditStop');

cypress/e2e/stop-registry/stopDetails.cy.ts

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3077,17 +3077,12 @@ describe('Stop details', { tags: [Tag.StopRegistry] }, () => {
30773077
});
30783078

30793079
describe('latest change history', () => {
3080-
it('should display 5 latest change history items', () => {
3080+
it('should display 5 latest change history items and support show all navigation', () => {
30813081
StopDetailsPage.visit('H2003');
30823082
StopDetailsPage.page().shouldBeVisible();
30833083

30843084
StopDetailsPage.latestChangeHistory.container().shouldBeVisible();
3085-
StopDetailsPage.latestChangeHistory
3086-
.title()
3087-
.shouldBeVisible()
3088-
.should('contain.text', 'Muutoshistoria');
3089-
3090-
StopDetailsPage.latestChangeHistory.getItems().should('have.length', 1);
3085+
StopDetailsPage.latestChangeHistory.title().shouldBeVisible();
30913086

30923087
cy.section('Make multiple changes to create history', () => {
30933088
// Change 1
@@ -3139,32 +3134,27 @@ describe('Stop details', { tags: [Tag.StopRegistry] }, () => {
31393134

31403135
StopDetailsPage.latestChangeHistory
31413136
.getNthItem(0)
3142-
.should('contain.text', 'Perustiedot')
3143-
.and('contain.text', 'ELY-numero:')
3137+
.should('be.visible')
31443138
.and('contain.text', '9999999');
31453139

31463140
StopDetailsPage.latestChangeHistory
31473141
.getNthItem(1)
3148-
.should('contain.text', 'Sijainti')
3149-
.and('contain.text', 'Postinumero:')
3142+
.should('be.visible')
31503143
.and('contain.text', '00200');
31513144

31523145
StopDetailsPage.latestChangeHistory
31533146
.getNthItem(2)
3154-
.should('contain.text', 'Perustiedot')
3155-
.and('contain.text', 'Sijainti (suomi):')
3147+
.should('be.visible')
31563148
.and('contain.text', 'Uusi sijainti');
31573149

31583150
StopDetailsPage.latestChangeHistory
31593151
.getNthItem(3)
3160-
.should('contain.text', 'Pysäkkikilvet')
3161-
.and('contain.text', 'Pysäkkikilpien tyyppi:')
3152+
.should('be.visible')
31623153
.and('contain.text', 'Katoskehikko');
31633154

31643155
StopDetailsPage.latestChangeHistory
31653156
.getNthItem(4)
3166-
.should('contain.text', 'Sijainti')
3167-
.and('contain.text', 'Pysäkin osoite:')
3157+
.should('be.visible')
31683158
.and('contain.text', 'Mannerheimintie 1');
31693159
});
31703160

cypress/pageObjects/forms/StopForm.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { expectGraphQLCallToSucceed } from '../../utils/assertions';
1+
import {
2+
expectGraphQLCallToSucceed,
3+
waitForSuccessfulGraphQLCall,
4+
} from '../../utils/assertions';
25
import { ChangeValidityForm } from './ChangeValidityForm';
36
import { CreateTimingPlaceForm } from './CreateTimingPlaceForm';
47
import { PriorityForm, PriorityFormInfo } from './PriorityForm';
@@ -129,6 +132,7 @@ export class StopForm {
129132

130133
if (values.stopPlace) {
131134
StopForm.getStopAreaInput().clearAndType(values.stopPlace);
135+
waitForSuccessfulGraphQLCall('@gqlFindStopAreasByNames');
132136
StopForm.getStopAreaResult(values.stopPlace).click();
133137
}
134138

cypress/pageObjects/map/MapFooter.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ReusableComponentsVehicleModeEnum } from '@hsl/jore4-test-db-manager/dist/CypressSpecExports';
2+
13
export class MapFooter {
24
static getMapFooter() {
35
return cy.getByTestId('MapFooter::mapFooter');
@@ -14,12 +16,25 @@ export class MapFooter {
1416
.click();
1517
}
1618

17-
static addStop() {
18-
return cy
19-
.getByTestId('MapFooter:addStopButton')
19+
static addStop(
20+
vehicleMode: ReusableComponentsVehicleModeEnum = ReusableComponentsVehicleModeEnum.Bus,
21+
) {
22+
cy.getByTestId('MapFooter:addStopButton')
2023
.should('be.visible')
2124
.and('be.enabled')
2225
.click();
26+
27+
if (vehicleMode === ReusableComponentsVehicleModeEnum.Tram) {
28+
return cy
29+
.getByTestId('AddStopDropdownOption::addTramStop')
30+
.should('be.visible')
31+
.click();
32+
}
33+
34+
return cy
35+
.getByTestId('AddStopDropdownOption::addBusStop')
36+
.should('be.visible')
37+
.click();
2338
}
2439

2540
static addStopArea() {

cypress/pageObjects/map/MapPage.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ReusableComponentsVehicleModeEnum } from '@hsl/jore4-test-db-manager/dist/CypressSpecExports';
12
import { expectGraphQLCallToSucceed } from '../../utils/assertions';
23
import { RoutePropertiesForm } from '../forms/RoutePropertiesForm';
34
import { StopAreaForm } from '../forms/StopAreaForm';
@@ -43,11 +44,13 @@ export class MapPage {
4344
static createStopAtLocation({
4445
stopFormInfo,
4546
clickRelativePoint,
47+
vehicleMode = ReusableComponentsVehicleModeEnum.Bus,
4648
}: {
4749
stopFormInfo: NewStopFormInfo;
4850
clickRelativePoint: { xPercentage: number; yPercentage: number };
51+
vehicleMode?: ReusableComponentsVehicleModeEnum;
4952
}) {
50-
MapFooter.addStop();
53+
MapFooter.addStop(vehicleMode);
5154

5255
Map.clickRelativePoint(
5356
clickRelativePoint.xPercentage,

cypress/utils/assertions.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,31 @@ export function expectGraphQLCallToSucceed(alias: string) {
132132
});
133133
}
134134

135+
/**
136+
* Like expectGraphQLCallToSucceed, but skips intercepted calls that have a raw
137+
* network error (e.g. socket closed mid-response due to rapid re-querying).
138+
* Useful when typing into a search field triggers multiple debounced requests
139+
* and intermediate requests may get cancelled in CI.
140+
*/
141+
export function waitForSuccessfulGraphQLCall(
142+
alias: string,
143+
): Cypress.Chainable<SuccessfulGraphQLInterception> {
144+
return cy
145+
.wait(alias)
146+
.then(
147+
(interceptedCall): Cypress.Chainable<SuccessfulGraphQLInterception> => {
148+
if (interceptedCall.error) {
149+
return waitForSuccessfulGraphQLCall(alias);
150+
}
151+
const body = assertAndGetValidGraphGLBody(alias, interceptedCall);
152+
assertGraphQLBodyHasNoErrors(alias, body);
153+
return cy.wrap(
154+
interceptedCall as unknown as SuccessfulGraphQLInterception,
155+
);
156+
},
157+
);
158+
}
159+
135160
export function expectGraphQLCallToReturnError(alias: string) {
136161
return cy
137162
.wait(alias)

jore4-hasura

Submodule jore4-hasura updated 75 files

ui/src/components/forms/stop/StopForm.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,15 @@ function mapFormStateToStopPointSetInput(
7373
function mapFormStateToStopPointCreateInput(
7474
state: StopFormState,
7575
): CreateStopPointInput {
76+
const vehicleMode =
77+
state.vehicleMode ?? ReusableComponentsVehicleModeEnum.Bus;
78+
7679
return {
7780
...mapFormStateToStopPointSetInput(state),
7881
vehicle_mode_on_scheduled_stop_point: {
7982
data: [
8083
{
81-
// TODO: Replace hard-coded Bus-value with propagated one
82-
vehicle_mode: ReusableComponentsVehicleModeEnum.Bus,
84+
vehicle_mode: vehicleMode,
8385
},
8486
],
8587
},

ui/src/components/forms/stop/components/FindStopArea.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from '@headlessui/react';
99
import debounce from 'lodash/debounce';
1010
import { FC, useEffect, useMemo, useState } from 'react';
11-
import { useController } from 'react-hook-form';
11+
import { useController, useFormContext } from 'react-hook-form';
1212
import { useTranslation } from 'react-i18next';
1313
import { MdOutlineSearch } from 'react-icons/md';
1414
import { comboboxStyles } from '../../../../uiComponents';
@@ -32,13 +32,18 @@ export const FindStopArea: FC<FindStopAreaProps> = ({
3232
disabled,
3333
}) => {
3434
const { t } = useTranslation();
35+
const { watch } = useFormContext<StopFormState>();
36+
const vehicleMode = watch('vehicleMode');
3537

3638
const [query, setQuery] = useState('');
3739
// Is there pending keystrokes in the input field being buffered by debouncing.
3840
// Set to true on key input and reset to false, after DB query.
3941
// This is to avoid flickering of the loading state
4042
const [queryDebounced, setQueryDebounced] = useState(false);
41-
const { areas, loading: loadingResults } = useFindStopAreas(query);
43+
const { areas, loading: loadingResults } = useFindStopAreas(
44+
query,
45+
vehicleMode,
46+
);
4247

4348
const {
4449
field: { onChange: onSelect, value: selected, ref },

0 commit comments

Comments
 (0)