test(piece-edit,documents) : add productIds sync, error paths, and document CRUD tests
This commit is contained in:
@@ -466,4 +466,179 @@ describe('submitEdition — no data loss', () => {
|
||||
expect(formLinks[1].constructeurId).toBe(mockConstructeurFAG.id)
|
||||
expect(formLinks[2].constructeurId).toBe('cstr-new-003')
|
||||
})
|
||||
|
||||
it('sends both productId and productIds in payload', async () => {
|
||||
mockUpdatePiece.mockResolvedValue({ success: true, data: { id: PIECE_ID } })
|
||||
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
expect(mockUpdatePiece).toHaveBeenCalledTimes(1)
|
||||
const payload = mockUpdatePiece.mock.calls[0]![1]
|
||||
expect(payload.productId).toBe('prod-001')
|
||||
expect(payload.productIds).toEqual(['prod-001'])
|
||||
})
|
||||
|
||||
it('productId is the first product selection when multiple exist', async () => {
|
||||
// Override the piece type to have 2 product requirements
|
||||
const multiProductType = {
|
||||
...mockPieceType,
|
||||
structure: {
|
||||
...mockPieceType.structure,
|
||||
products: [
|
||||
{
|
||||
typeProductId: 'tprod-grease-001',
|
||||
typeProductLabel: 'Graisse SKF',
|
||||
familyCode: 'LUB',
|
||||
role: 'lubrification',
|
||||
},
|
||||
{
|
||||
typeProductId: 'tprod-oil-002',
|
||||
typeProductLabel: 'Huile',
|
||||
familyCode: 'LUB',
|
||||
role: 'lubrification secondaire',
|
||||
},
|
||||
],
|
||||
customFields: [],
|
||||
},
|
||||
}
|
||||
mockPieceTypes.value = [multiProductType]
|
||||
|
||||
mockUpdatePiece.mockResolvedValue({ success: true, data: { id: PIECE_ID } })
|
||||
|
||||
const composable = await createAndHydrate({
|
||||
productIds: ['prod-001', 'prod-002'],
|
||||
})
|
||||
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
composable.setProductSelection(1, 'prod-002')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
expect(mockUpdatePiece).toHaveBeenCalledTimes(1)
|
||||
const payload = mockUpdatePiece.mock.calls[0]![1]
|
||||
expect(payload.productId).toBe('prod-001')
|
||||
expect(payload.productIds).toEqual(['prod-001', 'prod-002'])
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// submitEdition — null field handling
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('submitEdition — null field handling', () => {
|
||||
it('empty prix sends null', async () => {
|
||||
mockUpdatePiece.mockResolvedValue({ success: true, data: { id: PIECE_ID } })
|
||||
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
composable.editionForm.prix = ''
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
const payload = mockUpdatePiece.mock.calls[0]![1]
|
||||
expect(payload.prix).toBeNull()
|
||||
})
|
||||
|
||||
it('whitespace-only prix sends null', async () => {
|
||||
mockUpdatePiece.mockResolvedValue({ success: true, data: { id: PIECE_ID } })
|
||||
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
composable.editionForm.prix = ' '
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
const payload = mockUpdatePiece.mock.calls[0]![1]
|
||||
expect(payload.prix).toBeNull()
|
||||
})
|
||||
|
||||
it('empty reference sends null', async () => {
|
||||
mockUpdatePiece.mockResolvedValue({ success: true, data: { id: PIECE_ID } })
|
||||
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
composable.editionForm.reference = ''
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
const payload = mockUpdatePiece.mock.calls[0]![1]
|
||||
expect(payload.reference).toBeNull()
|
||||
})
|
||||
|
||||
it('valid prix is sent as string number', async () => {
|
||||
mockUpdatePiece.mockResolvedValue({ success: true, data: { id: PIECE_ID } })
|
||||
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
composable.editionForm.prix = '99.50'
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
const payload = mockUpdatePiece.mock.calls[0]![1]
|
||||
expect(payload.prix).toBe('99.5')
|
||||
})
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// submitEdition — error paths
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('submitEdition — error paths', () => {
|
||||
it('does not save custom fields when updatePiece fails', async () => {
|
||||
mockUpdatePiece.mockResolvedValue({ success: false, error: 'Server error' })
|
||||
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
expect(mockUpdatePiece).toHaveBeenCalledTimes(1)
|
||||
expect(mockSaveAll).not.toHaveBeenCalled()
|
||||
expect(mockSyncLinks).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('does not save custom fields when updatePiece throws', async () => {
|
||||
mockUpdatePiece.mockRejectedValue(new Error('Network failure'))
|
||||
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
composable.setProductSelection(0, 'prod-001')
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
expect(mockUpdatePiece).toHaveBeenCalledTimes(1)
|
||||
expect(mockSaveAll).not.toHaveBeenCalled()
|
||||
expect(mockSyncLinks).not.toHaveBeenCalled()
|
||||
expect(mockShowError).toHaveBeenCalledWith('Network failure')
|
||||
})
|
||||
|
||||
it('shows error toast when product selection is not filled', async () => {
|
||||
const composable = await createAndHydrate()
|
||||
|
||||
// Clear product selection
|
||||
composable.setProductSelection(0, null)
|
||||
await tick()
|
||||
|
||||
await composable.submitEdition()
|
||||
|
||||
expect(mockUpdatePiece).not.toHaveBeenCalled()
|
||||
expect(mockShowError).toHaveBeenCalledWith('Sélectionnez un produit conforme au squelette.')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user