fix: center bottom composer between sidebar and teachers
This commit is contained in:
@@ -69,7 +69,8 @@ for (const width of [375, 768, 1280, 1470]) {
|
||||
await expect(composer).toBeInViewport({ ratio: 1 });
|
||||
const box = (await composer.boundingBox())!;
|
||||
expect(850 - box.y - box.height).toBeLessThanOrEqual(40);
|
||||
expect((await page.getByTestId('community-invitation').boundingBox())!.y).toBeLessThan(box.y);
|
||||
const invitation = (await page.getByTestId('community-invitation').boundingBox())!;
|
||||
expect(box.y - invitation.y - invitation.height).toBeCloseTo(12, 0);
|
||||
await page.screenshot({ path: test.info().outputPath(`community-welcome-${width}.png`) });
|
||||
});
|
||||
}
|
||||
@@ -80,12 +81,49 @@ test('a short window scrolls the welcome while keeping the composer at the botto
|
||||
const composer = page.getByTestId('coding-message-composer');
|
||||
await expect(composer).toBeInViewport({ ratio: 1 });
|
||||
const before = (await composer.boundingBox())!;
|
||||
await page.getByTestId('community-invitation').scrollIntoViewIfNeeded();
|
||||
await page.locator('.classroom-chat-view').evaluate(el => { el.scrollTop = el.scrollHeight; });
|
||||
const after = (await composer.boundingBox())!;
|
||||
expect(after.y).toBeCloseTo(before.y, 0);
|
||||
expect(600 - after.y - after.height).toBeLessThanOrEqual(40);
|
||||
});
|
||||
|
||||
for (const width of [1280, 1470]) {
|
||||
test(`the bottom input is centered between the project sidebar and fixed teacher panel at ${width}px`, async ({ page }) => {
|
||||
await page.setViewportSize({ width, height: 850 });
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
await page.goto(baseUrl + '?teachers&sidebar');
|
||||
const teachers = page.getByTestId('teacher-welcomes');
|
||||
const composer = page.getByTestId('coding-message-composer');
|
||||
await expect(teachers).toHaveCSS('width', '340px');
|
||||
await expect.poll(async () => {
|
||||
const [side, teacher, input] = await Promise.all([
|
||||
page.getByTestId('project-sidebar').boundingBox(), teachers.boundingBox(), composer.boundingBox(),
|
||||
]);
|
||||
return Math.abs((input!.x + input!.width / 2) - (side!.x + side!.width + teacher!.x) / 2);
|
||||
}).toBeLessThan(2);
|
||||
const input = (await composer.boundingBox())!;
|
||||
const invitation = (await page.getByTestId('community-invitation').boundingBox())!;
|
||||
expect(invitation.x).toBeCloseTo(input.x, 0);
|
||||
expect(invitation.width).toBeCloseTo(input.width, 0);
|
||||
expect(input.y - invitation.y - invitation.height).toBeCloseTo(12, 0);
|
||||
await page.screenshot({ path: test.info().outputPath(`composer-between-panels-${width}.png`) });
|
||||
await composer.getByRole('textbox').fill('保留这份草稿');
|
||||
await page.getByTestId('project-sidebar').evaluate(el => { el.style.width = '60px'; });
|
||||
await expect.poll(async () => {
|
||||
const [side, teacher, input] = await Promise.all([
|
||||
page.getByTestId('project-sidebar').boundingBox(), teachers.boundingBox(), composer.boundingBox(),
|
||||
]);
|
||||
return Math.abs(input!.x + input!.width / 2 - (side!.x + side!.width + teacher!.x) / 2);
|
||||
}).toBeLessThan(2);
|
||||
await teachers.getByRole('button', { name: '先自己试试' }).click();
|
||||
await expect(composer.getByRole('textbox')).toHaveValue('保留这份草稿');
|
||||
await expect.poll(async () => {
|
||||
const [side, input] = await Promise.all([page.getByTestId('project-sidebar').boundingBox(), composer.boundingBox()]);
|
||||
return Math.abs(input!.x + input!.width / 2 - (side!.x + side!.width + width) / 2);
|
||||
}).toBeLessThan(2);
|
||||
});
|
||||
}
|
||||
|
||||
test('the community link opens only on click and leaves the draft mounted', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1280, height: 850 });
|
||||
const communityRequests: string[] = [];
|
||||
|
||||
@@ -27,7 +27,9 @@ export function Layout() {
|
||||
dismissWelcome: (id: string) => setDismissed(values => [...values, id]),
|
||||
dismissWelcomes: () => setDismissed(['0', '1']),
|
||||
} as ComponentProps<typeof TeacherCompanion>['companion'];
|
||||
return <div className="classroom-workspace flex h-screen flex-col bg-white">
|
||||
return <div className="flex h-screen">
|
||||
{new URLSearchParams(location.search).has('sidebar') && <aside data-testid="project-sidebar" className="shrink-0 border-r p-4 text-sm" style={{ width: 210, background: '#f1f6fc' }}>我的项目</aside>}
|
||||
<div className="classroom-workspace flex min-w-0 flex-1 flex-col bg-white">
|
||||
<header className="relative z-50 flex h-12 shrink-0 items-center justify-end border-b px-3" data-testid="coding-conversation-header">
|
||||
<span className="mr-auto min-w-0 truncate text-xs">测试项目 › 新对话</span>
|
||||
<TeacherCompanion companion={companion} open={false} onOpen={() => {}} onToggle={() => {}} bubbleRef={setBubble} />
|
||||
@@ -35,8 +37,9 @@ export function Layout() {
|
||||
<main className="classroom-main flex min-h-0 min-w-0 flex-1 flex-col">
|
||||
<div className="classroom-tabs" role="tablist"><button role="tab" aria-selected="true">操作对话</button><button role="tab">作品</button></div>
|
||||
<CodingChatBody welcome={!sent} hidden={false} bubble={bubble}>
|
||||
<div className="classroom-chat-view min-h-0 flex-1 flex-col">{!sent ? <><CodingStartHeading /><CommunityInvitation /></> : <p>第一条消息已发送(测试)</p>}</div>
|
||||
<div className="classroom-chat-view min-h-0 flex-1 flex-col">{!sent ? <CodingStartHeading /> : <p>第一条消息已发送(测试)</p>}</div>
|
||||
<div className="classroom-composer-view shrink-0">
|
||||
{!sent && <CommunityInvitation />}
|
||||
<CodingComposer value={draft} editable canSend={Boolean(draft)} preparing={false} recovering={false}
|
||||
runStatus="idle" mode="prompt" queue={{ items: [] }} error={null} recoverableError={false}
|
||||
attachments={[]} submitting={false} placeholder="说说你的想法,接下来想做什么?" onChange={setDraft}
|
||||
@@ -45,6 +48,6 @@ export function Layout() {
|
||||
</div>
|
||||
</CodingChatBody>
|
||||
</main>
|
||||
</div>;
|
||||
</div></div>;
|
||||
}
|
||||
createRoot(document.getElementById('root')!).render(<Layout />);
|
||||
|
||||
@@ -1112,6 +1112,11 @@ test('first PI Conversation is editable under 500 ms and submits before runtime
|
||||
|
||||
await expect(page.getByTestId('coding-message-composer')).toBeInViewport({ ratio: 1 });
|
||||
expect(await page.getByTestId('coding-message-composer').evaluate(el => innerHeight - el.getBoundingClientRect().bottom)).toBeLessThan(40);
|
||||
await expect(page.getByTestId('community-invitation')).toBeVisible();
|
||||
expect(await page.getByTestId('community-invitation').evaluate(el => {
|
||||
const composer = document.querySelector('[data-testid="coding-message-composer"]')!;
|
||||
return composer.getBoundingClientRect().top - el.getBoundingClientRect().bottom;
|
||||
})).toBeCloseTo(12, 0);
|
||||
|
||||
const pixelPng = Buffer.from(
|
||||
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=',
|
||||
|
||||
Reference in New Issue
Block a user