|
|
@ -169,27 +169,23 @@ describe("QuestionPhoto Component", () => { |
|
|
|
|
|
|
|
|
// Error toast should appear
|
|
|
// Error toast should appear
|
|
|
await waitFor(() => { |
|
|
await waitFor(() => { |
|
|
|
|
|
// Toast message should appear
|
|
|
expect(screen.getByText("Photo upload failed. Please try again.")).toBeInTheDocument(); |
|
|
expect(screen.getByText("Photo upload failed. Please try again.")).toBeInTheDocument(); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Answer value is cleared
|
|
|
|
|
|
expect(mockSetAnswerValue).toHaveBeenCalledWith(mockPhotoQuestion, null); |
|
|
|
|
|
|
|
|
|
|
|
// Default avatar SVG placeholder is restored
|
|
|
|
|
|
expect(container.querySelector("img[src*='Frame 2095586679.svg']")).toBeInTheDocument(); |
|
|
|
|
|
|
|
|
|
|
|
// Camera badge is not visible
|
|
|
|
|
|
expect(container.querySelector(".bg-\\[\\#F0445B\\]")).toBeNull(); |
|
|
|
|
|
|
|
|
// Answer value is NOT cleared — matches yesterday's behavior
|
|
|
|
|
|
// (error just shows toast, does not wipe the form state)
|
|
|
|
|
|
expect(mockSetAnswerValue).not.toHaveBeenCalledWith(mockPhotoQuestion, null); |
|
|
|
|
|
|
|
|
// File input is reset allowing re-upload
|
|
|
|
|
|
expect(fileInput.value).toBe(""); |
|
|
|
|
|
|
|
|
// File input is reset allowing re-upload
|
|
|
|
|
|
expect(fileInput.value).toBe(""); |
|
|
|
|
|
}); |
|
|
} finally { |
|
|
} finally { |
|
|
URL.createObjectURL = originalCreateObjectURL; |
|
|
URL.createObjectURL = originalCreateObjectURL; |
|
|
URL.revokeObjectURL = originalRevokeObjectURL; |
|
|
URL.revokeObjectURL = originalRevokeObjectURL; |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
it("shows error toast and reverts to default avatar when rendered image fails to load", async () => { |
|
|
|
|
|
|
|
|
it("keeps stored answer when rendered image fails to load (preview-only failure)", async () => { |
|
|
answerMap[mockPhotoQuestion.id] = "https://example.com/broken-avatar.jpg"; |
|
|
answerMap[mockPhotoQuestion.id] = "https://example.com/broken-avatar.jpg"; |
|
|
const { container } = render(<QuestionPhoto question={mockPhotoQuestion} />); |
|
|
const { container } = render(<QuestionPhoto question={mockPhotoQuestion} />); |
|
|
|
|
|
|
|
|
@ -199,15 +195,12 @@ describe("QuestionPhoto Component", () => { |
|
|
// Trigger image error (e.g. 404 / ERR_CONNECTION_REFUSED)
|
|
|
// Trigger image error (e.g. 404 / ERR_CONNECTION_REFUSED)
|
|
|
fireEvent.error(img); |
|
|
fireEvent.error(img); |
|
|
|
|
|
|
|
|
await waitFor(() => { |
|
|
|
|
|
expect(screen.getByText("Failed to load image. Please try uploading again.")).toBeInTheDocument(); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Answer value cleared
|
|
|
|
|
|
expect(mockSetAnswerValue).toHaveBeenCalledWith(mockPhotoQuestion, null); |
|
|
|
|
|
|
|
|
// The stored answer should NOT be cleared — the file is already on the server.
|
|
|
|
|
|
// This matches yesterday's behavior where preview errors never wiped the answer.
|
|
|
|
|
|
expect(mockSetAnswerValue).not.toHaveBeenCalledWith(mockPhotoQuestion, null); |
|
|
|
|
|
|
|
|
// Default avatar placeholder rendered instead of broken image
|
|
|
|
|
|
expect(container.querySelector("img[src*='Frame 2095586679.svg']")).toBeInTheDocument(); |
|
|
|
|
|
expect(container.querySelector(".bg-\\[\\#F0445B\\]")).toBeNull(); |
|
|
|
|
|
|
|
|
// The component should remain in "answered" state via data-question-answered
|
|
|
|
|
|
// because storedValue still holds the uploaded path
|
|
|
|
|
|
expect(container.querySelector("[data-question-answered='true']")).toBeInTheDocument(); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
}); |