feat(assignments): partial return action and ReturnButton modal
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest"
|
||||
|
||||
import { en } from "@/i18n/dictionaries/en"
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
revalidatePath: vi.fn(),
|
||||
getI18n: vi.fn(),
|
||||
getAuthenticatedUserId: vi.fn(),
|
||||
returnAssignmentUseCase: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock("next/cache", () => ({
|
||||
revalidatePath: mocks.revalidatePath,
|
||||
}))
|
||||
|
||||
vi.mock("@/i18n/server", () => ({
|
||||
getI18n: mocks.getI18n,
|
||||
}))
|
||||
|
||||
vi.mock("@/services/auth.service", () => ({
|
||||
getAuthenticatedUserId: mocks.getAuthenticatedUserId,
|
||||
}))
|
||||
|
||||
vi.mock("@/use-cases/assignment.use-cases", () => ({
|
||||
returnAssignmentUseCase: mocks.returnAssignmentUseCase,
|
||||
}))
|
||||
|
||||
import { returnAssignment } from "@/actions/assignment.actions"
|
||||
|
||||
describe("returnAssignment action", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mocks.getI18n.mockResolvedValue({ dictionary: en, locale: "en" })
|
||||
mocks.getAuthenticatedUserId.mockResolvedValue("user-1")
|
||||
})
|
||||
|
||||
it("returns validation errors for a missing assignment id", async () => {
|
||||
const result = await returnAssignment({ id: "" })
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
errors: {
|
||||
id: [en.inventory.assignments.schema.idRequired],
|
||||
},
|
||||
})
|
||||
expect(mocks.returnAssignmentUseCase).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("forwards returns to the use case and revalidates on success", async () => {
|
||||
mocks.returnAssignmentUseCase.mockResolvedValue({ success: true })
|
||||
|
||||
const result = await returnAssignment({
|
||||
id: "assignment-1",
|
||||
returns: [
|
||||
{ assignmentLineId: "line-1", quantity: 2, notes: "Slightly damaged" },
|
||||
],
|
||||
})
|
||||
|
||||
expect(result).toEqual({
|
||||
success: true as const,
|
||||
message: en.inventory.assignments.actions.returnSuccess,
|
||||
})
|
||||
expect(mocks.returnAssignmentUseCase).toHaveBeenCalledWith({
|
||||
id: "assignment-1",
|
||||
actorId: "user-1",
|
||||
returns: [
|
||||
{ assignmentLineId: "line-1", quantity: 2, notes: "Slightly damaged" },
|
||||
],
|
||||
})
|
||||
expect(mocks.revalidatePath).toHaveBeenCalledWith("/assignments")
|
||||
})
|
||||
|
||||
it("surfaces use-case errors and skips revalidation on failure", async () => {
|
||||
mocks.returnAssignmentUseCase.mockResolvedValue({
|
||||
success: false,
|
||||
errors: { error: ["errorConcurrent"] },
|
||||
})
|
||||
|
||||
const result = await returnAssignment({
|
||||
id: "assignment-1",
|
||||
returns: [{ assignmentLineId: "line-1", quantity: 2 }],
|
||||
})
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false as const,
|
||||
errors: { error: ["errorConcurrent"] },
|
||||
message: en.inventory.assignments.actions.returnFailure,
|
||||
})
|
||||
expect(mocks.revalidatePath).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("preserves the legacy full-return shortcut without returns", async () => {
|
||||
mocks.returnAssignmentUseCase.mockResolvedValue({ success: true })
|
||||
|
||||
const result = await returnAssignment({ id: "assignment-1" })
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
expect(mocks.returnAssignmentUseCase).toHaveBeenCalledWith({
|
||||
id: "assignment-1",
|
||||
actorId: "user-1",
|
||||
})
|
||||
expect(mocks.revalidatePath).toHaveBeenCalledWith("/assignments")
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user