diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_card/behavior.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/behavior.spec.ts new file mode 100644 index 0000000000..b4de004b57 --- /dev/null +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/behavior.spec.ts @@ -0,0 +1,15 @@ +import { editSideWindowPriorNotification } from '../logbook_prior_notification_form/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", () => { + editSideWindowPriorNotification(`DES BARS`, 'FAKE_OPERATION_107') + + cy.get('.Component-Banner').contains(`Le préavis est en cours de diffusion.`) + + cy.get('textarea[name=note]').should('have.attr', 'readonly') + cy.get('input[name=authorTrigram]').should('have.attr', 'readonly') + + cy.contains('button', 'Télécharger').should('be.disabled') + cy.contains('button', 'Diffuser').should('be.disabled') + }) +}) diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_card/card.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/card.spec.ts new file mode 100644 index 0000000000..d472a6d8b8 --- /dev/null +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/card.spec.ts @@ -0,0 +1,118 @@ +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' + +import { openSideWindowPriorNotificationCardAsUser } from './utils' + +context('Side Window > Logbook Prior Notification Card > Card', () => { + it('Should display a logbook prior notification corrected message as expected', () => { + openSideWindowPriorNotificationCardAsUser(`L'ANCRE`, 'FAKE_OPERATION_109_COR') + + // Title + cy.contains(`Préavis navire < 12 M`).should('be.visible') + cy.contains(`L'ANCRE SÈCHE (CFR106)`).should('be.visible') + + // Message Header + cy.contains(`PNO`).should('be.visible') + cy.contains(`Préavis (notification de retour au port)`).should('be.visible') + cy.contains(`MESSAGE CORRIGÉ`).should('be.visible') + + // Message Body + cy.contains(`Vannes (FRVNE)`).should('be.visible') + cy.contains(`Débarquement (LAN)`).should('be.visible') + cy.contains(`BATHYBATES FEROX (BHX)`).should('be.visible') + cy.contains(`32.5 kg`).should('be.visible') + }) + + it('Should display a logbook prior notification successfully acknowledged message as expected', () => { + openSideWindowPriorNotificationCardAsUser(`BARS`, 'FAKE_OPERATION_107') + + // Title + cy.contains(`Préavis navire ≥ 12 M`).should('be.visible') + cy.contains(`DES BARS (CFR104)`).should('be.visible') + + // Message Header + cy.contains(`PNO`).should('be.visible') + cy.contains(`Préavis (notification de retour au port)`).should('be.visible') + + // Message Body + cy.getDataCy('LogbookMessage-successful-acknowledgement-icon').should('be.visible') + cy.contains(`Saint-Malo (FRSML)`).should('be.visible') + cy.contains(`Débarquement (LAN)`).should('be.visible') + cy.contains(`MORUE COMMUNE (CABILLAUD) (COD)`).should('be.visible') + cy.contains(`25 kg`).should('be.visible') + }) + + it('Should refresh the list when the opened logbook prior notification data differs from its entry in the current list', () => { + const url = '/bff/v1/prior_notifications/FAKE_OPERATION_109_COR?isManuallyCreated=false&operationDate=*' + + cy.intercept({ + method: 'GET', + times: 1, + url + }).as('getOriginalPriorNotification') + + openSideWindowPriorNotificationCardAsUser(`L'ANCRE`, 'FAKE_OPERATION_109_COR') + + cy.wait('@getOriginalPriorNotification').then(interception => { + const originalPriorNotificationDetail: PriorNotification.Detail = interception.response!.body + const updatedPriorNotificationDetailStub: PriorNotification.Detail = { + ...originalPriorNotificationDetail, + fingerprint: '109.1109.2109' + } + + cy.reload() + + cy.fill('Rechercher un navire', `L'ANCRE`) + + cy.intercept('GET', url, { body: updatedPriorNotificationDetailStub }).as('getUpdatedPriorNotification') + cy.intercept('GET', '/bff/v1/prior_notifications?*').as('getPriorNotifications') + + cy.getTableRowById('FAKE_OPERATION_109_COR').clickButton('Consulter le préavis') + + cy.wait('@getUpdatedPriorNotification') + cy.wait('@getPriorNotifications') + + cy.contains(`L'ANCRE SÈCHE (CFR106)`).should('be.visible') + }) + }) + + it('Should display a warning banner and refresh the list when the opened logbook prior notification has been deleted', () => { + const url = '/bff/v1/prior_notifications/FAKE_OPERATION_109_COR?isManuallyCreated=false&operationDate=*' + + cy.intercept({ + method: 'GET', + times: 1, + url + }).as('getOriginalPriorNotification') + + openSideWindowPriorNotificationCardAsUser(`L'ANCRE`, 'FAKE_OPERATION_109_COR') + + cy.wait('@getOriginalPriorNotification').then(interception => { + const originalPriorNotificationDetail: PriorNotification.Detail = interception.response!.body + const deletedPriorNotificationDetailStub: PriorNotification.Detail = { + ...originalPriorNotificationDetail, + fingerprint: '109.1109.2109', + logbookMessage: { + ...originalPriorNotificationDetail.logbookMessage, + isDeleted: true + } + } + + cy.reload() + + cy.fill('Rechercher un navire', `L'ANCRE`) + + cy.intercept('GET', url, { body: deletedPriorNotificationDetailStub }).as('getDeletedPriorNotification') + cy.intercept('GET', '/bff/v1/prior_notifications?*').as('getPriorNotifications') + + cy.clickButton('Consulter le préavis') + + cy.wait('@getDeletedPriorNotification') + cy.wait('@getPriorNotifications') + + // The warning banner should be displayed + cy.contains(`Ce préavis a été supprimé (entre temps).`).should('be.visible') + // The card should be closed + cy.contains(`L'ANCRE SÈCHE (CFR106)`).should('not.exist') + }) + }) +}) diff --git a/frontend/cypress/e2e/side_window/prior_notification_card/error_handling.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/error_handling.spec.ts similarity index 78% rename from frontend/cypress/e2e/side_window/prior_notification_card/error_handling.spec.ts rename to frontend/cypress/e2e/side_window/logbook_prior_notification_card/error_handling.spec.ts index 0250ec3fa4..d361e21e94 100644 --- a/frontend/cypress/e2e/side_window/prior_notification_card/error_handling.spec.ts +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/error_handling.spec.ts @@ -1,15 +1,11 @@ import { RTK_MAX_RETRIES } from '@api/constants' -import { openSideWindowPriorNotification } from './utils' +import { openSideWindowPriorNotificationCardAsUser } from './utils' context('Side Window > Logbook Prior Notification Card > Error Handling', () => { const failedQueryCount = RTK_MAX_RETRIES + 1 const url = '/bff/v1/prior_notifications/FAKE_OPERATION_109_COR?isManuallyCreated=false&operationDate=*' - beforeEach(() => { - cy.intercept('/bff/v1/authorization/current', { statusCode: 401 }).as('getIsSuperUser') - }) - it('Should handle fetching error as expected', () => { cy.intercept( { @@ -22,7 +18,7 @@ context('Side Window > Logbook Prior Notification Card > Error Handling', () => } ).as('getPriorNotificationsWithError') - openSideWindowPriorNotification(`L'ANCRE`, false) + openSideWindowPriorNotificationCardAsUser(`L'ANCRE`, 'FAKE_OPERATION_109_COR') for (let i = 1; i <= failedQueryCount; i += 1) { cy.wait('@getPriorNotificationsWithError') diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_card/utils.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/utils.ts new file mode 100644 index 0000000000..276b533b34 --- /dev/null +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_card/utils.ts @@ -0,0 +1,16 @@ +import { openSideWindowPriorNotificationListAsUser } from '../prior_notification_list/utils' + +// Cards can only be opened as User, SuperUser open them as forms +export const openSideWindowPriorNotificationCardAsUser = (vesselName: string, reportId: string) => { + openSideWindowPriorNotificationListAsUser() + + cy.get('.Table-SimpleTable tr').should('have.length.to.be.greaterThan', 0) + + cy.get('[data-cy="side-window-sub-menu-ALL"]').click() + cy.fill('Rechercher un navire', vesselName) + + cy.getTableRowById(reportId as any).clickButton('Consulter le préavis') + if (document.querySelector('[data-cy="first-loader"]')) { + cy.getDataCy('first-loader').should('not.be.visible') + } +} diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts index 26100c5f9b..e676e4fd88 100644 --- a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts @@ -1,6 +1,6 @@ import { RTK_MAX_RETRIES } from '@api/constants' -import { editSideWindowPriorNotification } from '../manual_prior_notification_form/utils' +import { editSideWindowPriorNotification } from './utils' context('Side Window > Logbook Prior Notification Form > Error Handling', () => { const failedQueryCount = RTK_MAX_RETRIES + 1 diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/form.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/form.spec.ts index d2e25145f0..d60be457d4 100644 --- a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/form.spec.ts +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/form.spec.ts @@ -1,9 +1,55 @@ +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' import dayjs from 'dayjs' -import { editSideWindowPriorNotification } from '../manual_prior_notification_form/utils' +import { editSideWindowPriorNotification } from './utils' +import { openSideWindowPriorNotificationListAsSuperUser } from '../prior_notification_list/utils' context('Side Window > Logbook Prior Notification Form > Form', () => { - it('Should not update the form with a PUT request on first render', () => { + it('Should update a logbook prior notification', () => { + // Reset + const operationDate = dayjs().subtract(6, 'hours').toISOString() + cy.request('PUT', `/bff/v1/prior_notifications/logbook/FAKE_OPERATION_114?operationDate=${operationDate}`, { + body: { + authorTrigram: null, + note: null + } + }) + + // Given + editSideWindowPriorNotification(`MER À BOIRE`, 'FAKE_OPERATION_114') + + cy.intercept('PUT', `/bff/v1/prior_notifications/logbook/FAKE_OPERATION_114?operationDate=*`).as( + 'updateLogbookPriorNotification' + ) + + cy.get('[name="note"]').should('have.value', '') + cy.get('[name="authorTrigram"]').should('have.value', '') + + // When + cy.fill("Points d'attention identifiés par le CNSP", "Un point d'attention.") + cy.fill('Par', 'ABC') + + cy.wait('@updateLogbookPriorNotification') + + // Then, the PDF is deleted + cy.get('.Element-Button').contains('Télécharger').parent().should('be.disabled') + + // The note is saved + editSideWindowPriorNotification(`MER À BOIRE`, 'FAKE_OPERATION_114') + + cy.get('[name="note"]').should('have.value', "Un point d'attention.") + cy.get('[name="authorTrigram"]').should('have.value', 'ABC') + + // Reset + cy.request('PUT', `/bff/v1/prior_notifications/logbook/FAKE_OPERATION_114?operationDate=${operationDate}`, { + body: { + authorTrigram: null, + note: null + } + }) + }) + + it('Should not update the logbook prior notification before the form is filled', () => { cy.intercept('PUT', '/bff/v1/prior_notifications/logbook/FAKE_OPERATION_115*', cy.spy().as('updateForm')) editSideWindowPriorNotification(`LE MARIN`, 'FAKE_OPERATION_115') @@ -25,4 +71,79 @@ context('Side Window > Logbook Prior Notification Form > Form', () => { } }) }) + + it('Should verify and send a logbook prior notification', () => { + cy.intercept( + 'POST', + `/bff/v1/prior_notifications/FAKE_OPERATION_111_COR_ORPHAN/verify_and_send?isManuallyCreated=false&operationDate=*` + ).as('verifyAndSendPriorNotification') + + editSideWindowPriorNotification(`LE POISSON AMBULANT`, 'FAKE_OPERATION_111_COR_ORPHAN') + + cy.clickButton('Diffuser') + + cy.wait('@verifyAndSendPriorNotification').then(verifyAndSendInterception => { + if (!verifyAndSendInterception.response) { + assert.fail('`verifyAndSendInterception.response` is undefined.') + } + + const updatedPriorNotification = verifyAndSendInterception.response.body + + assert.deepInclude(updatedPriorNotification, { + state: PriorNotification.State.PENDING_SEND + }) + + cy.contains('Diffusion en cours') + + // ----------------------------------------------------------------------- + // List + + cy.clickButton('Fermer') + cy.fill('Rechercher un navire', 'LE POISSON AMBULANT') + + cy.getTableRowById('FAKE_OPERATION_111_COR_ORPHAN').find('span[title="Diffusion en cours"]').should('be.visible') + }) + }) + + it('Should download a logbook prior notification as a PDF document', () => { + // Given + editSideWindowPriorNotification(`COURANT MAIN PROFESSEUR`, 'FAKE_OPERATION_102') + + // Spy on the window.open method + cy.window().then(win => { + cy.stub(win, 'open').as('windowOpen') + }) + + // When + cy.clickButton('Télécharger') + + // Verify that window.open was called with the correct URL + cy.get('@windowOpen').should('be.calledWith', '/api/v1/prior_notifications/pdf/FAKE_OPERATION_102', '_blank') + }) + + it('Should invalidate a logbook prior notification', () => { + // Given + openSideWindowPriorNotificationListAsSuperUser() + cy.get('[data-cy="side-window-sub-menu-ALL"]').click() + cy.fill('Rechercher un navire', 'ANCRE') + + cy.getTableRowById('FAKE_OPERATION_109_COR').find('[title="Préavis invalidé"]').should('not.exist') + + cy.getTableRowById('FAKE_OPERATION_109_COR').clickButton('Éditer le préavis') + if (document.querySelector('[data-cy="first-loader"]')) { + cy.getDataCy('first-loader').should('not.be.visible') + } + + // When + cy.clickButton('Invalider le préavis') + cy.clickButton('Confirmer l’invalidation') + + // Then + cy.get('.Wrapper').contains('Invalidé') + cy.get('[title="Invalider le préavis"]').should('not.exist') + + cy.clickButton('Fermer') + + cy.getTableRowById('FAKE_OPERATION_109_COR').find('[title="Préavis invalidé"]').should('exist') + }) }) 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 new file mode 100644 index 0000000000..2b3ae091bf --- /dev/null +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/utils.ts @@ -0,0 +1,14 @@ +import { openSideWindowPriorNotificationListAsSuperUser } from '../prior_notification_list/utils' + +// Both logbook and manual prior notifications +export const editSideWindowPriorNotification = (vesselName: string, reportId: string) => { + openSideWindowPriorNotificationListAsSuperUser() + + cy.get('[data-cy="side-window-sub-menu-ALL"]').click() + cy.fill('Rechercher un navire', vesselName) + + cy.getTableRowById(reportId).clickButton('Éditer le préavis') + if (document.querySelector('[data-cy="first-loader"]')) { + cy.getDataCy('first-loader').should('not.be.visible') + } +} diff --git a/frontend/cypress/e2e/side_window/manual_prior_notification_card/card.spec.ts b/frontend/cypress/e2e/side_window/manual_prior_notification_card/card.spec.ts new file mode 100644 index 0000000000..f6f14703b2 --- /dev/null +++ b/frontend/cypress/e2e/side_window/manual_prior_notification_card/card.spec.ts @@ -0,0 +1,54 @@ +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' + +import { openSideWindowPriorNotificationCardAsUser } from '../logbook_prior_notification_card/utils' + +context('Side Window > Manual Prior Notification Card > Card', () => { + it('Should display a read-only manual prior notification form', () => { + openSideWindowPriorNotificationCardAsUser(`POISSON PAS NET`, '00000000-0000-4000-0000-000000000001') + + // Title + cy.contains(`Préavis navire < 12 M`).should('be.visible') + cy.contains(`POISSON PAS NET (CFR112)`).should('be.visible') + + // Message Header + cy.contains(`Préavis (notification de retour au port) – navire sans JPE`).should('be.visible') + + // Message Body + cy.contains(`Filets soulevés portatifs (LNP)`).should('be.visible') + }) + + it('Should refresh the list when the opened manual prior notification data differs from its entry in the current list', () => { + const url = + '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000001?isManuallyCreated=true&operationDate=*' + + cy.intercept({ + method: 'GET', + times: 1, + url + }).as('getOriginalPriorNotification') + + openSideWindowPriorNotificationCardAsUser(`POISSON PAS NET`, '00000000-0000-4000-0000-000000000001') + + cy.wait('@getOriginalPriorNotification').then(interception => { + const originalPriorNotificationDetail: PriorNotification.Detail = interception.response!.body + const updatedPriorNotificationDetailStub: PriorNotification.Detail = { + ...originalPriorNotificationDetail, + fingerprint: '109.1109.2109' + } + + cy.reload() + + cy.fill('Rechercher un navire', `POISSON`) + + cy.intercept('GET', url, { body: updatedPriorNotificationDetailStub }).as('getUpdatedPriorNotification') + cy.intercept('GET', '/bff/v1/prior_notifications?*').as('getPriorNotifications') + + cy.getTableRowById('00000000-0000-4000-0000-000000000001').clickButton('Consulter le préavis') + + cy.wait('@getUpdatedPriorNotification') + cy.wait('@getPriorNotifications') + + cy.contains(`POISSON PAS NET (CFR112)`).should('be.visible') + }) + }) +}) diff --git a/frontend/cypress/e2e/side_window/manual_prior_notification_card/error_handling.spec.ts b/frontend/cypress/e2e/side_window/manual_prior_notification_card/error_handling.spec.ts new file mode 100644 index 0000000000..e296ed75d3 --- /dev/null +++ b/frontend/cypress/e2e/side_window/manual_prior_notification_card/error_handling.spec.ts @@ -0,0 +1,35 @@ +import { RTK_MAX_RETRIES } from '@api/constants' + +import { openSideWindowPriorNotificationCardAsUser } from '../logbook_prior_notification_card/utils' + +context('Side Window > Manual Prior Notification Card > Error Handling', () => { + const failedQueryCount = RTK_MAX_RETRIES + 1 + const url = '/bff/v1/prior_notifications/00000000-0000-4000-0000-000000000001?isManuallyCreated=true&operationDate=*' + + it('Should handle fetching error as expected', () => { + cy.intercept( + { + method: 'GET', + times: failedQueryCount, + url + }, + { + statusCode: 400 + } + ).as('getPriorNotificationsWithError') + + openSideWindowPriorNotificationCardAsUser(`POISSON PAS NET`, '00000000-0000-4000-0000-000000000001') + + for (let i = 1; i <= failedQueryCount; i += 1) { + cy.wait('@getPriorNotificationsWithError') + } + + cy.intercept('GET', url).as('getPriorNotification') + + cy.clickButton('Réessayer') + + cy.wait('@getPriorNotification') + + cy.contains(`POISSON PAS NET (CFR112)`).should('be.visible') + }) +}) 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 2e6ff963a4..fa2a68bfa4 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,18 +1,19 @@ import { ALL_SEAFRONT_GROUP } from '@constants/seafront' -import { addSideWindowPriorNotification, editSideWindowPriorNotification } from './utils' +import { addManualSideWindowPriorNotification } from './utils' import { customDayjs } from '../../utils/customDayjs' import { getUtcDateInMultipleFormats } from '../../utils/getUtcDateInMultipleFormats' +import { editSideWindowPriorNotification } from '../logbook_prior_notification_form/utils' context('Side Window > Manual Prior Notification Form > Behavior', () => { - it('Should ask for confirmation before closing form when form is dirty', () => { + it('Should ask for confirmation before closing form when manual prior notification form is dirty', () => { const { utcDateTupleWithTime: arrivalDateTupleWithTime } = getUtcDateInMultipleFormats( customDayjs().add(2, 'hours').startOf('minute').toISOString() ) cy.intercept('POST', '/bff/v1/prior_notifications/manual').as('createPriorNotification') - addSideWindowPriorNotification() + addManualSideWindowPriorNotification() cy.getDataCy('vessel-search-input').click().wait(500) cy.getDataCy('vessel-search-input').type('PAGEOT JO', { delay: 100 }) @@ -27,7 +28,7 @@ context('Side Window > Manual Prior Notification Form > Behavior', () => { cy.contains('Abandon de préavis').should('be.visible') cy.clickButton('Annuler') - cy.getDataCy('Card-overlay').click() + cy.getDataCy('SideWindowCard-overlay').click() cy.contains('Abandon de préavis').should('be.visible') cy.clickButton('Annuler') @@ -51,7 +52,7 @@ context('Side Window > Manual Prior Notification Form > Behavior', () => { cy.contains('Abandon de préavis').should('be.visible') cy.clickButton('Annuler') - cy.getDataCy('Card-overlay').click() + cy.getDataCy('SideWindowCard-overlay').click() cy.contains('Abandon de préavis').should('be.visible') cy.clickButton('Annuler') @@ -77,7 +78,7 @@ context('Side Window > Manual Prior Notification Form > Behavior', () => { cy.clickButton('Fermer') cy.get('.Component-Dialog').should('not.exist') - cy.getDataCy('Card-overlay').should('not.exist') + cy.getDataCy('SideWindowCard-overlay').should('not.exist') editSideWindowPriorNotification('PAGEOT JO', createdPriorNotification.reportId) @@ -93,7 +94,7 @@ context('Side Window > Manual Prior Notification Form > Behavior', () => { cy.contains('Abandon de préavis').should('be.visible') cy.clickButton('Annuler') - cy.getDataCy('Card-overlay').click() + cy.getDataCy('SideWindowCard-overlay').click() cy.contains('Abandon de préavis').should('be.visible') cy.clickButton('Annuler') @@ -103,7 +104,31 @@ context('Side Window > Manual Prior Notification Form > Behavior', () => { cy.clickButton('Fermer') cy.get('.Component-Dialog').should('not.exist') - cy.getDataCy('Card-overlay').should('not.exist') + cy.getDataCy('SideWindowCard-overlay').should('not.exist') }) }) + + it("Should show a banner, freeze the manual prior notification form and button when it's in pending send", () => { + editSideWindowPriorNotification(`VIVA L'ITALIA`, '00000000-0000-4000-0000-000000000005') + + cy.get('.Component-Banner').contains(`Le préavis est en cours de diffusion.`) + + cy.get('textarea[name=note]').should('have.attr', 'readonly') + cy.get('input[name=authorTrigram]').should('have.attr', 'readonly') + + cy.contains('button', 'Enregistrer').should('be.disabled') + cy.contains('button', 'Diffuser').should('be.disabled') + }) + + it("Should show a banner, freeze the manual prior notification form and button when it's in pending auto-send", () => { + editSideWindowPriorNotification(`DOS FIN`, '00000000-0000-4000-0000-000000000002') + + cy.get('.Component-Banner').contains(`Le préavis est en cours d’envoi aux unités qui l’ont demandé.`) + + cy.get('textarea[name=note]').should('have.attr', 'readonly') + cy.get('input[name=authorTrigram]').should('have.attr', 'readonly') + + cy.contains('button', 'Enregistrer').should('be.disabled') + cy.contains('button', 'Diffuser').should('be.disabled') + }) }) diff --git a/frontend/cypress/e2e/side_window/manual_prior_notification_form/error_handling.spec.ts b/frontend/cypress/e2e/side_window/manual_prior_notification_form/error_handling.spec.ts index f1622d60f8..1430433d84 100644 --- a/frontend/cypress/e2e/side_window/manual_prior_notification_form/error_handling.spec.ts +++ b/frontend/cypress/e2e/side_window/manual_prior_notification_form/error_handling.spec.ts @@ -1,6 +1,6 @@ import { RTK_MAX_RETRIES } from '@api/constants' -import { editSideWindowPriorNotification } from './utils' +import { editSideWindowPriorNotification } from '../logbook_prior_notification_form/utils' context('Side Window > Manual Prior Notification Form > Error Handling', () => { const failedQueryCount = RTK_MAX_RETRIES + 1 diff --git a/frontend/cypress/e2e/side_window/manual_prior_notification_form/form.spec.ts b/frontend/cypress/e2e/side_window/manual_prior_notification_form/form.spec.ts index 44bb9647f7..0c4a995d8e 100644 --- a/frontend/cypress/e2e/side_window/manual_prior_notification_form/form.spec.ts +++ b/frontend/cypress/e2e/side_window/manual_prior_notification_form/form.spec.ts @@ -1,11 +1,12 @@ import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' import { omit } from 'lodash' -import { addSideWindowPriorNotification, editSideWindowPriorNotification } from './utils' +import { addManualSideWindowPriorNotification } from './utils' import { customDayjs } from '../../utils/customDayjs' import { getUtcDateInMultipleFormats } from '../../utils/getUtcDateInMultipleFormats' import { isDateCloseTo } from '../../utils/isDateCloseTo' -import { openSideWindowPriorNotificationList } from '../prior_notification_list/utils' +import { editSideWindowPriorNotification } from '../logbook_prior_notification_form/utils' +import { openSideWindowPriorNotificationListAsSuperUser } from '../prior_notification_list/utils' context('Side Window > Manual Prior Notification Form > Form', () => { it('Should add and edit a manual prior notification', () => { @@ -20,7 +21,7 @@ context('Side Window > Manual Prior Notification Form > Form', () => { cy.intercept('POST', '/bff/v1/prior_notifications/manual').as('createPriorNotification') - addSideWindowPriorNotification() + addManualSideWindowPriorNotification() cy.getDataCy('vessel-search-input').click().wait(500) cy.getDataCy('vessel-search-input').type('PAGEOT JO', { delay: 100 }) @@ -135,13 +136,13 @@ context('Side Window > Manual Prior Notification Form > Form', () => { }) }) - it('Should display the expected form validation errors', () => { + it('Should display the expected manual prior notification form validation errors', () => { // ------------------------------------------------------------------------- // Base form validation errors const { utcDateTupleWithTime } = getUtcDateInMultipleFormats(customDayjs().toISOString()) - addSideWindowPriorNotification() + addManualSideWindowPriorNotification() cy.fill('Date et heure de réception du préavis (UTC)', undefined) @@ -212,7 +213,7 @@ context('Side Window > Manual Prior Notification Form > Form', () => { cy.contains('Créer le préavis').should('be.enabled') }) - it('Should calculate and display fleet segments, risk factor & types', () => { + it('Should calculate and display manual prior notification fleet segments, risk factor & types', () => { // ------------------------------------------------------------------------- // Add @@ -223,7 +224,7 @@ context('Side Window > Manual Prior Notification Form > Form', () => { cy.intercept('POST', '/bff/v1/prior_notifications/manual').as('createPriorNotification') cy.intercept('POST', '/bff/v1/prior_notifications/manual/compute').as('computePriorNotification') - addSideWindowPriorNotification() + addManualSideWindowPriorNotification() cy.getDataCy('vessel-search-input').click().wait(500) cy.getDataCy('vessel-search-input').type('IN-ARÊTE-ABLE', { delay: 100 }) @@ -279,7 +280,7 @@ context('Side Window > Manual Prior Notification Form > Form', () => { // ----------------------------------------------------------------------- // List - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.fill('Rechercher un navire', 'IN-ARÊTE-ABLE') // TODO Check if we need to update the vessel risk factor in DB while saving a prior notification. @@ -328,7 +329,7 @@ context('Side Window > Manual Prior Notification Form > Form', () => { // ----------------------------------------------------------------------- // List - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.fill('Rechercher un navire', 'IN-ARÊTE-ABLE') cy.getTableRowById(createdPriorNotification.reportId).contains('NWW01/02') @@ -338,11 +339,11 @@ context('Side Window > Manual Prior Notification Form > Form', () => { }) }) - it('Should only recalculate fleet segments, risk factor & types when necessary (creation)', () => { + it('Should only recalculate manual prior notification fleet segments, risk factor & types when necessary (creation)', () => { cy.intercept('POST', '/bff/v1/prior_notifications/manual/compute').as('computePriorNotification') cy.resetCountRequestsByAlias('@computePriorNotification') - addSideWindowPriorNotification() + addManualSideWindowPriorNotification() cy.countRequestsByAlias('@computePriorNotification', 1500).should('be.equal', 0) @@ -382,7 +383,7 @@ context('Side Window > Manual Prior Notification Form > Form', () => { cy.countRequestsByAlias('@computePriorNotification', 1500).should('be.equal', 1) }) - it('Should only recalculate fleet segments, risk factor & types when necessary (edition)', () => { + it('Should only recalculate manual prior notification fleet segments, risk factor & types when necessary (edition)', () => { cy.intercept('POST', '/bff/v1/prior_notifications/manual/compute').as('computePriorNotification') cy.resetCountRequestsByAlias('@computePriorNotification') @@ -463,7 +464,7 @@ context('Side Window > Manual Prior Notification Form > Form', () => { /\/bff\/v1\/prior_notifications\/[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}\?isManuallyCreated=true&operationDate=.*/i ).as('getPriorNotification') - addSideWindowPriorNotification() + addManualSideWindowPriorNotification() cy.getDataCy('vessel-search-input').click().wait(500) cy.getDataCy('vessel-search-input').type('IN-ARÊTE-ABLE', { delay: 100 }) @@ -555,8 +556,6 @@ context('Side Window > Manual Prior Notification Form > Form', () => { // Then cy.clickButton('Fermer') - cy.getTableRowById('00000000-0000-4000-0000-000000000001' as any) - .find('[title="Préavis invalidé"]') - .should('exist') + cy.getTableRowById('00000000-0000-4000-0000-000000000001').find('[title="Préavis invalidé"]').should('exist') }) }) diff --git a/frontend/cypress/e2e/side_window/manual_prior_notification_form/utils.ts b/frontend/cypress/e2e/side_window/manual_prior_notification_form/utils.ts index cf4a49d045..2e0dd9aaba 100644 --- a/frontend/cypress/e2e/side_window/manual_prior_notification_form/utils.ts +++ b/frontend/cypress/e2e/side_window/manual_prior_notification_form/utils.ts @@ -1,45 +1,10 @@ -import { SideWindowMenuLabel } from 'domain/entities/sideWindow/constants' +import { openSideWindowPriorNotificationListAsSuperUser } from '../prior_notification_list/utils' -export const addSideWindowPriorNotification = () => { - cy.viewport(1920, 1080) - cy.visit('/side_window') - cy.wait(500) - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } - - cy.clickButton(SideWindowMenuLabel.PRIOR_NOTIFICATION_LIST) - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } - cy.get('.Table-SimpleTable tr').should('have.length.to.be.greaterThan', 0) +export const addManualSideWindowPriorNotification = () => { + openSideWindowPriorNotificationListAsSuperUser() cy.clickButton('Ajouter un préavis') if (document.querySelector('[data-cy="first-loader"]')) { cy.getDataCy('first-loader').should('not.be.visible') } } - -export const editSideWindowPriorNotification = (vesselName: string, reportId: string) => { - cy.viewport(1920, 1080) - cy.visit('/side_window') - cy.wait(500) - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } - - cy.clickButton(SideWindowMenuLabel.PRIOR_NOTIFICATION_LIST) - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } - cy.get('.Table-SimpleTable tr').should('have.length.to.be.greaterThan', 0) - - cy.get('[data-cy="side-window-sub-menu-ALL"]').click() - cy.fill('Rechercher un navire', vesselName) - - // TODO Allow for `string` type in monitor-ui. - cy.getTableRowById(reportId as any).clickButton('Éditer le préavis') - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } -} diff --git a/frontend/cypress/e2e/side_window/prior_notification_card/card.spec.ts b/frontend/cypress/e2e/side_window/prior_notification_card/card.spec.ts deleted file mode 100644 index ba4ae5e59f..0000000000 --- a/frontend/cypress/e2e/side_window/prior_notification_card/card.spec.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' -import dayjs from 'dayjs' - -import { openSideWindowPriorNotification } from './utils' -import { openSideWindowPriorNotificationList } from '../prior_notification_list/utils' - -context('Side Window > Prior Notification Card > Card', () => { - it('Should display a corrected message as expected', () => { - openSideWindowPriorNotification(`L'ANCRE`) - - // Title - cy.contains(`Préavis navire < 12 M`).should('be.visible') - cy.contains(`L'ANCRE SÈCHE (CFR106)`).should('be.visible') - - // Message Header - cy.contains(`PNO`).should('be.visible') - cy.contains(`Préavis (notification de retour au port)`).should('be.visible') - cy.contains(`MESSAGE CORRIGÉ`).should('be.visible') - - // Message Body - cy.contains(`Vannes (FRVNE)`).should('be.visible') - cy.contains(`Débarquement (LAN)`).should('be.visible') - cy.contains(`BATHYBATES FEROX (BHX)`).should('be.visible') - cy.contains(`32.5 kg`).should('be.visible') - }) - - it('Should display a non-editable message for a non-super user', () => { - cy.intercept('/bff/v1/authorization/current', { statusCode: 401 }).as('getIsSuperUser') - openSideWindowPriorNotification(`POISSON PAS NET`, false) - cy.wait('@getIsSuperUser') - - // Title - cy.contains(`Préavis navire < 12 M`).should('be.visible') - cy.contains(`POISSON PAS NET (CFR112)`).should('be.visible') - - // Message Header - cy.contains(`Préavis (notification de retour au port) – navire sans JPE`).should('be.visible') - - // Message Body - cy.contains(`Filets soulevés portatifs (LNP)`).should('be.visible') - }) - - it('Should display a successfully acknowledged message as expected', () => { - openSideWindowPriorNotification(`BARS`) - - // Title - cy.contains(`Préavis navire ≥ 12 M`).should('be.visible') - cy.contains(`DES BARS (CFR104)`).should('be.visible') - - // Message Header - cy.contains(`PNO`).should('be.visible') - cy.contains(`Préavis (notification de retour au port)`).should('be.visible') - - // Message Body - cy.getDataCy('LogbookMessage-successful-acknowledgement-icon').should('be.visible') - cy.contains(`Saint-Malo (FRSML)`).should('be.visible') - cy.contains(`Débarquement (LAN)`).should('be.visible') - cy.contains(`MORUE COMMUNE (CABILLAUD) (COD)`).should('be.visible') - cy.contains(`25 kg`).should('be.visible') - }) - - it('Should refresh the list when the opened prior notification data differs from its entry in the current list', () => { - const url = '/bff/v1/prior_notifications/FAKE_OPERATION_109_COR?isManuallyCreated=false&operationDate=*' - - cy.intercept({ - method: 'GET', - times: 1, - url - }).as('getOriginalPriorNotification') - - openSideWindowPriorNotification(`L'ANCRE`) - - cy.wait('@getOriginalPriorNotification').then(interception => { - const originalPriorNotificationDetail: PriorNotification.Detail = interception.response!.body - const updatedPriorNotificationDetailStub: PriorNotification.Detail = { - ...originalPriorNotificationDetail, - fingerprint: '109.1109.2109' - } - - openSideWindowPriorNotificationList() - cy.fill('Rechercher un navire', `L'ANCRE`) - - cy.intercept('GET', url, { body: updatedPriorNotificationDetailStub }).as('getUpdatedPriorNotification') - cy.intercept('GET', '/bff/v1/prior_notifications?*').as('getPriorNotifications') - - cy.clickButton('Éditer le préavis') - - cy.wait('@getUpdatedPriorNotification') - cy.wait('@getPriorNotifications') - - cy.contains(`L'ANCRE SÈCHE (CFR106)`).should('be.visible') - }) - }) - - it('Should display a warning banner and refresh the list when the opened prior notification has been deleted', () => { - const url = '/bff/v1/prior_notifications/FAKE_OPERATION_109_COR?isManuallyCreated=false&operationDate=*' - - cy.intercept({ - method: 'GET', - times: 1, - url - }).as('getOriginalPriorNotification') - - openSideWindowPriorNotification(`L'ANCRE`) - - cy.wait('@getOriginalPriorNotification').then(interception => { - const originalPriorNotificationDetail: PriorNotification.Detail = interception.response!.body - const deletedPriorNotificationDetailStub: PriorNotification.Detail = { - ...originalPriorNotificationDetail, - fingerprint: '109.1109.2109', - logbookMessage: { - ...originalPriorNotificationDetail.logbookMessage, - isDeleted: true - } - } - - openSideWindowPriorNotificationList() - cy.fill('Rechercher un navire', `L'ANCRE`) - - cy.intercept('GET', url, { body: deletedPriorNotificationDetailStub }).as('getDeletedPriorNotification') - cy.intercept('GET', '/bff/v1/prior_notifications?*').as('getPriorNotifications') - - cy.clickButton('Éditer le préavis') - - cy.wait('@getDeletedPriorNotification') - cy.wait('@getPriorNotifications') - - // The warning banner should be displayed - cy.contains(`Ce préavis a été supprimé (entre temps).`).should('be.visible') - // The card should be closed - cy.contains(`L'ANCRE SÈCHE (CFR106)`).should('not.exist') - }) - }) - - it('Should update a logbook prior notification', () => { - // Reset - const operationDate = dayjs().subtract(6, 'hours').toISOString() - cy.request('PUT', `/bff/v1/prior_notifications/logbook/FAKE_OPERATION_114?operationDate=${operationDate}`, { - body: { - authorTrigram: null, - note: null - } - }) - - // Given - openSideWindowPriorNotification(`MER À BOIRE`) - - cy.intercept('PUT', `/bff/v1/prior_notifications/logbook/FAKE_OPERATION_114?operationDate=*`).as( - 'updateLogbookPriorNotification' - ) - - cy.get('[name="note"]').should('have.value', '') - cy.get('[name="authorTrigram"]').should('have.value', '') - - // When - cy.fill("Points d'attention identifiés par le CNSP", "Un point d'attention.") - cy.fill('Par', 'ABC') - - cy.wait('@updateLogbookPriorNotification') - - // Then, the PDF is deleted - cy.get('.Element-Button').contains('Télécharger').parent().should('be.disabled') - - // The note is saved - openSideWindowPriorNotification(`MER À BOIRE`) - - cy.get('[name="note"]').should('have.value', "Un point d'attention.") - cy.get('[name="authorTrigram"]').should('have.value', 'ABC') - - // Reset - cy.request('PUT', `/bff/v1/prior_notifications/logbook/FAKE_OPERATION_114?operationDate=${operationDate}`, { - body: { - authorTrigram: null, - note: null - } - }) - }) - - it('Should verify and send a logbook prior notification', () => { - openSideWindowPriorNotification(`LE POISSON AMBULANT`) - - cy.intercept( - 'POST', - `/bff/v1/prior_notifications/FAKE_OPERATION_111_COR_ORPHAN/verify_and_send?isManuallyCreated=false&operationDate=*` - ).as('verifyAndSendPriorNotification') - - cy.clickButton('Diffuser') - - cy.wait('@verifyAndSendPriorNotification').then(verifyAndSendInterception => { - if (!verifyAndSendInterception.response) { - assert.fail('`verifyAndSendInterception.response` is undefined.') - } - - const updatedPriorNotification = verifyAndSendInterception.response.body - - assert.deepInclude(updatedPriorNotification, { - state: PriorNotification.State.PENDING_SEND - }) - - cy.contains('Diffusion en cours') - - // ----------------------------------------------------------------------- - // List - - cy.clickButton('Fermer') - cy.fill('Rechercher un navire', 'LE POISSON AMBULANT') - - cy.getTableRowById('FAKE_OPERATION_111_COR_ORPHAN' as unknown as number) - .find('span[title="Diffusion en cours"]') - .should('be.visible') - }) - }) - - it('Should download a logbook prior notification as a PDF document', () => { - // Given - openSideWindowPriorNotification(`COURANT MAIN PROFESSEUR`) - - // Spy on the window.open method - cy.window().then(win => { - cy.stub(win, 'open').as('windowOpen') - }) - - // When - cy.clickButton('Télécharger') - - // Verify that window.open was called with the correct URL - cy.get('@windowOpen').should('be.calledWith', '/api/v1/prior_notifications/pdf/FAKE_OPERATION_102', '_blank') - }) - - it('Should invalidate a logbook prior notification', () => { - // Given - openSideWindowPriorNotificationList() - cy.get('[data-cy="side-window-sub-menu-ALL"]').click() - cy.fill('Rechercher un navire', 'ANCRE') - - cy.getTableRowById('FAKE_OPERATION_109_COR' as any) - .find('[title="Préavis invalidé"]') - .should('not.exist') - - cy.getTableRowById('FAKE_OPERATION_109_COR' as any).clickButton('Éditer le préavis') - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } - - // When - cy.clickButton('Invalider le préavis') - cy.clickButton('Confirmer l’invalidation') - - // Then - cy.get('.Wrapper').contains('Invalidé') - cy.get('[title="Invalider le préavis"]').should('not.exist') - - cy.clickButton('Fermer') - - cy.getTableRowById('FAKE_OPERATION_109_COR' as any) - .find('[title="Préavis invalidé"]') - .should('exist') - }) -}) diff --git a/frontend/cypress/e2e/side_window/prior_notification_card/utils.ts b/frontend/cypress/e2e/side_window/prior_notification_card/utils.ts deleted file mode 100644 index 88f329e486..0000000000 --- a/frontend/cypress/e2e/side_window/prior_notification_card/utils.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { SideWindowMenuLabel } from 'domain/entities/sideWindow/constants' - -export const openSideWindowPriorNotification = (vesselName: string, isSuperUser: boolean = true) => { - cy.viewport(1920, 1080) - cy.visit('/side_window') - cy.wait(500) - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } - - if (isSuperUser) { - cy.clickButton(SideWindowMenuLabel.PRIOR_NOTIFICATION_LIST) - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } - } - cy.get('.Table-SimpleTable tr').should('have.length.to.be.greaterThan', 0) - - cy.get('[data-cy="side-window-sub-menu-ALL"]').click() - cy.fill('Rechercher un navire', vesselName) - - if (isSuperUser) { - cy.clickButton('Éditer le préavis') - } else { - cy.clickButton('Consulter le préavis') - } - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } -} diff --git a/frontend/cypress/e2e/side_window/prior_notification_list/error_handling.spec.ts b/frontend/cypress/e2e/side_window/prior_notification_list/error_handling.spec.ts index ea09b8127d..b94100864f 100644 --- a/frontend/cypress/e2e/side_window/prior_notification_list/error_handling.spec.ts +++ b/frontend/cypress/e2e/side_window/prior_notification_list/error_handling.spec.ts @@ -1,6 +1,6 @@ import { RTK_MAX_RETRIES } from '@api/constants' -import { openSideWindowPriorNotificationList } from './utils' +import { openSideWindowPriorNotificationListAsSuperUser } from './utils' context('Side Window > Prior Notification List > Error Handling', () => { const failedQueryCount = RTK_MAX_RETRIES + 1 @@ -18,7 +18,7 @@ context('Side Window > Prior Notification List > Error Handling', () => { } ).as('getPriorNotificationsWithError') - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() for (let i = 1; i <= failedQueryCount; i += 1) { cy.wait('@getPriorNotificationsWithError') diff --git a/frontend/cypress/e2e/side_window/prior_notification_list/filter_bar.spec.ts b/frontend/cypress/e2e/side_window/prior_notification_list/filter_bar.spec.ts index 955f1e79ee..39c2a73886 100644 --- a/frontend/cypress/e2e/side_window/prior_notification_list/filter_bar.spec.ts +++ b/frontend/cypress/e2e/side_window/prior_notification_list/filter_bar.spec.ts @@ -1,7 +1,7 @@ import { assertNotNullish } from '@utils/assertNotNullish' import { SideWindowMenuLabel } from 'domain/entities/sideWindow/constants' -import { openSideWindowPriorNotificationList } from './utils' +import { openSideWindowPriorNotificationListAsSuperUser } from './utils' import { assertAll } from '../../utils/assertAll' import { customDayjs } from '../../utils/customDayjs' import { getUtcDateInMultipleFormats } from '../../utils/getUtcDateInMultipleFormats' @@ -12,7 +12,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { const apiPathBase = '/bff/v1/prior_notifications?' it('Should filter prior notifications by seafront group', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*seafrontGroup=MEMN*`).as('getPriorNotificationsForMEMN') @@ -32,7 +32,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by vessel name (search input)', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*searchQuery=pheno*`).as('getPriorNotifications') @@ -44,7 +44,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by countries', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*flagStates=ESP,FRA*`).as('getPriorNotifications') @@ -56,7 +56,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by fleet segments', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*tripSegmentCodes=NWW03,SWW06*`).as('getPriorNotifications') @@ -68,7 +68,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by species', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*specyCodes=FRF,HKE*`).as('getPriorNotifications') @@ -80,7 +80,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by gears', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*tripGearCodes=OTT,TBS*`).as('getPriorNotifications') @@ -92,7 +92,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by last control date', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() const expectedPartialBeforeDate = customDayjs.utc().subtract(3, 'months').toISOString().substring(0, 10) cy.intercept('GET', `${apiPathBase}*lastControlledBefore=${expectedPartialBeforeDate}*`).as('getPriorNotifications') @@ -114,7 +114,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications with or without reportings', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*hasOneOrMoreReportings=true*`).as('getPriorNotificationsWithReportings') @@ -164,7 +164,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by arrival date', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*`).as('getPriorNotifications') @@ -189,7 +189,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by arrival date (custom)', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*`).as('getPriorNotifications') @@ -220,7 +220,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by ports', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*&portsFRSM,FRVN*`).as('getPriorNotifications') @@ -230,7 +230,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications by type', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*priorNotificationTypes=Préavis type A,Préavis type C*`).as( 'getPriorNotifications' @@ -242,7 +242,7 @@ context('Side Window > Prior Notification List > Filter Bar', () => { }) it('Should filter prior notifications for vessels with length < or >= 12 meters', () => { - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.intercept('GET', `${apiPathBase}*isLessThanTwelveMetersVessel=true*`).as( 'getPriorNotificationsForVesselsWithLengthLessThanTwelveMeters' diff --git a/frontend/cypress/e2e/side_window/prior_notification_list/pagination.spec.ts b/frontend/cypress/e2e/side_window/prior_notification_list/pagination.spec.ts index de2d128acf..8447b856ee 100644 --- a/frontend/cypress/e2e/side_window/prior_notification_list/pagination.spec.ts +++ b/frontend/cypress/e2e/side_window/prior_notification_list/pagination.spec.ts @@ -1,6 +1,6 @@ import { getPseudoRandomString } from '@mtes-mct/monitor-ui' -import { openSideWindowPriorNotificationList } from './utils' +import { openSideWindowPriorNotificationListAsSuperUser } from './utils' import type { BackendApi } from '@api/BackendApi.types' import type { LogbookMessage } from '@features/Logbook/LogbookMessage.types' @@ -12,7 +12,7 @@ context('Side Window > Prior Notification List > Pagination', () => { it('Should filter prior notifications by seafront group', () => { cy.intercept('GET', `${apiPathBase}*`).as('getPriorNotifications') - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.wait('@getPriorNotifications').then(interception => { const responseBody: BackendApi.ResponseBodyPaginatedList< @@ -46,7 +46,7 @@ context('Side Window > Prior Notification List > Pagination', () => { } }).as('getPriorNotificationsSecondPage') - openSideWindowPriorNotificationList() + openSideWindowPriorNotificationListAsSuperUser() cy.wait('@getPriorNotificationsFirstPage') diff --git a/frontend/cypress/e2e/side_window/prior_notification_list/side_menu.spec.ts b/frontend/cypress/e2e/side_window/prior_notification_list/side_menu.spec.ts index 3c413604c1..da5dfdd71b 100644 --- a/frontend/cypress/e2e/side_window/prior_notification_list/side_menu.spec.ts +++ b/frontend/cypress/e2e/side_window/prior_notification_list/side_menu.spec.ts @@ -23,7 +23,7 @@ context('Side Window > Prior Notification List > Side Menu', () => { cy.get('[data-cy="side-window-sub-menu-ALL-number"] > div').contains('2') cy.fill('Rechercher un navire', 'FILET DOUX') - cy.getTableRowById('00000000-0000-4000-0000-000000000007' as any).clickButton('Éditer le préavis') + cy.getTableRowById('00000000-0000-4000-0000-000000000007').clickButton('Éditer le préavis') if (document.querySelector('[data-cy="first-loader"]')) { cy.getDataCy('first-loader').should('not.be.visible') } diff --git a/frontend/cypress/e2e/side_window/prior_notification_list/utils.ts b/frontend/cypress/e2e/side_window/prior_notification_list/utils.ts index a0b8b6bf0a..f912e1c80c 100644 --- a/frontend/cypress/e2e/side_window/prior_notification_list/utils.ts +++ b/frontend/cypress/e2e/side_window/prior_notification_list/utils.ts @@ -1,16 +1,15 @@ import { SideWindowMenuLabel } from '../../../../src/domain/entities/sideWindow/constants' +import { openSideWindowAsSuperUser, openSideWindowAsUser } from '../utils' -export const openSideWindowPriorNotificationList = () => { - cy.viewport(1920, 1080) - cy.visit('/side_window') - cy.wait(500) - if (document.querySelector('[data-cy="first-loader"]')) { - cy.getDataCy('first-loader').should('not.be.visible') - } +export const openSideWindowPriorNotificationListAsUser = openSideWindowAsUser + +export const openSideWindowPriorNotificationListAsSuperUser = () => { + openSideWindowAsSuperUser() cy.clickButton(SideWindowMenuLabel.PRIOR_NOTIFICATION_LIST) if (document.querySelector('[data-cy="first-loader"]')) { cy.getDataCy('first-loader').should('not.be.visible') } + cy.wait(1000) } diff --git a/frontend/cypress/e2e/side_window/utils.ts b/frontend/cypress/e2e/side_window/utils.ts new file mode 100644 index 0000000000..a36cd48636 --- /dev/null +++ b/frontend/cypress/e2e/side_window/utils.ts @@ -0,0 +1,19 @@ +export const openSideWindowAsUser = () => { + cy.intercept('/bff/v1/authorization/current', { statusCode: 401 }).as('getIsSuperUser') + + cy.viewport(1920, 1080) + cy.visit('/side_window') + cy.wait(500) + if (document.querySelector('[data-cy="first-loader"]')) { + cy.getDataCy('first-loader').should('not.be.visible') + } +} + +export const openSideWindowAsSuperUser = () => { + cy.viewport(1920, 1080) + cy.visit('/side_window') + cy.wait(500) + if (document.querySelector('[data-cy="first-loader"]')) { + cy.getDataCy('first-loader').should('not.be.visible') + } +} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index a4c18a9593..0cf4d616cf 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": "21.0.0", + "@mtes-mct/monitor-ui": "21.0.1", "@reduxjs/toolkit": "2.2.7", "@sentry/react": "7.117.0", "@tanstack/react-table": "8.19.3", @@ -2448,9 +2448,9 @@ "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==" }, "node_modules/@mtes-mct/monitor-ui": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-21.0.0.tgz", - "integrity": "sha512-2tKEwb3WUlQTyay93cwgoExEjfnInxoPH5OhfLEU2lklLvKGEVBeJikT4UcA138/KGGMb+9tRqHNAupduWXZnA==", + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-21.0.1.tgz", + "integrity": "sha512-blcqeHq2Hi1Zv1NfWkODtk0kAOm36NME49NGH5kfXkbpZlp+P2QWiEmXz4F+vP6lJlU/peRvRQF/aPUFR9tfFA==", "license": "AGPL-3.0", "dependencies": { "@babel/runtime": "7.25.0", diff --git a/frontend/package.json b/frontend/package.json index 82928d88d2..dc43e9307a 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": "21.0.0", + "@mtes-mct/monitor-ui": "21.0.1", "@reduxjs/toolkit": "2.2.7", "@sentry/react": "7.117.0", "@tanstack/react-table": "8.19.3", diff --git a/frontend/src/auth/hooks/useCustomAuth.tsx b/frontend/src/auth/hooks/useCustomAuth.tsx index 1c44b7e41a..fb546a3a76 100644 --- a/frontend/src/auth/hooks/useCustomAuth.tsx +++ b/frontend/src/auth/hooks/useCustomAuth.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useState } from 'react' -import { hasAuthParams, useAuth } from 'react-oidc-context' +import { hasAuthParams, useAuth, type AuthContextProps } from 'react-oidc-context' import { getCurrentUserAuthorization } from '../../domain/use_cases/authorization/getCurrentUserAuthorization' @@ -11,7 +11,9 @@ export function useCustomAuth(): { isLoading: boolean userAccount: UserAccountContextType | undefined } { - const auth = useAuth() + // `| undefined` because it's undefined if the OICD is disabled which is the case for Cypress tests + const auth = useAuth() as AuthContextProps | undefined + const [userAuthorization, setUserAuthorization] = useState(undefined) useEffect(() => { @@ -23,11 +25,15 @@ export function useCustomAuth(): { }, []) const logout = useCallback(() => { - const idTokenHint = auth?.user?.id_token + if (!auth) { + return + } + + const idTokenHint = auth.user?.id_token - auth?.removeUser() - auth?.removeUser() - auth?.signoutRedirect({ id_token_hint: idTokenHint ?? '' }) + auth.removeUser() + auth.removeUser() + auth.signoutRedirect({ id_token_hint: idTokenHint ?? '' }) }, [auth]) const userAccount = useMemo( @@ -45,15 +51,15 @@ export function useCustomAuth(): { } // automatically sign-in - if (!hasAuthParams() && !auth?.isAuthenticated && !auth?.activeNavigator && !auth?.isLoading) { + if (!hasAuthParams() && !auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading) { // eslint-disable-next-line no-console console.log('Redirect after Cerbère sign-in.') - auth?.signinRedirect() + auth.signinRedirect() return } - if (!auth.isLoading && auth?.isAuthenticated && userAuthorization?.mustReload) { + if (!auth.isLoading && auth.isAuthenticated && userAuthorization?.mustReload) { // eslint-disable-next-line no-console console.log('Re-trying to login with the latest token...') diff --git a/frontend/src/components/SideWindowCard.tsx b/frontend/src/components/SideWindowCard.tsx index b053053fa5..c5725d8bb4 100644 --- a/frontend/src/components/SideWindowCard.tsx +++ b/frontend/src/components/SideWindowCard.tsx @@ -10,7 +10,7 @@ export function SideWindowCard({ children, onBackgroundClick, ...nativeProps }: return ( // eslint-disable-next-line react/jsx-props-no-spreading - + {children} diff --git a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/Form.tsx b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/Form.tsx index 3c84448127..43325988aa 100644 --- a/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/Form.tsx +++ b/frontend/src/features/PriorNotification/components/LogbookPriorNotificationForm/Form.tsx @@ -29,7 +29,8 @@ export function Form({ detail, initialFormValues }: FormProps) { const priorNotificationIdentifier = useMemo(() => getPriorNotificationIdentifier(detail), [detail]) assertNotNullish(priorNotificationIdentifier) - const { isInvalidated } = detail.logbookMessage.message + const { isBeingSent, isInvalidated } = detail.logbookMessage.message + const isReadOnly = !isSuperUser || !!isBeingSent || isInvalidated const invalidate = () => { dispatch(invalidatePriorNotification(priorNotificationIdentifier, false)) @@ -55,23 +56,20 @@ export function Form({ detail, initialFormValues }: FormProps) { <> <> - + {!isReadOnly && } - + - {isSuperUser && } + {isSuperUser && } {isSuperUser && !isInvalidated && ( setIsInvalidatingPriorNotificationDialog(true)} title="Invalider le préavis" diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx index 86163db7de..ff56a763ba 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx @@ -54,6 +54,7 @@ export function Content({ detail, isValidatingOnChange, onClose, onSubmit, onVer !!detail?.state && [PriorNotification.State.PENDING_AUTO_SEND, PriorNotification.State.PENDING_SEND].includes(detail?.state) const isPendingVerification = detail?.state === PriorNotification.State.PENDING_VERIFICATION + const isReadOnly = isPendingSend || isInvalidated const isVerifiedAndSent = detail?.state === PriorNotification.State.VERIFIED_AND_SENT const hasDesignatedPorts = editedPriorNotificationComputedValues?.types?.find(type => type.hasDesignatedPorts) const priorNotificationIdentifier = getPriorNotificationIdentifier(detail) @@ -171,9 +172,9 @@ export function Content({ detail, isValidatingOnChange, onClose, onSubmit, onVer
-
+ - {!!detail && !isInvalidated && ( + {!!detail && !isInvalidated && !isPendingSend && ( -export function Form({ isInvalidated }: FormProps) { +export function Form({ isReadOnly }: FormProps) { const { values } = useFormikContext() const dispatch = useMainAppDispatch() @@ -58,21 +58,21 @@ export function Form({ isInvalidated }: FormProps) { return ( <> - + @@ -80,7 +80,7 @@ export function Form({ isInvalidated }: FormProps) { isStringDate label="Date et heure estimées d'arrivée au port (UTC)" name="expectedArrivalDate" - readOnly={isInvalidated} + readOnly={isReadOnly} withTime /> @@ -90,13 +90,13 @@ export function Form({ isInvalidated }: FormProps) { isStringDate label="Date et heure prévues de débarque (UTC)" name="expectedLandingDate" - readOnly={isInvalidated} + readOnly={isReadOnly} withTime /> @@ -105,19 +105,19 @@ export function Form({ isInvalidated }: FormProps) { label="Port d'arrivée" name="portLocode" options={portsAsOptions ?? []} - readOnly={isInvalidated} + readOnly={isReadOnly} searchable virtualized /> - + @@ -127,7 +127,7 @@ export function Form({ isInvalidated }: FormProps) { label="Zone de pêche" name="faoArea" options={faoAreasAsOptions ?? []} - readOnly={isInvalidated} + readOnly={isReadOnly} searchable virtualized /> @@ -141,28 +141,28 @@ export function Form({ isInvalidated }: FormProps) { label="Autorisation d'entrée au port" name="hasPortEntranceAuthorization" options={BOOLEAN_AS_OPTIONS} - readOnly={isInvalidated} + readOnly={isReadOnly} /> )} - + - + ) }