Files
Genarrative/src/components/image-editor/EditorAgentConversation/EditorAgentDraftTextarea.test.tsx
T
k88936 62bbd3876a
Project CI / Backend tests (pull_request) Failing after 11s
Project CI / Repository checks (pull_request) Failing after 12s
Project CI / Frontend tests (pull_request) Successful in 30s
Project CI / Native shell tests (pull_request) Successful in 1m59s
fix: textarea fallback 高度加入 offsetHeight - clientHeight 的边框差,溢出判断也改用完整 border-box 高度。
2026-07-23 13:41:12 +08:00

126 lines
3.9 KiB
TypeScript

/* @vitest-environment jsdom */
import { act, fireEvent, render, screen } from '@testing-library/react';
import type { FormEvent } from 'react';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { EditorAgentDraftTextarea } from './EditorAgentDraftTextarea.tsx';
afterEach(() => {
vi.unstubAllGlobals();
});
describe('EditorAgentDraftTextarea', () => {
it('uses native field sizing when the browser supports it', () => {
const supports = vi.fn().mockReturnValue(true);
const resizeObserver = vi.fn();
const onChange = vi.fn();
vi.stubGlobal('CSS', { supports });
vi.stubGlobal('ResizeObserver', resizeObserver);
render(<EditorAgentDraftTextarea value="" onChange={onChange} />);
const input = screen.getByLabelText(
'发送给画布 Agent',
) as HTMLTextAreaElement;
expect(supports).toHaveBeenCalledWith('field-sizing', 'content');
expect(resizeObserver).not.toHaveBeenCalled();
expect(input.className).toContain('[field-sizing:content]');
expect(input.className).toContain('min-h-10');
expect(input.className).toContain('max-h-32');
expect(input.className).toContain('overflow-y-auto');
expect(input.style.height).toBe('');
fireEvent.change(input, { target: { value: '新草稿' } });
expect(onChange).toHaveBeenCalledWith('新草稿');
});
it('falls back to measured sizing and remeasures when width changes', () => {
let resizeObserverCallback!: ResizeObserverCallback;
const observe = vi.fn();
const disconnect = vi.fn();
vi.stubGlobal('CSS', { supports: vi.fn().mockReturnValue(false) });
vi.stubGlobal(
'ResizeObserver',
vi.fn().mockImplementation((callback: ResizeObserverCallback) => {
resizeObserverCallback = callback;
return {
observe,
unobserve: vi.fn(),
disconnect,
};
}),
);
const { rerender, unmount } = render(
<EditorAgentDraftTextarea value="" onChange={vi.fn()} />,
);
const input = screen.getByLabelText(
'发送给画布 Agent',
) as HTMLTextAreaElement;
expect(observe).toHaveBeenCalledWith(input);
let contentHeight = 92;
Object.defineProperty(input, 'offsetHeight', {
configurable: true,
get: () => {
const styleHeight = Number.parseFloat(input.style.height);
return Number.isNaN(styleHeight) ? 42 : styleHeight;
},
});
Object.defineProperty(input, 'clientHeight', {
configurable: true,
get: () => input.offsetHeight - 2,
});
Object.defineProperty(input, 'scrollHeight', {
configurable: true,
get: () => contentHeight,
});
rerender(
<EditorAgentDraftTextarea
value="第一行\n第二行\n第三行\n第四行\n第五行"
onChange={vi.fn()}
/>,
);
expect(input.style.height).toBe('94px');
expect(input.style.overflowY).toBe('hidden');
expect(input.scrollHeight).toBeLessThanOrEqual(input.clientHeight);
contentHeight = 180;
act(() => {
resizeObserverCallback(
[
{
target: input,
contentRect: { width: 180 },
} as unknown as ResizeObserverEntry,
],
{} as ResizeObserver,
);
});
expect(input.style.height).toBe('128px');
expect(input.style.overflowY).toBe('auto');
unmount();
expect(disconnect).toHaveBeenCalledTimes(1);
});
it('submits on Enter and keeps Shift+Enter for line breaks', () => {
const onSubmit = vi.fn((event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
});
render(
<form onSubmit={onSubmit}>
<EditorAgentDraftTextarea value="草稿" onChange={vi.fn()} />
</form>,
);
const input = screen.getByLabelText('发送给画布 Agent');
fireEvent.keyDown(input, { key: 'Enter', shiftKey: true });
expect(onSubmit).not.toHaveBeenCalled();
fireEvent.keyDown(input, { key: 'Enter' });
expect(onSubmit).toHaveBeenCalledTimes(1);
});
});