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

[Mission] Correction de la duplication de missions #3052

Merged
merged 3 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 0 additions & 82 deletions frontend/cypress/e2e/side_window/mission_form/action_list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,88 +34,6 @@ context('Side Window > Mission Form > Action List', () => {
cy.get('*[data-cy="action-list-item"]').eq(0).should('contain', 'Une observation.')
})

it('Should send the expected data to the API when duplicating a mission action', () => {
editSideWindowMissionListMissionWithId(4, SeaFrontGroup.MEMN)

cy.intercept('POST', '/api/v1/missions/4', {
body: {
id: 1
},
statusCode: 201
}).as('updateMission4')
cy.intercept('POST', '/bff/v1/mission_actions').as('createMissionAction')
cy.get('*[data-cy="action-list-item"]').click()

cy.wait(250)

cy.clickButton('Dupliquer l’action')

cy.wait(250)

cy.waitForLastRequest(
'@createMissionAction',
{
body: {
actionType: 'SEA_CONTROL',
closedBy: null,
controlQualityComments: null,
controlUnits: [],
emitsAis: null,
emitsVms: 'NOT_APPLICABLE',
externalReferenceNumber: null,
facade: 'MEMN',
faoAreas: ['27.8.a'],
feedbackSheetRequired: false,
flagState: 'FR',
flightGoals: [],
gearInfractions: [],
gearOnboard: [],
hasSomeGearsSeized: false,
hasSomeSpeciesSeized: false,
id: null,
internalReferenceNumber: 'U_W0NTFINDME',
ircs: null,
latitude: 53.35,
licencesAndLogbookObservations: null,
licencesMatchActivity: 'NOT_APPLICABLE',
logbookInfractions: [],
logbookMatchesActivity: 'NOT_APPLICABLE',
longitude: -10.85,
missionId: 4,
numberOfVesselsFlownOver: null,
otherComments: 'Commentaires post contrôle',
otherInfractions: [],
portLocode: null,
segments: [],
seizureAndDiversion: false,
seizureAndDiversionComments: null,
separateStowageOfPreservedSpecies: 'NO',
speciesInfractions: [],
speciesObservations: null,
speciesOnboard: [],
speciesSizeControlled: null,
speciesWeightControlled: null,
unitWithoutOmegaGauge: false,
userTrigram: 'JKL',
vesselId: 2,
vesselName: 'MALOTRU',
vesselTargeted: 'YES'
}
},
5
)
.its('response.statusCode')
.should('eq', 201)

// And we delete this action

editSideWindowMissionListMissionWithId(4, SeaFrontGroup.MEMN)

cy.clickButton('Supprimer l’action', { index: 1 })

cy.wait(250)
})

it('Should send the expected data to the API when deleting a mission action', () => {
editSideWindowMissionListMissionWithId(34, SeaFrontGroup.MEMN)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,82 @@ context('Side Window > Mission Form > Sea Control Edition', () => {
}
)

/**
* Non-regression test to prevent mission actions IDs to be modified instead of update the right ID.
*
* Bug case:
* 1. The first control in this test has the id `4`
* 2. A new control is added
* 3. We save the form
* 3. The bug was sending :
* - 1 POST request with the data of the first control (instead of an update of the id `4`)
* - 1 PUT request with the date of the new control (instead of a creation with a POST request)
*/
it(
'Should update actions and keep existing actions ids',
{
env: {
FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED: false
}
},
() => {
cy.intercept('PUT', '/bff/v1/mission_actions/4', {
body: {
id: 4
},
statusCode: 201
}).as('updateMissionAction')
cy.intercept('POST', '/bff/v1/mission_actions', {
body: {
id: 5
},
statusCode: 201
}).as('createMissionAction')

// -------------------------------------------------------------------------
// Form
const endDate = getUtcDateInMultipleFormats(customDayjs().utc().add(7, 'day').toISOString())
cy.fill('Fin de mission', endDate.utcDateTupleWithTime)

// Add another control
cy.clickButton('Ajouter')
cy.clickButton('Ajouter un contrôle en mer')

// Navire
// TODO Handle Automplete in custom `cy.fill()` command once it's used via monitor-ui.
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
cy.get('input[placeholder="Rechercher un navire..."]').type('FR263418260').wait(250)
cy.contains('mark', 'FR263418260').click()

// Date et heure du contrôle
cy.fill('Date et heure du contrôle', endDate.utcDateTupleWithTime)

// Saisi par
cy.fill('Saisi par', 'Marlin')

// We need to wait for some time because there is a throttle on the form
cy.wait(500)
cy.clickButton('Enregistrer')

// -------------------------------------------------------------------------
// Request

cy.waitForLastRequest(
'@updateMissionAction',
{
body: {
internalReferenceNumber: 'U_W0NTFINDME',
vesselName: 'MALOTRU'
}
},
5
)
.its('response.statusCode')
.should('eq', 201)
cy.wait('@createMissionAction')
}
)

it('Should not update the mission zone When a CACEM control is newer', () => {
editSideWindowMissionListMissionWithId(34, SeaFrontGroup.MEMN)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import type { Promisable } from 'type-fest'

type FishActionCardProps = Readonly<{
missionAction: MissionActionFormValues
onDuplicate: () => Promisable<void>
onRemove: () => Promisable<void>
}>
export function FishActionCard({ missionAction, onDuplicate, onRemove }: FishActionCardProps) {
export function FishActionCard({ missionAction, onRemove }: FishActionCardProps) {
const natinfsAsOptions = useGetNatinfsAsOptions()

const isControlAction =
Expand Down Expand Up @@ -119,15 +118,6 @@ export function FishActionCard({ missionAction, onDuplicate, onRemove }: FishAct
<p>{actionLabel}</p>
</ActionLabel>

<RightAlignedIconButton
accent={Accent.TERTIARY}
color={THEME.color.slateGray}
Icon={Icon.Duplicate}
iconSize={20}
onClick={onDuplicate}
title="Dupliquer l’action"
withUnpropagatedClick
/>
<RightAlignedIconButton
accent={Accent.TERTIARY}
color={THEME.color.maximumRed}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ type ActionListProps = Readonly<{
missionId: number | undefined
missionTypes: Mission.MissionType[] | undefined
onAdd: (actionType: MissionAction.MissionActionType) => Promisable<void>
onDuplicate: (actionIndex: number) => Promisable<void>
onRemove: (actionIndex: number) => Promisable<void>
onSelect: (actionIndex: number) => Promisable<void>
}>
Expand All @@ -33,7 +32,6 @@ export function ActionList({
missionId,
missionTypes = [],
onAdd,
onDuplicate,
onRemove,
onSelect
}: ActionListProps) {
Expand Down Expand Up @@ -128,7 +126,6 @@ export function ActionList({
// eslint-disable-next-line react/no-array-index-key
key={index}
missionAction={action as MissionActionFormValues}
onDuplicate={() => onDuplicate(action.index!!)}
onRemove={() => onRemove(action.index!!)}
/>
</ActionCard>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { expect } from '@jest/globals'

import { MissionAction } from '../../../missionAction.types'
import { getMissionActionsDataFromMissionActionsFormValues } from '../utils'
import { getMissionActionsToCreateUpdateOrDelete } from '../utils'

import MissionActionType = MissionAction.MissionActionType

describe('features/Mission/components/MissionForm/utils.getMissionActionsDataFromMissionActionsFormValues()', () => {
it('Should add the id to an updated action', () => {
it('Should delete a previous action delete from the list and create a new action', () => {
// Given
const missionId = 123
const actionsFormValues = [
Expand Down Expand Up @@ -171,22 +171,104 @@ describe('features/Mission/components/MissionForm/utils.getMissionActionsDataFro
]

// When
const { deletedMissionActionIds, updatedMissionActionDatas } = getMissionActionsDataFromMissionActionsFormValues(
const { createdOrUpdatedMissionActions, deletedMissionActionIds } = getMissionActionsToCreateUpdateOrDelete(
missionId,
actionsFormValues,
originalMissionActions
)

// Then
expect(deletedMissionActionIds).toHaveLength(0)
expect(updatedMissionActionDatas).toHaveLength(1)
expect(updatedMissionActionDatas[0]?.id).toEqual(20)
expect(deletedMissionActionIds).toHaveLength(1)
expect(deletedMissionActionIds[0]).toEqual(20)
expect(createdOrUpdatedMissionActions).toHaveLength(1)
expect(createdOrUpdatedMissionActions[0]?.id).toEqual(undefined)
})

it('Should get deleted actions When the action is no more in the action form list', () => {
// Given
const missionId = 123
const actionsFormValues = []
const actionsFormValues = [
{
actionDatetimeUtc: '2023-12-08T08:27:00Z',
actionType: MissionActionType.SEA_CONTROL,
closedBy: undefined,
controlQualityComments: undefined,
controlUnits: [],
districtCode: 'AY',
emitsAis: undefined,
emitsVms: undefined,
externalReferenceNumber: 'DONTSINK',
facade: 'NAMO',
faoAreas: ['27.8.b', '27.8.c'],
feedbackSheetRequired: false,
flagState: 'FR',
flightGoals: [],
gearInfractions: [],
gearOnboard: [
{
comments: undefined,
controlledMesh: undefined,
declaredMesh: 70.0,
gearCode: 'OTB',
gearName: 'Chaluts de fond à panneaux',
gearWasControlled: undefined,
hasUncontrolledMesh: false
}
],
hasSomeGearsSeized: false,
hasSomeSpeciesSeized: false,
id: 20,
internalReferenceNumber: 'FAK000999999',
ircs: 'CALLME',
isAdministrativeControl: undefined,
isComplianceWithWaterRegulationsControl: undefined,
isFromPoseidon: false,
isSafetyEquipmentAndStandardsComplianceControl: undefined,
isSeafarersControl: undefined,
isValid: true,
latitude: 47.648401281163814,
licencesAndLogbookObservations: undefined,
licencesMatchActivity: undefined,
logbookInfractions: [],
logbookMatchesActivity: undefined,
longitude: -4.281934312813745,
missionId: 43,
numberOfVesselsFlownOver: undefined,
otherComments: undefined,
otherInfractions: [],
portLocode: undefined,
portName: undefined,
segments: [{ segment: 'SWW01/02/03', segmentName: 'Bottom trawls' }],
seizureAndDiversion: false,
seizureAndDiversionComments: undefined,
separateStowageOfPreservedSpecies: undefined,
speciesInfractions: [],
speciesObservations: undefined,
speciesOnboard: [
{
controlledWeight: undefined,
declaredWeight: 471.2,
nbFish: undefined,
speciesCode: 'HKE',
underSized: false
},
{
controlledWeight: undefined,
declaredWeight: 13.46,
nbFish: undefined,
speciesCode: 'BLI',
underSized: false
}
],
speciesSizeControlled: undefined,
speciesWeightControlled: undefined,
unitWithoutOmegaGauge: false,
userTrigram: 'LT',
vesselId: 1,
vesselName: 'PHENOMENE',
vesselTargeted: undefined
}
]
const originalMissionActions = [
{
actionDatetimeUtc: '2023-12-08T08:27:00Z',
Expand Down Expand Up @@ -270,15 +352,15 @@ describe('features/Mission/components/MissionForm/utils.getMissionActionsDataFro
]

// When
const { deletedMissionActionIds, updatedMissionActionDatas } = getMissionActionsDataFromMissionActionsFormValues(
const { createdOrUpdatedMissionActions, deletedMissionActionIds } = getMissionActionsToCreateUpdateOrDelete(
missionId,
actionsFormValues,
originalMissionActions
)

// Then
expect(deletedMissionActionIds).toHaveLength(1)
expect(deletedMissionActionIds).toEqual([20])
expect(updatedMissionActionDatas).toHaveLength(0)
expect(deletedMissionActionIds).toHaveLength(0)
expect(createdOrUpdatedMissionActions).toHaveLength(1)
expect(createdOrUpdatedMissionActions[0]?.id).toEqual(20)
})
})
Loading
Loading