feat(chat): show playful teacher introductions on hover
This commit is contained in:
@@ -70,6 +70,76 @@ async function geometry(page: Page) {
|
||||
});
|
||||
}
|
||||
|
||||
for (const width of [520, 1000]) {
|
||||
test(`teacher introduction floats outside the scrolling strip and clears the work at ${width}px`, async ({ page }) => {
|
||||
await page.setViewportSize({ width, height: 800 });
|
||||
await page.goto(`${baseUrl}?agents=8&quiet=1`);
|
||||
const first = page.getByRole('button', { name: '与智能体1聊天', exact: true });
|
||||
const card = page.getByTestId('teacher-introduction');
|
||||
await expect(first).not.toHaveAttribute('title');
|
||||
await first.hover();
|
||||
await expect(card).toBeVisible();
|
||||
await expect(card.locator('.teacher-introduction-description')).toContainText('我是智能体1');
|
||||
await page.getByRole('button', { name: '与智能体2聊天', exact: true }).hover();
|
||||
await expect(card).toHaveCount(1);
|
||||
await expect(card.locator('.teacher-introduction-description')).toContainText('我是智能体2');
|
||||
await first.hover();
|
||||
await expect(card.locator('.teacher-introduction-description')).toContainText('我是智能体1');
|
||||
await expect.poll(async () => page.evaluate(() => {
|
||||
const card = document.querySelector('[data-testid="teacher-introduction"]')!.getBoundingClientRect();
|
||||
const viewport = document.querySelector('[data-testid="agent-browser-viewport"]')!.getBoundingClientRect();
|
||||
return card.left >= 0 && card.right <= innerWidth && card.bottom <= innerHeight
|
||||
&& (card.left >= viewport.right || card.right <= viewport.left || viewport.top - card.bottom >= 8);
|
||||
})).toBe(true);
|
||||
await card.hover();
|
||||
await expect(card).toBeVisible();
|
||||
await page.screenshot({ path: test.info().outputPath('teacher-hover-introduction.png') });
|
||||
const cardBounds = (await card.boundingBox())!;
|
||||
await page.screenshot({ path: test.info().outputPath('teacher-introduction-card.png'), clip: {
|
||||
x: Math.max(0, cardBounds.x - 12), y: cardBounds.y - 12,
|
||||
width: cardBounds.width + 24, height: cardBounds.height + 30,
|
||||
} });
|
||||
await page.mouse.move(0, 780);
|
||||
await expect(card).toHaveCount(0);
|
||||
await expect(page.getByTestId('agent-browser-panel')).toHaveCSS('margin-top', '0px');
|
||||
|
||||
const last = page.getByRole('button', { name: '与智能体8聊天', exact: true });
|
||||
await last.focus();
|
||||
await expect(card).toBeVisible();
|
||||
await expect(card.locator('.teacher-introduction-description')).toContainText('我是智能体8');
|
||||
await last.press('Escape');
|
||||
await expect(card).toHaveCount(0);
|
||||
await expect(last).toBeFocused();
|
||||
await last.hover();
|
||||
await expect(card).toBeVisible();
|
||||
await last.click();
|
||||
await expect(card).toHaveCount(0);
|
||||
await expect(page.locator('#coding-consultation-dock')).toBeVisible();
|
||||
const lastBounds = (await last.boundingBox())!;
|
||||
await page.mouse.move(lastBounds.x + lastBounds.width / 2 + 2, lastBounds.y + lastBounds.height / 2);
|
||||
await page.waitForTimeout(300);
|
||||
await expect(card).toHaveCount(0);
|
||||
await page.mouse.move(0, 780);
|
||||
await last.hover();
|
||||
await expect(card).toBeVisible();
|
||||
await last.click();
|
||||
await expect(page.locator('#coding-consultation-dock')).toHaveCount(0);
|
||||
});
|
||||
}
|
||||
|
||||
test('closing an introduction preserves the unread speech and its native preview clearance', async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1180, height: 720 });
|
||||
await page.goto(`${baseUrl}?agents=2`);
|
||||
await expect.poll(async () => (await geometry(page)).nativeGap).toBeGreaterThanOrEqual(8);
|
||||
const original = (await geometry(page)).clearance;
|
||||
await page.getByRole('button', { name: '与智能体2聊天', exact: true }).hover();
|
||||
await expect(page.getByTestId('teacher-introduction')).toBeVisible();
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(page.getByTestId('teacher-introduction')).toHaveCount(0);
|
||||
await expect(page.getByTestId('teacher-invitation')).toBeVisible();
|
||||
await expect.poll(async () => (await geometry(page)).clearance).toBe(original);
|
||||
});
|
||||
|
||||
test('distributed icons load over HTTP and broken images fall back in the titlebar', async ({ page }) => {
|
||||
await page.route('https://yuxi.example.test/api/storage/public/images/agent-0.png', route => route.fulfill({
|
||||
contentType: 'image/svg+xml',
|
||||
|
||||
Reference in New Issue
Block a user