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;
|
||||
}) => <div data-testid="responsive-grid">{children}</div>,
|
||||
noCompactor: () => null,
|
||||
}));
|
||||
|
||||
// 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';
|
||||
|
||||
// Mock next-intl
|
||||
@@ -80,32 +80,15 @@ describe('NoteWidget', () => {
|
||||
<NoteWidget instanceId="note-1" config={{}} isEditMode={false} />,
|
||||
);
|
||||
|
||||
const editor = screen.getByTestId('md-editor');
|
||||
|
||||
// Type into editor
|
||||
// Enable edit mode so onChange is wired up
|
||||
await act(async () => {
|
||||
editor.dispatchEvent(
|
||||
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
|
||||
fireEvent.click(screen.getByRole('button'));
|
||||
});
|
||||
|
||||
// Directly trigger onChange via the textarea
|
||||
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 }));
|
||||
});
|
||||
const textarea = screen.getByTestId('md-editor') as HTMLTextAreaElement;
|
||||
|
||||
// Before debounce fires, fetch should NOT have been called
|
||||
fireEvent.change(textarea, { target: { value: '# Hello' } });
|
||||
expect(fetchSpy).not.toHaveBeenCalled();
|
||||
|
||||
// Advance past debounce window
|
||||
@@ -126,18 +109,16 @@ describe('NoteWidget', () => {
|
||||
<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;
|
||||
|
||||
// Simulate rapid typing — three changes in quick succession
|
||||
for (const char of ['H', 'He', 'Hel']) {
|
||||
await act(async () => {
|
||||
Object.getOwnPropertyDescriptor(
|
||||
HTMLTextAreaElement.prototype,
|
||||
'value',
|
||||
)?.set?.call(textarea, char);
|
||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
// Small delay between keystrokes (less than debounce)
|
||||
fireEvent.change(textarea, { target: { value: char } });
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(200);
|
||||
});
|
||||
@@ -162,17 +143,15 @@ describe('NoteWidget', () => {
|
||||
<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;
|
||||
|
||||
// First change -> debounce -> save starts
|
||||
await act(async () => {
|
||||
Object.getOwnPropertyDescriptor(
|
||||
HTMLTextAreaElement.prototype,
|
||||
'value',
|
||||
)?.set?.call(textarea, 'first');
|
||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
|
||||
fireEvent.change(textarea, { target: { value: 'first' } });
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(1500);
|
||||
});
|
||||
@@ -181,14 +160,7 @@ describe('NoteWidget', () => {
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Second change -> debounce -> should abort the first
|
||||
await act(async () => {
|
||||
Object.getOwnPropertyDescriptor(
|
||||
HTMLTextAreaElement.prototype,
|
||||
'value',
|
||||
)?.set?.call(textarea, 'second');
|
||||
textarea.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
});
|
||||
|
||||
fireEvent.change(textarea, { target: { value: 'second' } });
|
||||
await act(async () => {
|
||||
vi.advanceTimersByTime(1500);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user