Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Préavis – Prévenir le risque de race condition entre la sauvegarde et la diffusion par la pipeline pendant l'envoi #3544

Merged
merged 8 commits into from
Aug 20, 2024
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
Loading