fix(tests): add noCompactor mock + fix note-widget event simulation
- dashboard-grid.test: add noCompactor to react-grid-layout mock - note-widget.test: enable edit mode before typing (onChange is undefined when isEditing=false), replace native dispatchEvent with fireEvent.change Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,7 @@ vi.mock('react-grid-layout', () => ({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) => <div data-testid="responsive-grid">{children}</div>,
|
}) => <div data-testid="responsive-grid">{children}</div>,
|
||||||
|
noCompactor: () => null,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Mock dashboard-api
|
// Mock dashboard-api
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { act, render, screen } from '@testing-library/react';
|
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
// Mock next-intl
|
// Mock next-intl
|
||||||
@@ -80,32 +80,15 @@ describe('NoteWidget', () => {
|
|||||||
<NoteWidget instanceId="note-1" config={{}} isEditMode={false} />,
|
<NoteWidget instanceId="note-1" config={{}} isEditMode={false} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
const editor = screen.getByTestId('md-editor');
|
// Enable edit mode so onChange is wired up
|
||||||
|
|
||||||
// Type into editor
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
editor.dispatchEvent(
|
fireEvent.click(screen.getByRole('button'));
|
||||||
new Event('change', { bubbles: true }),
|
|
||||||
);
|
|
||||||
// Simulate onChange via the mock
|
|
||||||
const event = new Event('input', { bubbles: true });
|
|
||||||
Object.defineProperty(event, 'target', { value: { value: '# Hello' } });
|
|
||||||
// Use fireEvent approach
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Directly trigger onChange via the textarea
|
const textarea = screen.getByTestId('md-editor') as HTMLTextAreaElement;
|
||||||
await act(async () => {
|
|
||||||
const textarea = screen.getByTestId('md-editor') as HTMLTextAreaElement;
|
|
||||||
// Change value triggers onChange in our mock
|
|
||||||
Object.getOwnPropertyDescriptor(
|
|
||||||
HTMLTextAreaElement.prototype,
|
|
||||||
'value',
|
|
||||||
)?.set?.call(textarea, '# Hello');
|
|
||||||
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
||||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Before debounce fires, fetch should NOT have been called
|
// Before debounce fires, fetch should NOT have been called
|
||||||
|
fireEvent.change(textarea, { target: { value: '# Hello' } });
|
||||||
expect(fetchSpy).not.toHaveBeenCalled();
|
expect(fetchSpy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
// Advance past debounce window
|
// Advance past debounce window
|
||||||
@@ -126,18 +109,16 @@ describe('NoteWidget', () => {
|
|||||||
<NoteWidget instanceId="note-1" config={{}} isEditMode={false} />,
|
<NoteWidget instanceId="note-1" config={{}} isEditMode={false} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Enable edit mode so onChange is wired up
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByRole('button'));
|
||||||
|
});
|
||||||
|
|
||||||
const textarea = screen.getByTestId('md-editor') as HTMLTextAreaElement;
|
const textarea = screen.getByTestId('md-editor') as HTMLTextAreaElement;
|
||||||
|
|
||||||
// Simulate rapid typing — three changes in quick succession
|
// Simulate rapid typing — three changes in quick succession
|
||||||
for (const char of ['H', 'He', 'Hel']) {
|
for (const char of ['H', 'He', 'Hel']) {
|
||||||
await act(async () => {
|
fireEvent.change(textarea, { target: { value: char } });
|
||||||
Object.getOwnPropertyDescriptor(
|
|
||||||
HTMLTextAreaElement.prototype,
|
|
||||||
'value',
|
|
||||||
)?.set?.call(textarea, char);
|
|
||||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
||||||
});
|
|
||||||
// Small delay between keystrokes (less than debounce)
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
vi.advanceTimersByTime(200);
|
vi.advanceTimersByTime(200);
|
||||||
});
|
});
|
||||||
@@ -162,17 +143,15 @@ describe('NoteWidget', () => {
|
|||||||
<NoteWidget instanceId="note-1" config={{}} isEditMode={false} />,
|
<NoteWidget instanceId="note-1" config={{}} isEditMode={false} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Enable edit mode so onChange is wired up
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByRole('button'));
|
||||||
|
});
|
||||||
|
|
||||||
const textarea = screen.getByTestId('md-editor') as HTMLTextAreaElement;
|
const textarea = screen.getByTestId('md-editor') as HTMLTextAreaElement;
|
||||||
|
|
||||||
// First change -> debounce -> save starts
|
// First change -> debounce -> save starts
|
||||||
await act(async () => {
|
fireEvent.change(textarea, { target: { value: 'first' } });
|
||||||
Object.getOwnPropertyDescriptor(
|
|
||||||
HTMLTextAreaElement.prototype,
|
|
||||||
'value',
|
|
||||||
)?.set?.call(textarea, 'first');
|
|
||||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
||||||
});
|
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
vi.advanceTimersByTime(1500);
|
vi.advanceTimersByTime(1500);
|
||||||
});
|
});
|
||||||
@@ -181,14 +160,7 @@ describe('NoteWidget', () => {
|
|||||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
// Second change -> debounce -> should abort the first
|
// Second change -> debounce -> should abort the first
|
||||||
await act(async () => {
|
fireEvent.change(textarea, { target: { value: 'second' } });
|
||||||
Object.getOwnPropertyDescriptor(
|
|
||||||
HTMLTextAreaElement.prototype,
|
|
||||||
'value',
|
|
||||||
)?.set?.call(textarea, 'second');
|
|
||||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
||||||
});
|
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
vi.advanceTimersByTime(1500);
|
vi.advanceTimersByTime(1500);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user