test: update coverage, add some tests
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
import ImageUpload from "$components/image/ImageUpload.svelte";
|
||||
import { fireEvent, render, screen, waitFor } from "@testing-library/svelte";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
// Mock the stores and services
|
||||
vi.mock("$stores/uiStore", () => ({
|
||||
uiStore: {
|
||||
subscribe: vi.fn((callback) => {
|
||||
callback({ error: null, loading: false });
|
||||
return () => {};
|
||||
}),
|
||||
},
|
||||
setCurrentStep: vi.fn(),
|
||||
setLoading: vi.fn(),
|
||||
clearError: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("$services/imageService", () => ({
|
||||
imageService: {
|
||||
validateAndProcessImage: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("$lib/utils/errorHandler", () => ({
|
||||
handleError: vi.fn((error) => `Error: ${error}`),
|
||||
}));
|
||||
|
||||
describe("ImageUpload", () => {
|
||||
let mockOnImageSelect: (image: string) => void;
|
||||
let mockImageService: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockOnImageSelect = vi.fn();
|
||||
vi.clearAllMocks();
|
||||
|
||||
// Setup mock image service
|
||||
mockImageService = {
|
||||
validateAndProcessImage: vi.fn().mockResolvedValue({
|
||||
success: true,
|
||||
imageUrl: "data:image/jpeg;base64,/9j/4AAQSkZJRg==",
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
it("should render upload component", () => {
|
||||
const { container } = render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
expect(container).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should handle file selection via input", async () => {
|
||||
const { container } = render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
// Create a mock file
|
||||
const mockFile = new File(["test image content"], "test.jpg", {
|
||||
type: "image/jpeg",
|
||||
});
|
||||
|
||||
// Find file input
|
||||
const fileInput = container.querySelector('input[type="file"]');
|
||||
expect(fileInput).toBeTruthy();
|
||||
|
||||
if (fileInput) {
|
||||
// Simulate file selection
|
||||
await fireEvent.change(fileInput, {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
// Should call image service
|
||||
await waitFor(() => {
|
||||
expect(mockImageService.validateAndProcessImage).toHaveBeenCalled();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("should handle drag and drop", async () => {
|
||||
const { container } = render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
// Create mock file
|
||||
const mockFile = new File(["test image content"], "test.jpg", {
|
||||
type: "image/jpeg",
|
||||
});
|
||||
|
||||
// Find drop zone
|
||||
const dropZone = container.querySelector("[data-testid='drop-zone'], .drop-zone, .upload-area");
|
||||
if (dropZone) {
|
||||
// Simulate drag over
|
||||
await fireEvent.dragOver(dropZone, {
|
||||
dataTransfer: { files: [mockFile] },
|
||||
});
|
||||
|
||||
// Simulate drop
|
||||
await fireEvent.drop(dropZone, {
|
||||
dataTransfer: { files: [mockFile] },
|
||||
});
|
||||
|
||||
// Should process the image
|
||||
await waitFor(() => {
|
||||
expect(mockImageService.validateAndProcessImage).toHaveBeenCalled();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("should handle URL input", async () => {
|
||||
const { container } = render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
// Find URL input and toggle button
|
||||
const urlInputs = container.querySelectorAll('input[type="url"], input[placeholder*="URL"]');
|
||||
const buttons = screen.getAllByRole("button");
|
||||
|
||||
// Toggle URL input if needed
|
||||
const toggleButton = buttons.find(
|
||||
(button) =>
|
||||
button.textContent?.includes("URL") ||
|
||||
button.textContent?.includes("Ссылка") ||
|
||||
button.textContent?.includes("By URL"),
|
||||
);
|
||||
|
||||
if (toggleButton) {
|
||||
await fireEvent.click(toggleButton);
|
||||
}
|
||||
|
||||
if (urlInputs.length > 0) {
|
||||
const testUrl = "https://example.com/image.jpg";
|
||||
await fireEvent.input(urlInputs[0], { target: { value: testUrl } });
|
||||
|
||||
// Submit URL form
|
||||
const submitButton = buttons.find((button) => {
|
||||
const isLoadButton = button.textContent?.includes("Load") || button.textContent?.includes("Загрузить");
|
||||
const buttonType = (button as HTMLButtonElement).type;
|
||||
return isLoadButton || buttonType === "submit";
|
||||
});
|
||||
|
||||
if (submitButton) {
|
||||
await fireEvent.click(submitButton);
|
||||
|
||||
// Should process the URL
|
||||
await waitFor(() => {
|
||||
expect(mockImageService.validateAndProcessImage).toHaveBeenCalled();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("should handle paste event", async () => {
|
||||
render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
// Create mock clipboard data
|
||||
const mockClipboardData = {
|
||||
items: [
|
||||
{
|
||||
kind: "file",
|
||||
type: "image/jpeg",
|
||||
getAsFile: () => new File(["pasted image"], "pasted.jpg", { type: "image/jpeg" }),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Simulate paste event
|
||||
const pasteEvent = new ClipboardEvent("paste", {
|
||||
clipboardData: mockClipboardData as any,
|
||||
});
|
||||
|
||||
document.dispatchEvent(pasteEvent);
|
||||
|
||||
// Should process the pasted image
|
||||
await waitFor(() => {
|
||||
expect(mockImageService.validateAndProcessImage).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("should show error for invalid image", async () => {
|
||||
// Mock image service to return error
|
||||
mockImageService.validateAndProcessImage.mockResolvedValue({
|
||||
success: false,
|
||||
error: "Invalid image format",
|
||||
});
|
||||
|
||||
const { container } = render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
const mockFile = new File(["invalid content"], "test.txt", {
|
||||
type: "text/plain",
|
||||
});
|
||||
|
||||
const fileInput = container.querySelector('input[type="file"]');
|
||||
if (fileInput) {
|
||||
await fireEvent.change(fileInput, {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
// Should show error message
|
||||
await waitFor(() => {
|
||||
expect(container.textContent).toContain("Error");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("should call onImageSelect when image is successfully processed", async () => {
|
||||
const mockImageUrl = "data:image/jpeg;base64,/9j/4AAQSkZJRg==";
|
||||
|
||||
// Mock successful image processing
|
||||
mockImageService.validateAndProcessImage.mockResolvedValue({
|
||||
success: true,
|
||||
imageUrl: mockImageUrl,
|
||||
});
|
||||
|
||||
const { container } = render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
const mockFile = new File(["test image content"], "test.jpg", {
|
||||
type: "image/jpeg",
|
||||
});
|
||||
|
||||
const fileInput = container.querySelector('input[type="file"]');
|
||||
if (fileInput) {
|
||||
await fireEvent.change(fileInput, {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
// Should call onImageSelect with processed image
|
||||
await waitFor(() => {
|
||||
expect(mockOnImageSelect).toHaveBeenCalledWith(mockImageUrl);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("should show loading state during processing", async () => {
|
||||
const { setLoading } = await import("$stores/uiStore");
|
||||
|
||||
// Mock slow processing
|
||||
mockImageService.validateAndProcessImage.mockImplementation(
|
||||
() =>
|
||||
new Promise((resolve) =>
|
||||
setTimeout(
|
||||
() =>
|
||||
resolve({
|
||||
success: true,
|
||||
imageUrl: "data:image/jpeg;base64,/9j/4AAQSkZJRg==",
|
||||
}),
|
||||
100,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
const { container } = render(ImageUpload, {
|
||||
props: {
|
||||
onImageSelect: mockOnImageSelect,
|
||||
},
|
||||
});
|
||||
|
||||
const mockFile = new File(["test image content"], "test.jpg", {
|
||||
type: "image/jpeg",
|
||||
});
|
||||
|
||||
const fileInput = container.querySelector('input[type="file"]');
|
||||
if (fileInput) {
|
||||
await fireEvent.change(fileInput, {
|
||||
target: { files: [mockFile] },
|
||||
});
|
||||
|
||||
// Should show loading state
|
||||
expect(setLoading).toHaveBeenCalledWith(true);
|
||||
|
||||
// Wait for processing to complete
|
||||
await waitFor(() => {
|
||||
expect(setLoading).toHaveBeenCalledWith(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user