From 04a3629a3aef75a901664e225d1429e5ce5750f4 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Thu, 3 Oct 2024 14:46:53 +0200 Subject: [PATCH 1/6] Fix pending sent message subscriber list in pno form --- frontend/src/api/constants.ts | 1 - .../ManualPriorNotificationForm/Content.tsx | 2 +- .../PriorNotificationCard/index.tsx | 2 +- .../shared/CardBodyHead/SentMessageList.tsx | 55 ++++++++++--------- .../components/shared/CardBodyHead/index.tsx | 8 +-- .../PriorNotification/priorNotificationApi.ts | 2 +- 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/frontend/src/api/constants.ts b/frontend/src/api/constants.ts index 292f521033..eb0752a7cc 100644 --- a/frontend/src/api/constants.ts +++ b/frontend/src/api/constants.ts @@ -36,7 +36,6 @@ export enum HttpStatusCode { export enum RtkCacheTagType { PriorNotificationDocuments = 'PriorNotificationDocuments', - PriorNotificationSentMessages = 'PriorNotificationSentMessages', PriorNotificationSubscribers = 'PriorNotificationSubscribers', PriorNotificationTypes = 'PriorNotificationTypes', PriorNotifications = 'PriorNotifications', diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx index 33f77c1c35..b610a9623a 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx @@ -162,6 +162,7 @@ export function Content({ detail, isValidatingOnChange, onClose, onSubmit, onVer diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx index 512e808255..2199b45822 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx @@ -94,6 +94,7 @@ export function PriorNotificationCard({ diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx index 7cc63e6535..e5923e1524 100644 --- a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx @@ -1,3 +1,4 @@ +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' import { useGetPriorNotificationSentNessagesQuery } from '@features/PriorNotification/priorNotificationApi' import { Icon } from '@mtes-mct/monitor-ui' import { Steps } from 'rsuite' @@ -6,17 +7,16 @@ import styled from 'styled-components' import { SentMessagesBatchStatus } from './constants' import { getSentMessagesBatches, getSubscribersFromSentMessages } from './utils' -import type { PriorNotification } from '@features/PriorNotification/PriorNotification.types' - type SentMessageListProps = Readonly<{ detail: PriorNotification.Detail + state: PriorNotification.State | undefined }> -export function SentMessageList({ detail }: SentMessageListProps) { - const { data: sentMessages, isError } = useGetPriorNotificationSentNessagesQuery(detail.reportId) +export function SentMessageList({ detail, state }: SentMessageListProps) { + const { data: sentMessages, isError, isFetching } = useGetPriorNotificationSentNessagesQuery(detail.reportId) - const sentMessagesBatches = sentMessages ? getSentMessagesBatches(sentMessages) : undefined + const sentMessagesBatches = sentMessages ? getSentMessagesBatches(sentMessages) : [] const lastSentMessagesBatch = sentMessagesBatches ? sentMessagesBatches[sentMessagesBatches.length - 1] : undefined - const subscribers = lastSentMessagesBatch ? getSubscribersFromSentMessages(lastSentMessagesBatch.messages) : undefined + const subscribers = lastSentMessagesBatch ? getSubscribersFromSentMessages(lastSentMessagesBatch.messages) : [] return ( <> @@ -24,19 +24,26 @@ export function SentMessageList({ detail }: SentMessageListProps) { {isError &&

Impossible de récupérer la liste.

} {!isError && ( <> - {!subscribers &&

Chargement en cours...

} - {subscribers && subscribers.length === 0 &&

Aucun message n’a été envoyé pour ce préavis.

} - {subscribers?.map(subsriber => ( - -

- {subsriber.name} ({subsriber.organization}) -

- - {subsriber.email && {subsriber.email}} - {subsriber.phone && {subsriber.phone}} - -
- ))} + {isFetching &&

Chargement en cours...

} + {!isFetching && subscribers.length === 0 && ( +

+ {state === PriorNotification.State.FAILED_SEND + ? `Aucune unité n'est inscrite à ce préavis.` + : `Aucun message n’a été envoyé pour ce préavis.`} +

+ )} + {!isFetching && + subscribers.map(subsriber => ( + +

+ {subsriber.name} ({subsriber.organization}) +

+ + {subsriber.email && {subsriber.email}} + {subsriber.phone && {subsriber.phone}} + +
+ ))} )} @@ -44,13 +51,9 @@ export function SentMessageList({ detail }: SentMessageListProps) { {isError &&

Impossible de récupérer l’historique.

} {!isError && ( <> - {!sentMessagesBatches &&

Chargement en cours...

} - <> - {sentMessagesBatches && sentMessagesBatches.length === 0 && ( -

Aucun message n’a été envoyé pour ce préavis.

- )} - - {sentMessagesBatches && ( + {isFetching &&

Chargement en cours...

} + {!isFetching && sentMessagesBatches.length === 0 &&

Aucun message n’a été envoyé pour ce préavis.

} + {!isFetching && sentMessagesBatches.length > 0 && ( {sentMessagesBatches.map(sentMessagesBatch => ( | undefined hasBeenComputed: boolean @@ -16,11 +17,11 @@ type CardBodyHeadProps = Readonly<{ isPriorNotificationZero: boolean | undefined isVesselUnderCharter: boolean | undefined riskFactor: number | undefined - state: PriorNotification.State | undefined tripSegments: LogbookMessage.Segment[] | undefined types: PriorNotification.Type[] | undefined }> export function CardBodyHead({ + applicableState, detail, editedPriorNotificationComputedValues, hasBeenComputed, @@ -28,7 +29,6 @@ export function CardBodyHead({ isPriorNotificationZero, isVesselUnderCharter, riskFactor, - state, tripSegments, types }: CardBodyHeadProps) { @@ -54,7 +54,7 @@ export function CardBodyHead({ isPriorNotificationZero={isPriorNotificationZero} isVesselUnderCharter={isVesselUnderCharter} riskFactor={riskFactor} - state={state} + state={applicableState} tripSegments={tripSegments} types={types} /> @@ -79,7 +79,7 @@ export function CardBodyHead({ )} {isSentMessageListExpanded && !!detail && ( <> - + Masquer les détails de la diffusion du préavis diff --git a/frontend/src/features/PriorNotification/priorNotificationApi.ts b/frontend/src/features/PriorNotification/priorNotificationApi.ts index 63a1873c1b..0d78e80414 100644 --- a/frontend/src/features/PriorNotification/priorNotificationApi.ts +++ b/frontend/src/features/PriorNotification/priorNotificationApi.ts @@ -131,7 +131,7 @@ export const priorNotificationApi = monitorfishApi.injectEndpoints({ }), getPriorNotificationSentNessages: builder.query({ - providesTags: () => [{ type: RtkCacheTagType.PriorNotificationSentMessages }], + providesTags: () => [{ type: RtkCacheTagType.PriorNotifications }], query: reportId => `/prior_notifications/${reportId}/sent_messages`, transformErrorResponse: response => new FrontendApiError(GET_PRIOR_NOTIFICATION_SENT_MESSAGES_ERROR_MESSAGE, response) From ec99ba1f1063d45cba674cdd656bc3ac80df1a6a Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Thu, 3 Oct 2024 16:49:49 +0200 Subject: [PATCH 2/6] Fix some types in LogbookMessage.types.ts --- frontend/cypress/e2e/types.ts | 10 ++++++++++ .../src/features/Logbook/LogbookMessage.types.ts | 12 +++++------- .../LogbookMessages/messages/LogbookMessage.tsx | 2 +- .../PriorNotification/PriorNotification.types.ts | 8 ++------ .../DownloadButton/__tests__/getHtmlContent.test.ts | 2 -- 5 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 frontend/cypress/e2e/types.ts diff --git a/frontend/cypress/e2e/types.ts b/frontend/cypress/e2e/types.ts new file mode 100644 index 0000000000..0886f602ec --- /dev/null +++ b/frontend/cypress/e2e/types.ts @@ -0,0 +1,10 @@ +export type OrUndefinedToOrNull = + T extends Array + ? Array> + : T extends object + ? { + [K in keyof T]: OrUndefinedToOrNull extends infer U ? (undefined extends T[K] ? U | null : U) : never + } + : T extends undefined + ? null + : T diff --git a/frontend/src/features/Logbook/LogbookMessage.types.ts b/frontend/src/features/Logbook/LogbookMessage.types.ts index 07a786715a..fc0c1d213b 100644 --- a/frontend/src/features/Logbook/LogbookMessage.types.ts +++ b/frontend/src/features/Logbook/LogbookMessage.types.ts @@ -6,7 +6,6 @@ export namespace LogbookMessage { interface LogbookMessageBase { acknowledgment: Acknowledgment | undefined - createdAt: string externalReferenceNumber: string | undefined flagState: string | undefined imo: string | undefined @@ -21,14 +20,13 @@ export namespace LogbookMessage { operationDateTime: string operationNumber: string | undefined operationType: OperationType - rawMessage: string + rawMessage: string | undefined referencedReportId: string | undefined reportDateTime: string reportId: string tripGears: Gear[] | undefined tripNumber: string | undefined tripSegments: Segment[] | undefined - updatedAt: string vesselName: string } export interface PnoLogbookMessage extends LogbookMessageBase { @@ -67,12 +65,12 @@ export namespace LogbookMessage { weight: number | undefined } + // TODO Replace `| null` by `| undefined` after deleting Gear in logbook.types.ts export type Gear = { - dimensions: string - gear: string - // TODO Replace null by undefined after deleting Gear in logbook.types.ts + dimensions: string | null + gear: string | null gearName: string | null - mesh: number + mesh: number | null } interface MessageBase {} diff --git a/frontend/src/features/Logbook/components/VesselLogbook/LogbookMessages/messages/LogbookMessage.tsx b/frontend/src/features/Logbook/components/VesselLogbook/LogbookMessages/messages/LogbookMessage.tsx index 531670f8d9..1bef41b238 100644 --- a/frontend/src/features/Logbook/components/VesselLogbook/LogbookMessages/messages/LogbookMessage.tsx +++ b/frontend/src/features/Logbook/components/VesselLogbook/LogbookMessages/messages/LogbookMessage.tsx @@ -107,7 +107,7 @@ export function LogbookMessage({ {!isManuallyCreated && logbookMessage.rawMessage && ( openXML(logbookMessage.rawMessage)} + onClick={() => openXML(logbookMessage.rawMessage!)} style={{ cursor: 'pointer' }} title="Ouvrir le message XML brut" /> diff --git a/frontend/src/features/PriorNotification/PriorNotification.types.ts b/frontend/src/features/PriorNotification/PriorNotification.types.ts index a4d9c28f15..c725c0b33f 100644 --- a/frontend/src/features/PriorNotification/PriorNotification.types.ts +++ b/frontend/src/features/PriorNotification/PriorNotification.types.ts @@ -11,14 +11,10 @@ export namespace PriorNotification { expectedLandingDate: string | undefined /** Unique identifier concatenating all the DAT, COR, RET & DEL operations `id` used for data consolidation. */ fingerprint: string - hasVesselRiskFactorSegments: boolean | undefined - isBeingSent: boolean isCorrection: boolean - isInVerificationScope: boolean isInvalidated: boolean | undefined isManuallyCreated: boolean - isSent: boolean - isVerified: boolean + isPriorNotificationZero: boolean isVesselUnderCharter: boolean | undefined onBoardCatches: LogbookMessage.Catch[] operationDate: string @@ -92,7 +88,6 @@ export namespace PriorNotification { purpose: PurposeCode | undefined sentAt: string | undefined tripGearCodes: string[] - updatedAt: string | undefined vesselId: number | undefined } @@ -164,6 +159,7 @@ export namespace PriorNotification { communicationMeans: 'EMAIL' | 'FAX' | 'SMS' dateTimeUtc: string errorMessage: string | undefined + id: number recipientAddressOrNumber: string recipientName: string recipientOrganization: string diff --git a/frontend/src/features/PriorNotification/components/shared/DownloadButton/__tests__/getHtmlContent.test.ts b/frontend/src/features/PriorNotification/components/shared/DownloadButton/__tests__/getHtmlContent.test.ts index 6aab21be07..ce2f0b6e30 100644 --- a/frontend/src/features/PriorNotification/components/shared/DownloadButton/__tests__/getHtmlContent.test.ts +++ b/frontend/src/features/PriorNotification/components/shared/DownloadButton/__tests__/getHtmlContent.test.ts @@ -13,7 +13,6 @@ describe('PriorNotificationCard/utils.getHtmlContent()', () => { // Given const pno: LogbookMessage.PnoLogbookMessage = { acknowledgment: undefined, - createdAt: '2024-06-14T06:52:22.978603Z', externalReferenceNumber: undefined, flagState: 'ESP', imo: undefined, @@ -188,7 +187,6 @@ describe('PriorNotificationCard/utils.getHtmlContent()', () => { name: 'Chalut à perche' } ], - updatedAt: '2024-06-14T06:52:22.978603Z', vesselName: 'VIVA ESPANA' } const gears = [ From 6cf681db7063ad34a514e89fe100f42a38a5d568 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Mon, 7 Oct 2024 08:52:10 +0200 Subject: [PATCH 3/6] Add missing computed values reset in verifyAndSendPriorNotification() use case --- .../useCases/verifyAndSendPriorNotification.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/features/PriorNotification/useCases/verifyAndSendPriorNotification.ts b/frontend/src/features/PriorNotification/useCases/verifyAndSendPriorNotification.ts index f99d52d116..336a353062 100644 --- a/frontend/src/features/PriorNotification/useCases/verifyAndSendPriorNotification.ts +++ b/frontend/src/features/PriorNotification/useCases/verifyAndSendPriorNotification.ts @@ -17,6 +17,9 @@ export const verifyAndSendPriorNotification = ): MainAppThunk> => async dispatch => { try { + dispatch(priorNotificationActions.unsetOpenedPriorNotificationDetail()) + dispatch(priorNotificationActions.unsetEditedPriorNotificationComputedValues()) + const priorNotificationDetail = await dispatch( priorNotificationApi.endpoints.verifyAndSendPriorNotification.initiate({ ...priorNotificationIdentifier, From 202c57acf33a316f3701ae8aa83b05cf8d864136 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Mon, 7 Oct 2024 09:04:27 +0200 Subject: [PATCH 4/6] Fix Frontend unit tests typing following PriorNotification types fix --- .../__tests__/getSentMessagesBatches.test.ts | 13 +++++++++++++ .../getSubscribersFromSentMessages.test.ts | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSentMessagesBatches.test.ts b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSentMessagesBatches.test.ts index f84bdc680f..5f4f613765 100644 --- a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSentMessagesBatches.test.ts +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSentMessagesBatches.test.ts @@ -20,6 +20,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -43,6 +44,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email1@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -52,6 +54,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:20Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: 'email2@example.com', recipientName: 'Jane Smith', recipientOrganization: 'Org B', @@ -75,6 +78,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email1@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -84,6 +88,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:31Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: 'email2@example.com', recipientName: 'Jane Smith', recipientOrganization: 'Org B', @@ -110,6 +115,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email1@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -119,6 +125,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:20Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: 'email2@example.com', recipientName: 'Jane Smith', recipientOrganization: 'Org B', @@ -140,6 +147,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email1@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -149,6 +157,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:20Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: 'email2@example.com', recipientName: 'Jane Smith', recipientOrganization: 'Org B', @@ -172,6 +181,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email1@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -181,6 +191,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:25Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email2@example.com', recipientName: 'Jane Smith', recipientOrganization: 'Org B', @@ -190,6 +201,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:01:05Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: 'email3@example.com', recipientName: 'Alice Johnson', recipientOrganization: 'Org C', @@ -199,6 +211,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSentMes communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:01:25Z', errorMessage: undefined, + id: 3, recipientAddressOrNumber: 'email4@example.com', recipientName: 'Bob Brown', recipientOrganization: 'Org D', diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSubscribersFromSentMessages.test.ts b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSubscribersFromSentMessages.test.ts index 099b6c51b3..21b81ffbdc 100644 --- a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSubscribersFromSentMessages.test.ts +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSubscribersFromSentMessages.test.ts @@ -20,6 +20,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -44,6 +45,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -53,6 +55,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'SMS', dateTimeUtc: '2023-10-01T10:01:00Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: '1234567890', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -78,6 +81,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email1@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -87,6 +91,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'SMS', dateTimeUtc: '2023-10-01T10:01:00Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: '1234567890', recipientName: 'Jane Smith', recipientOrganization: 'Org B', @@ -96,6 +101,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'FAX', dateTimeUtc: '2023-10-01T10:02:00Z', errorMessage: undefined, + id: 3, recipientAddressOrNumber: '0987654321', recipientName: 'Alice Johnson', recipientOrganization: 'Org C', @@ -130,6 +136,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email1@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -139,6 +146,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:01:00Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: 'email2@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -163,6 +171,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'EMAIL', dateTimeUtc: '2023-10-01T10:00:00Z', errorMessage: undefined, + id: 1, recipientAddressOrNumber: 'email@example.com', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -172,6 +181,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'SMS', dateTimeUtc: '2023-10-01T10:01:00Z', errorMessage: undefined, + id: 2, recipientAddressOrNumber: '1234567890', recipientName: 'John Doe', recipientOrganization: 'Org A', @@ -181,6 +191,7 @@ describe('features/PriorNotification/components/shared/CardBodyHead > getSubscri communicationMeans: 'FAX', dateTimeUtc: '2023-10-01T10:02:00Z', errorMessage: undefined, + id: 3, recipientAddressOrNumber: '0987654321', recipientName: 'John Doe', recipientOrganization: 'Org A', From 7590006ad9a347e60cfa1cd1e28558313b33b2c1 Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Mon, 7 Oct 2024 09:04:59 +0200 Subject: [PATCH 5/6] Add e2e tests for manual & logbook pno verification pipeline --- .../behavior.spec.ts | 243 +++++++++++++- .../logbook_prior_notification_form/utils.ts | 309 ++++++++++++++++++ .../behavior.spec.ts | 258 ++++++++++++++- frontend/package-lock.json | 17 +- frontend/package.json | 2 +- 5 files changed, 818 insertions(+), 11 deletions(-) diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/behavior.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/behavior.spec.ts index e615768cb9..1cb9c93ab4 100644 --- a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/behavior.spec.ts +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/behavior.spec.ts @@ -1,6 +1,13 @@ +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' import dayjs from 'dayjs' -import { editSideWindowPriorNotification } from './utils' +import { + getPriorNotificationFakeResponse, + getPriorNotificationsFakeResponse, + editSideWindowPriorNotification, + getPriorNotificationSentMessagesFakeResponse +} from './utils' +import { openSideWindowPriorNotificationListAsSuperUser } from '../prior_notification_list/utils' context('Side Window > Logbook Prior Notification Form > Behavior', () => { it("Should show a banner, freeze the logbook prior notification form and button when it's in pending send", () => { @@ -37,4 +44,238 @@ context('Side Window > Logbook Prior Notification Form > Behavior', () => { } }) }) + + it('Should behave as expected when a logbook prior norification is sent, failed to be sent, resent and successfully sent', () => { + // ------------------------------------------------------------------------- + // Superuser opens a prior notification in edit mode + + const initialFakeParams = { + isManuallyCreated: false, + state: PriorNotification.State.OUT_OF_VERIFICATION_SCOPE, + updatedAt: dayjs().toISOString() + } + + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications?*' + }, + { + body: getPriorNotificationsFakeResponse(initialFakeParams) + } + ).as('getFakePriorNotifications') + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000?*' + }, + { + body: getPriorNotificationFakeResponse(initialFakeParams) + } + ).as('getFakePriorNotification') + + openSideWindowPriorNotificationListAsSuperUser() + cy.wait('@getFakePriorNotifications') + cy.clickButton('Éditer le préavis') + cy.wait('@getFakePriorNotification') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.intercept( + { + method: 'GET', + times: 2, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000/sent_messages' + }, + { + body: [] + } + ).as('getFakePriorNotificationSentMessages1') + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + cy.wait('@getFakePriorNotificationSentMessages1') + + cy.contains('Hors vérification').should('be.visible') + cy.contains('Aucun message n’a été envoyé pour ce préavis.').should('be.visible') + + // ------------------------------------------------------------------------- + // Superuser sends the prior notification + + cy.intercept( + { + method: 'POST', + times: 1, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000/verify_and_send?*' + }, + { + body: getPriorNotificationFakeResponse({ + isManuallyCreated: false, + state: PriorNotification.State.PENDING_SEND, + updatedAt: dayjs().toISOString() + }) + } + ).as('verifyAndSendFakePriorNotification') + + cy.clickButton('Diffuser') + cy.wait('@verifyAndSendFakePriorNotification') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + cy.wait('@getFakePriorNotificationSentMessages1') + + cy.contains('Le préavis est en cours de diffusion.').should('be.visible') + cy.clickButton('Masquer') + cy.contains('Diffusion en cours').should('be.visible') + cy.contains('Aucun message n’a été envoyé pour ce préavis.').should('be.visible') + + // ------------------------------------------------------------------------- + // Frontend automatically polls the prior notification 5s later + // and Backend API returns the prior notification as failed to be sent + + const failedSendFakeParams = { + isManuallyCreated: false, + state: PriorNotification.State.FAILED_SEND, + updatedAt: dayjs().toISOString() + } + const failedSentMessagesFakeResponse = getPriorNotificationSentMessagesFakeResponse({ + length: 3, + numberOfFailedMessages: 3, + sentAt: dayjs().subtract(35, 'seconds').toISOString() + }) + + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000?*' + }, + { + body: getPriorNotificationFakeResponse(failedSendFakeParams) + } + ).as('getFakePriorNotification') + cy.intercept( + { + method: 'GET', + times: 2, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000/sent_messages' + }, + { + body: failedSentMessagesFakeResponse + } + ).as('getFakePriorNotificationSentMessages2') + + cy.wait('@getFakePriorNotification') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + cy.wait('@getFakePriorNotificationSentMessages2') + + cy.contains('Échec de diffusion').should('be.visible') + cy.contains('Unité 1 (Organisation 1)').should('be.visible') + cy.contains('Unité 2 (Organisation 2)').should('be.visible') + cy.contains('Unité 3 (Organisation 3)').should('be.visible') + cy.contains( + 'Échec de la diffusion pour tous les contacts: unite3@organisation3.gouv.fr, unite2@organisation2.gouv.fr, unite1@organisation1.gouv.fr.' + ) + + // ------------------------------------------------------------------------- + // Superuser resends the prior notification + + cy.intercept( + { + method: 'POST', + times: 1, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000/verify_and_send?*' + }, + { + body: getPriorNotificationFakeResponse({ + isManuallyCreated: false, + state: PriorNotification.State.PENDING_SEND, + updatedAt: dayjs().toISOString() + }) + } + ).as('verifyAndSendFakePriorNotification') + + cy.clickButton('Diffuser') + cy.wait('@verifyAndSendFakePriorNotification') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + cy.wait('@getFakePriorNotificationSentMessages2') + + cy.contains('Le préavis est en cours de diffusion.').should('be.visible') + cy.clickButton('Masquer') + cy.contains('Diffusion en cours').should('be.visible') + cy.contains('Unité 1 (Organisation 1)').should('be.visible') + cy.contains('Unité 2 (Organisation 2)').should('be.visible') + cy.contains('Unité 3 (Organisation 3)').should('be.visible') + cy.contains( + 'Échec de la diffusion pour tous les contacts: unite3@organisation3.gouv.fr, unite2@organisation2.gouv.fr, unite1@organisation1.gouv.fr.' + ) + + // ------------------------------------------------------------------------- + // Frontend automatically polls the prior notification 5s later + // and Backend API returns the prior notification as failed to be sent + + const verifiedAndSentFakeParams = { + isManuallyCreated: false, + state: PriorNotification.State.VERIFIED_AND_SENT, + updatedAt: dayjs().toISOString() + } + + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000?*' + }, + { + body: getPriorNotificationFakeResponse(verifiedAndSentFakeParams) + } + ).as('getFakePriorNotification') + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/FAKE_OPERATION_000/sent_messages' + }, + { + body: [ + ...failedSentMessagesFakeResponse, + ...getPriorNotificationSentMessagesFakeResponse({ + length: 3, + numberOfFailedMessages: 0, + sentAt: dayjs().toISOString() + }) + ] + } + ).as('getFakePriorNotificationSentMessages3') + + cy.wait('@getFakePriorNotification') + // Fingerprint has changed which should trigger refetching + cy.wait('@getFakePriorNotificationSentMessages3') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + + cy.contains('Vérifié et diffusé').should('be.visible') + cy.contains('Unité 1 (Organisation 1)').should('be.visible') + cy.contains('Unité 2 (Organisation 2)').should('be.visible') + cy.contains('Unité 3 (Organisation 3)').should('be.visible') + cy.contains('Préavis diffusé avec succès à tous les contacts.') + cy.contains( + 'Échec de la diffusion pour tous les contacts: unite3@organisation3.gouv.fr, unite2@organisation2.gouv.fr, unite1@organisation1.gouv.fr.' + ) + }) }) diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/utils.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/utils.ts index 2b3ae091bf..77b7d0f946 100644 --- a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/utils.ts +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/utils.ts @@ -1,5 +1,14 @@ +import { Seafront } from '@constants/seafront' +import { faker } from '@faker-js/faker' +import { LogbookMessage } from '@features/Logbook/LogbookMessage.types' +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' +import dayjs from 'dayjs' + import { openSideWindowPriorNotificationListAsSuperUser } from '../prior_notification_list/utils' +import type { OrUndefinedToOrNull } from '../../types' +import type { BackendApi } from '@api/BackendApi.types' + // Both logbook and manual prior notifications export const editSideWindowPriorNotification = (vesselName: string, reportId: string) => { openSideWindowPriorNotificationListAsSuperUser() @@ -12,3 +21,303 @@ export const editSideWindowPriorNotification = (vesselName: string, reportId: st cy.getDataCy('first-loader').should('not.be.visible') } } + +export function getPriorNotificationsFakeResponse({ + isManuallyCreated, + state, + updatedAt +}: { + isManuallyCreated: boolean + state: PriorNotification.State + updatedAt: string +}): BackendApi.ResponseBodyPaginatedList< + OrUndefinedToOrNull, + LogbookMessage.ApiListExtraData +> { + const reportId = isManuallyCreated ? '00000000-0000-4000-0000-000000000000' : 'FAKE_OPERATION_000' + const createdAt = dayjs().subtract(1, 'hour').toISOString() + const expectedArrivalDate = dayjs().add(1, 'hour').toISOString() + const fingerprint = `${reportId}.${updatedAt}.${state}` + + return { + data: [ + { + acknowledgment: null, + createdAt, + expectedArrivalDate, + expectedLandingDate: expectedArrivalDate, + fingerprint, + isCorrection: false, + isInvalidated: null, + isManuallyCreated, + isPriorNotificationZero: false, + isVesselUnderCharter: false, + onBoardCatches: [ + { + conversionFactor: null, + economicZone: null, + effortZone: null, + faoZone: '21.1.C', + freshness: null, + nbFish: null, + packaging: null, + presentation: null, + preservationState: null, + species: 'AGS', + speciesName: 'SARDINELLE TACHETEE', + statisticalRectangle: null, + weight: 50.0 + } + ], + operationDate: createdAt, + portLocode: 'FRMRS', + portName: 'Marseille', + purposeCode: PriorNotification.PurposeCode.LAN, + reportId, + reportingCount: 0, + riskFactor: 3.2, + seafront: Seafront.MEMN, + sentAt: createdAt, + state, + tripGears: [{ dimensions: null, gear: 'OTT', gearName: null, mesh: null }], + tripSegments: [{ code: 'MED01', name: 'All Trawls 1' }], + types: [{ hasDesignatedPorts: false, minimumNotificationPeriod: 4.0, name: 'Préavis type A' }], + updatedAt, + vesselExternalReferenceNumber: 'EXTIMM121', + vesselFlagCountryCode: 'FR', + vesselId: 121, + vesselInternalReferenceNumber: 'CFR121', + vesselIrcs: 'IRCS121', + vesselLastControlDateTime: null, + vesselLength: 7.7, + vesselMmsi: 'MMSI121', + vesselName: 'MARE ET BASS' + } + ], + extraData: { + perSeafrontGroupCount: { + ALL: 1, + MED: 0, + MEMN: 1, + NAMO: 0, + NONE: 0, + OUTREMEROA: 0, + OUTREMEROI: 0, + SA: 0 + } + }, + lastPageNumber: 0, + pageNumber: 0, + pageSize: 50, + totalLength: 1 + } +} + +export function getPriorNotificationFakeResponse({ + isManuallyCreated, + state, + updatedAt +}: { + isManuallyCreated: boolean + state: PriorNotification.State + updatedAt: string +}): OrUndefinedToOrNull { + const reportId = isManuallyCreated ? '00000000-0000-4000-0000-000000000000' : 'FAKE_OPERATION_000' + const createdAt = dayjs().subtract(1, 'hour').toISOString() + const expectedArrivalDate = dayjs().add(1, 'hour').toISOString() + const fingerprint = `${reportId}.${updatedAt}.${state}` + const tripStartDate = dayjs().subtract(8, 'hours').toISOString() + + const commonData: OrUndefinedToOrNull< + Omit + > = { + fingerprint, + isLessThanTwelveMetersVessel: true, + isVesselUnderCharter: false, + logbookMessage: { + acknowledgment: null, + externalReferenceNumber: null, + flagState: 'FRA', + imo: null, + integrationDateTime: updatedAt, + internalReferenceNumber: 'CFR121', + ircs: null, + isCorrectedByNewerMessage: false, + isDeleted: false, + isSentByFailoverSoftware: false, + message: { + authorTrigram: 'ABC', + catchOnboard: [ + { + conversionFactor: null, + economicZone: null, + effortZone: null, + faoZone: '21.1.C', + freshness: null, + nbFish: null, + packaging: null, + presentation: null, + preservationState: null, + species: 'AGS', + speciesName: 'SARDINELLE TACHETEE', + statisticalRectangle: null, + weight: 50.0 + } + ], + catchToLand: [ + { + conversionFactor: null, + economicZone: null, + effortZone: null, + faoZone: '21.1.C', + freshness: null, + nbFish: null, + packaging: null, + presentation: null, + preservationState: null, + species: 'AGS', + speciesName: null, + statisticalRectangle: null, + weight: 50.0 + } + ], + economicZone: null, + effortZone: null, + faoZone: null, + hasPortEntranceAuthorization: null, + hasPortLandingAuthorization: null, + isBeingSent: false, + isInvalidated: null, + isInVerificationScope: false, + isSent: true, + isVerified: true, + latitude: null, + longitude: null, + note: null, + pnoTypes: [{ hasDesignatedPorts: false, minimumNotificationPeriod: 4.0, pnoTypeName: 'Préavis type A' }], + port: 'FRMRS', + portName: 'Marseille', + predictedArrivalDatetimeUtc: expectedArrivalDate, + predictedLandingDatetimeUtc: expectedArrivalDate, + purpose: PriorNotification.PurposeCode.LAN, + riskFactor: 3.2, + statisticalRectangle: null, + tripStartDate + }, + messageType: LogbookMessage.MessageType.PNO, + operationDateTime: updatedAt, + operationNumber: null, + operationType: LogbookMessage.OperationType.DAT, + rawMessage: null, + referencedReportId: null, + reportDateTime: updatedAt, + reportId, + tripGears: [{ dimensions: null, gear: 'OTT', gearName: null, mesh: null }], + tripNumber: null, + tripSegments: [{ code: 'MED01', name: 'All Trawls 1' }], + vesselName: 'MARE ET BASS' + }, + operationDate: updatedAt, + reportId, + riskFactor: 3.2, + state, + vesselId: 121 + } + + if (!isManuallyCreated) { + return { + ...commonData, + asLogbookForm: { + authorTrigram: 'ABC', + note: null + }, + asManualDraft: { + authorTrigram: 'ABC', + didNotFishAfterZeroNotice: false, + expectedArrivalDate, + expectedLandingDate: expectedArrivalDate, + fishingCatches: [ + { faoArea: null, quantity: null, specyCode: 'AGS', specyName: 'SARDINELLE TACHETEE', weight: 50.0 } + ], + globalFaoArea: '21.1.C', + hasPortEntranceAuthorization: true, + hasPortLandingAuthorization: true, + note: null, + portLocode: 'FRMRS', + purpose: PriorNotification.PurposeCode.LAN, + sentAt: updatedAt, + tripGearCodes: ['OTT'], + vesselId: 121 + }, + asManualForm: null, + isManuallyCreated: false + } + } + + return { + ...commonData, + asLogbookForm: null, + asManualDraft: null, + asManualForm: { + authorTrigram: 'ABC', + didNotFishAfterZeroNotice: false, + expectedArrivalDate, + expectedLandingDate: expectedArrivalDate, + fishingCatches: [ + { faoArea: null, quantity: null, specyCode: 'AGS', specyName: 'SARDINELLE TACHETEE', weight: 50.0 } + ], + globalFaoArea: '21.1.C', + hasPortEntranceAuthorization: true, + hasPortLandingAuthorization: true, + note: null, + portLocode: 'FRMRS', + purpose: PriorNotification.PurposeCode.LAN, + reportId, + sentAt: createdAt, + tripGearCodes: ['OTT'], + updatedAt, + vesselId: 121 + }, + isManuallyCreated: true + } +} + +export function getPriorNotificationSentMessagesFakeResponse({ + length, + numberOfFailedMessages, + sentAt +}: { + length: number + numberOfFailedMessages: number + sentAt: string +}): Array> { + const sentMessages = Array.from( + { length }, + (_, index) => + ({ + communicationMeans: 'EMAIL', + dateTimeUtc: dayjs(sentAt).subtract(index, 'seconds').toISOString(), + errorMessage: null, + id: index + 1, + recipientAddressOrNumber: `unite${index + 1}@organisation${index + 1}.gouv.fr`, + recipientName: `Unité ${index + 1}`, + recipientOrganization: `Organisation ${index + 1}`, + success: true + }) satisfies OrUndefinedToOrNull + ) + + return sentMessages.reduce[]>((acc, sentMessage, index) => { + if (index < numberOfFailedMessages) { + return [ + ...acc, + { + ...sentMessage, + errorMessage: faker.lorem.sentence(), + success: false + } + ] + } + + return [...acc, sentMessage] + }, []) +} diff --git a/frontend/cypress/e2e/side_window/manual_prior_notification_form/behavior.spec.ts b/frontend/cypress/e2e/side_window/manual_prior_notification_form/behavior.spec.ts index cceb1c56cc..3baf55742a 100644 --- a/frontend/cypress/e2e/side_window/manual_prior_notification_form/behavior.spec.ts +++ b/frontend/cypress/e2e/side_window/manual_prior_notification_form/behavior.spec.ts @@ -1,9 +1,17 @@ import { ALL_SEAFRONT_GROUP } from '@constants/seafront' +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' +import dayjs from 'dayjs' import { addManualSideWindowPriorNotification } from './utils' import { customDayjs } from '../../utils/customDayjs' import { getUtcDateInMultipleFormats } from '../../utils/getUtcDateInMultipleFormats' -import { editSideWindowPriorNotification } from '../logbook_prior_notification_form/utils' +import { + editSideWindowPriorNotification, + getPriorNotificationFakeResponse, + getPriorNotificationSentMessagesFakeResponse, + getPriorNotificationsFakeResponse +} from '../logbook_prior_notification_form/utils' +import { openSideWindowPriorNotificationListAsSuperUser } from '../prior_notification_list/utils' context('Side Window > Manual Prior Notification Form > Behavior', () => { it('Should ask for confirmation before closing form when manual prior notification form is dirty', () => { @@ -210,4 +218,252 @@ context('Side Window > Manual Prior Notification Form > Behavior', () => { cy.get('[id="fishingCatches[0].weight"]').should('have.value', '90') }) + + it('Should behave as expected when a manual prior norification is sent, failed to be sent, resent and successfully sent', () => { + // ------------------------------------------------------------------------- + // Superuser opens a prior notification in edit mode + + const initialFakeParams = { + isManuallyCreated: true, + state: PriorNotification.State.OUT_OF_VERIFICATION_SCOPE, + updatedAt: dayjs().toISOString() + } + + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications?*' + }, + { + body: getPriorNotificationsFakeResponse(initialFakeParams) + } + ).as('getFakePriorNotifications') + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000?*' + }, + { + body: getPriorNotificationFakeResponse(initialFakeParams) + } + ).as('getFakePriorNotification') + + openSideWindowPriorNotificationListAsSuperUser() + cy.wait('@getFakePriorNotifications') + cy.clickButton('Éditer le préavis') + cy.wait('@getFakePriorNotification') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.intercept( + { + method: 'GET', + times: 2, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000/sent_messages' + }, + { + body: [] + } + ).as('getFakePriorNotificationSentMessages1') + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + cy.wait('@getFakePriorNotificationSentMessages1') + + cy.contains('Hors vérification').should('be.visible') + cy.contains('Aucun message n’a été envoyé pour ce préavis.').should('be.visible') + + // ------------------------------------------------------------------------- + // Superuser sends the prior notification + + const pendingSendFakeParams = { + isManuallyCreated: true, + state: PriorNotification.State.PENDING_SEND, + updatedAt: dayjs().toISOString() + } + + cy.intercept( + { + method: 'POST', + times: 1, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000/verify_and_send?*' + }, + { + body: getPriorNotificationFakeResponse(pendingSendFakeParams) + } + ).as('verifyAndSendFakePriorNotification') + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000?*' + }, + { + body: getPriorNotificationFakeResponse(pendingSendFakeParams) + } + ).as('getFakePriorNotification') + + cy.clickButton('Diffuser') + cy.wait('@verifyAndSendFakePriorNotification') + // Use case should trigger a tag invalidation + cy.wait('@getFakePriorNotification') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + cy.wait('@getFakePriorNotificationSentMessages1') + + cy.contains('Le préavis est en cours de diffusion.').should('be.visible') + cy.clickButton('Masquer') + cy.contains('Diffusion en cours').should('be.visible') + cy.contains('Aucun message n’a été envoyé pour ce préavis.').should('be.visible') + + // ------------------------------------------------------------------------- + // Frontend automatically polls the prior notification 5s later + // and Backend API returns the prior notification as failed to be sent + + const failedSendFakeParams = { + isManuallyCreated: true, + state: PriorNotification.State.FAILED_SEND, + updatedAt: dayjs().toISOString() + } + const failedSentMessagesFakeResponse = getPriorNotificationSentMessagesFakeResponse({ + length: 3, + numberOfFailedMessages: 3, + sentAt: dayjs().subtract(35, 'seconds').toISOString() + }) + + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000?*' + }, + { + body: getPriorNotificationFakeResponse(failedSendFakeParams) + } + ).as('getFakePriorNotification') + cy.intercept( + { + method: 'GET', + times: 2, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000/sent_messages' + }, + { + body: failedSentMessagesFakeResponse + } + ).as('getFakePriorNotificationSentMessages2') + + cy.wait('@getFakePriorNotification') + // Fingerprint has changed which should trigger refetching + cy.wait('@getFakePriorNotificationSentMessages2') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + + cy.contains('Échec de diffusion').should('be.visible') + cy.contains('Unité 1 (Organisation 1)').should('be.visible') + cy.contains('Unité 2 (Organisation 2)').should('be.visible') + cy.contains('Unité 3 (Organisation 3)').should('be.visible') + cy.contains( + 'Échec de la diffusion pour tous les contacts: unite3@organisation3.gouv.fr, unite2@organisation2.gouv.fr, unite1@organisation1.gouv.fr.' + ) + + // ------------------------------------------------------------------------- + // Superuser resends the prior notification + + cy.intercept( + { + method: 'POST', + times: 1, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000/verify_and_send?*' + }, + { + body: getPriorNotificationFakeResponse({ + isManuallyCreated: true, + state: PriorNotification.State.PENDING_SEND, + updatedAt: dayjs().toISOString() + }) + } + ).as('verifyAndSendFakePriorNotification') + + cy.clickButton('Diffuser') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + cy.wait('@getFakePriorNotificationSentMessages2') + + cy.contains('Le préavis est en cours de diffusion.').should('be.visible') + cy.clickButton('Masquer') + cy.contains('Diffusion en cours').should('be.visible') + cy.contains('Unité 1 (Organisation 1)').should('be.visible') + cy.contains('Unité 2 (Organisation 2)').should('be.visible') + cy.contains('Unité 3 (Organisation 3)').should('be.visible') + cy.contains( + 'Échec de la diffusion pour tous les contacts: unite3@organisation3.gouv.fr, unite2@organisation2.gouv.fr, unite1@organisation1.gouv.fr.' + ) + + // ------------------------------------------------------------------------- + // Frontend automatically polls the prior notification 5s later + // and Backend API returns the prior notification as failed to be sent + + const verifiedAndSentFakeParams = { + isManuallyCreated: true, + state: PriorNotification.State.VERIFIED_AND_SENT, + updatedAt: dayjs().toISOString() + } + + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000?*' + }, + { + body: getPriorNotificationFakeResponse(verifiedAndSentFakeParams) + } + ).as('getFakePriorNotification') + cy.intercept( + { + method: 'GET', + times: 1, + url: '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000000/sent_messages' + }, + { + body: [ + ...failedSentMessagesFakeResponse, + ...getPriorNotificationSentMessagesFakeResponse({ + length: 3, + numberOfFailedMessages: 0, + sentAt: dayjs().toISOString() + }) + ] + } + ).as('getFakePriorNotificationSentMessages3') + + cy.wait('@getFakePriorNotification') + // Fingerprint has changed which should trigger refetching + cy.wait('@getFakePriorNotificationSentMessages3') + + // ------------------------------------------------------------------------- + // Superuser opens the prior notification sent messages + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + + cy.contains('Vérifié et diffusé').should('be.visible') + cy.contains('Unité 1 (Organisation 1)').should('be.visible') + cy.contains('Unité 2 (Organisation 2)').should('be.visible') + cy.contains('Unité 3 (Organisation 3)').should('be.visible') + cy.contains('Préavis diffusé avec succès à tous les contacts.') + cy.contains( + 'Échec de la diffusion pour tous les contacts: unite3@organisation3.gouv.fr, unite2@organisation2.gouv.fr, unite1@organisation1.gouv.fr.' + ) + }) }) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b6b8d1c11c..cc4ccfa9e9 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@dnd-kit/core": "6.1.0", "@dnd-kit/modifiers": "6.0.1", - "@mtes-mct/monitor-ui": "23.4.0", + "@mtes-mct/monitor-ui": "23.5.0", "@reduxjs/toolkit": "2.2.7", "@sentry/react": "8.32.0", "@tanstack/react-table": "8.20.5", @@ -717,9 +717,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", - "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", + "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -2488,11 +2488,12 @@ "license": "BSD-2-Clause" }, "node_modules/@mtes-mct/monitor-ui": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-23.4.0.tgz", - "integrity": "sha512-RyOE8h3HILzhC67Mnd+T67vs1d3xQXTiZiUa/TtYI+gRgqS1sgcra7Rxa3Fu2Xw+TjrKqZ2vA1sRF1CUJ6sxNw==", + "version": "23.5.0", + "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-23.5.0.tgz", + "integrity": "sha512-PuqVgbb7XiHY1I/9HvnyI8e4zwUdEXq93VMjXmNviCUBPdc3Q4WlZNSjgJe/gdH/PRF7+jQYtVG1EXn9lX8FPg==", + "license": "AGPL-3.0", "dependencies": { - "@babel/runtime": "7.25.6", + "@babel/runtime": "7.25.7", "@tanstack/react-table": "8.20.5", "@tanstack/react-virtual": "beta", "prop-types": "15.8.1", diff --git a/frontend/package.json b/frontend/package.json index d7eb3c7473..7e6420047b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -37,7 +37,7 @@ "dependencies": { "@dnd-kit/core": "6.1.0", "@dnd-kit/modifiers": "6.0.1", - "@mtes-mct/monitor-ui": "23.4.0", + "@mtes-mct/monitor-ui": "23.5.0", "@reduxjs/toolkit": "2.2.7", "@sentry/react": "8.32.0", "@tanstack/react-table": "8.20.5", From 6e5bd03f5ddbb2df109b07ff4514c1984f6a0ecb Mon Sep 17 00:00:00 2001 From: Ivan Gabriele Date: Mon, 7 Oct 2024 09:49:34 +0200 Subject: [PATCH 6/6] Fix styling in pno form sent message list --- .../shared/CardBodyHead/SentMessageList.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx index e5923e1524..0455287d81 100644 --- a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx @@ -26,11 +26,11 @@ export function SentMessageList({ detail, state }: SentMessageListProps) { <> {isFetching &&

Chargement en cours...

} {!isFetching && subscribers.length === 0 && ( -

+ {state === PriorNotification.State.FAILED_SEND ? `Aucune unité n'est inscrite à ce préavis.` : `Aucun message n’a été envoyé pour ce préavis.`} -

+ )} {!isFetching && subscribers.map(subsriber => ( @@ -52,7 +52,9 @@ export function SentMessageList({ detail, state }: SentMessageListProps) { {!isError && ( <> {isFetching &&

Chargement en cours...

} - {!isFetching && sentMessagesBatches.length === 0 &&

Aucun message n’a été envoyé pour ce préavis.

} + {!isFetching && sentMessagesBatches.length === 0 && ( + Aucun message n’a été envoyé pour ce préavis. + )} {!isFetching && sentMessagesBatches.length > 0 && ( {sentMessagesBatches.map(sentMessagesBatch => ( @@ -88,6 +90,11 @@ const Title = styled.p` margin: 16px 0 0; ` +const InfoMessage = styled.p` + color: ${p => p.theme.color.slateGray}; + font-style: italic; +` + const SubscriberRow = styled.address` background-color: ${p => p.theme.color.gainsboro}; display: flex; @@ -121,7 +128,7 @@ const HistoryItem = styled(Steps.Item)<{ $isSuccess: boolean }>` padding-bottom: 16px; - padding-left: 34px; + padding-left: 24px; > .rs-steps-item-icon-wrapper { border-radius: 0;