Skip to content

Commit

Permalink
Préavis – Prévenir le risque de race condition entre la sauvegarde et…
Browse files Browse the repository at this point in the history
… la diffusion par la pipeline pendant l'envoi (#3544)

## Linked issues

- Resolve #3538
- Resolve #3419

----

- [x] Tests E2E (Cypress)
  • Loading branch information
ivangabriele committed Aug 20, 2024
2 parents 9deba56 + 22b92fc commit c363ce1
Show file tree
Hide file tree
Showing 28 changed files with 524 additions and 432 deletions.
Original file line number Diff line number Diff line change
@@ -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')
})
})
Original file line number Diff line number Diff line change
@@ -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')
})
})
})
Original file line number Diff line number Diff line change
@@ -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(
{
Expand All @@ -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')
Expand Down
Original file line number Diff line number Diff line change
@@ -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')
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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')
Expand All @@ -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')
})
})
Original file line number Diff line number Diff line change
@@ -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')
}
}
Original file line number Diff line number Diff line change
@@ -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')
})
})
})
Loading

0 comments on commit c363ce1

Please sign in to comment.