mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
fix(web-shell): hide turn navigation without sufficient gutters (#15604)
* fix(web-shell): hide turn navigation without sufficient gutters * test(web-shell): cover navigation visibility across desktop layouts --------- Co-authored-by: 钉萁 <[email protected]>
This commit is contained in:
1 parent
b63b733642
commit
9df10f873b
5 files changed
+60
-23
No files matched your search
@@ -51,7 +51,7 @@ test('search locates persisted history outside the live window without changing
|
||||
|
||||
for (const theme of ['light', 'dark']) {
|
||||
for (const language of ['en', 'zh-CN']) {
|
||||
for (const width of [1440, 390]) {
|
||||
for (const width of [1600, 1440, 390]) {
|
||||
test(`conversation search content and layout ${theme} ${language} ${width} @smoke`, async ({
|
||||
page,
|
||||
baseURL,
|
||||
@@ -74,19 +74,20 @@ for (const theme of ['light', 'dark']) {
|
||||
exact: true,
|
||||
});
|
||||
await expect(bottom).toBeVisible();
|
||||
await expect(button).toBeVisible();
|
||||
const searchBox = await button.boundingBox();
|
||||
const timeline = page.getByRole('navigation', {
|
||||
name: /Session timeline|会话时间线/,
|
||||
});
|
||||
await expect(
|
||||
timeline.getByRole('button', {
|
||||
name: /Search this conversation|搜索当前会话/,
|
||||
exact: true,
|
||||
}),
|
||||
).toBeVisible();
|
||||
expect(searchBox!.width).toBeLessThanOrEqual(20);
|
||||
expect(searchBox!.height).toBe(24);
|
||||
if (width === 1440) {
|
||||
if (width === 1600) {
|
||||
await expect(
|
||||
timeline.getByRole('button', {
|
||||
name: /Search this conversation|搜索当前会话/,
|
||||
exact: true,
|
||||
}),
|
||||
).toBeVisible();
|
||||
const tick = await timeline
|
||||
.locator('li button span')
|
||||
.first()
|
||||
@@ -96,6 +97,8 @@ for (const theme of ['light', 'dark']) {
|
||||
searchBox!.x + searchBox!.width / 2 - (tick!.x + tick!.width / 2),
|
||||
),
|
||||
).toBeLessThan(1);
|
||||
} else {
|
||||
await expect(timeline).toBeHidden();
|
||||
}
|
||||
await page.screenshot({
|
||||
path: `/tmp/qwen-12231-entry-${theme}-${language}-${width}.png`,
|
||||
|
||||
@@ -50,7 +50,7 @@ async function historyScenario(
|
||||
baseURL: string | undefined,
|
||||
pageRecords: number,
|
||||
) {
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await page.setViewportSize({ width: 1600, height: 900 });
|
||||
const count = pageRecords * 12;
|
||||
const sessionId = `history-navigation-${pageRecords}`;
|
||||
const live = Array.from({ length: 40 }, (_, index) =>
|
||||
|
||||
@@ -29,7 +29,7 @@ for (const navigation of [true, false]) {
|
||||
page,
|
||||
baseURL,
|
||||
}, testInfo) => {
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await page.setViewportSize({ width: 1600, height: 900 });
|
||||
const scenario = createWebShellDaemonScenario({
|
||||
events: Array.from({ length: 4 }, (_, index) => [
|
||||
userTextEvent('What is the weather?', { id: index * 3 + 1 }),
|
||||
@@ -117,7 +117,9 @@ for (const navigation of [true, false]) {
|
||||
'color(srgb 1 1 1 / 0.96)',
|
||||
);
|
||||
await scrollToBottom.click();
|
||||
for (const width of [1440, 1300, 1261, 1260, 1259, 1000, 802, 700, 599]) {
|
||||
for (const width of [
|
||||
1600, 1440, 1405, 1404, 1403, 1300, 1000, 802, 700, 599,
|
||||
]) {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await expectSameEdges(message, composer);
|
||||
const viewport = page.locator('[data-history-viewport]');
|
||||
@@ -132,7 +134,7 @@ for (const navigation of [true, false]) {
|
||||
})
|
||||
.toBeLessThanOrEqual(1);
|
||||
const viewportBox = await viewport.boundingBox();
|
||||
if (viewportBox && viewportBox.width >= 1000) {
|
||||
if (viewportBox && viewportBox.width >= 1128) {
|
||||
await expect(rail).toBeVisible();
|
||||
const railBox = await rail.boundingBox();
|
||||
const messageBox = await message.boundingBox();
|
||||
@@ -142,7 +144,7 @@ for (const navigation of [true, false]) {
|
||||
}
|
||||
}
|
||||
{
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await page.setViewportSize({ width: 1600, height: 900 });
|
||||
const shell = page.locator('[data-web-shell-root]');
|
||||
const sidebar = page.getByRole('complementary', {
|
||||
name: 'Workspace sidebar',
|
||||
@@ -155,17 +157,37 @@ for (const navigation of [true, false]) {
|
||||
'--chat-regular-content-width',
|
||||
`${width}px`,
|
||||
);
|
||||
element.style.setProperty('--chat-content-width', `${width}px`);
|
||||
element.style.setProperty('--chat-shell-width', `${width + 40}px`);
|
||||
}, minWidth);
|
||||
for (const offset of [-1, 0, 1]) {
|
||||
await page.setViewportSize({
|
||||
width: minWidth + sidebarWidth + offset,
|
||||
width: minWidth + 128 + sidebarWidth + offset,
|
||||
height: 900,
|
||||
});
|
||||
if (offset < 0) await expect(rail).toBeHidden();
|
||||
else await expect(rail).toBeVisible();
|
||||
else {
|
||||
await expect(rail).toBeVisible();
|
||||
const button = rail.locator('button').first();
|
||||
const tick = button.locator(':scope > span').first();
|
||||
await button.hover();
|
||||
await expect
|
||||
.poll(async () => (await tick.boundingBox())?.width ?? 0)
|
||||
.toBeGreaterThan(27);
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const tickBox = await tick.boundingBox();
|
||||
const messageBox = await message.boundingBox();
|
||||
return tickBox && messageBox
|
||||
? messageBox.x - tickBox.x - tickBox.width
|
||||
: -Infinity;
|
||||
})
|
||||
.toBeGreaterThanOrEqual(16);
|
||||
await page.mouse.move(500, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
await page.setViewportSize({ width: 1000 + sidebarWidth, height: 900 });
|
||||
await page.setViewportSize({ width: 1128 + sidebarWidth, height: 900 });
|
||||
await shell.evaluate((element) => {
|
||||
element.style.setProperty('--chat-regular-content-width', '1200px');
|
||||
});
|
||||
@@ -174,8 +196,17 @@ for (const navigation of [true, false]) {
|
||||
element.style.setProperty('--chat-regular-content-width', '1000px');
|
||||
});
|
||||
await expect(rail).toBeVisible();
|
||||
await shell.evaluate((element) => {
|
||||
element.style.setProperty('--chat-content-width', '100%');
|
||||
});
|
||||
await expect(rail).toBeHidden();
|
||||
await shell.evaluate((element) => {
|
||||
element.style.setProperty('--chat-content-width', '1000px');
|
||||
element.style.setProperty('--chat-shell-width', '1040px');
|
||||
});
|
||||
await expect(rail).toBeVisible();
|
||||
}
|
||||
for (const width of [1440, 1360]) {
|
||||
for (const width of [1600, 1500]) {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
const button = rail.locator('button').first();
|
||||
const tick = button.locator(':scope > span').first();
|
||||
|
||||
@@ -82,7 +82,7 @@ test('global turn navigation follows transcript scrolling @smoke', async ({
|
||||
page,
|
||||
baseURL,
|
||||
}) => {
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await page.setViewportSize({ width: 1600, height: 900 });
|
||||
const live = Array.from({ length: TURNS * 2 }, (_, index) =>
|
||||
recordEvent(
|
||||
index,
|
||||
@@ -178,7 +178,7 @@ test('global turn navigation follows transcript scrolling @smoke', async ({
|
||||
await expect(rail).toBeHidden();
|
||||
await scrollTranscriptTo(page, 0.5);
|
||||
await expect.poll(() => ariaOrdinal(page)).toBeNull();
|
||||
await page.setViewportSize({ width: 1440, height: 900 });
|
||||
await page.setViewportSize({ width: 1600, height: 900 });
|
||||
await expect(rail).toBeVisible();
|
||||
await expect.poll(() => ariaOrdinal(page)).not.toBeNull();
|
||||
const ratio = await markerOffsetRatio(page);
|
||||
|
||||
@@ -13,13 +13,16 @@ export function useChatNavigationVisible(
|
||||
}
|
||||
const container = element.closest('[data-history-viewport]') ?? element;
|
||||
const update = () => {
|
||||
const style = getComputedStyle(element);
|
||||
const minWidth =
|
||||
Number.parseFloat(
|
||||
getComputedStyle(element).getPropertyValue(
|
||||
'--chat-regular-content-width',
|
||||
),
|
||||
style.getPropertyValue('--chat-regular-content-width'),
|
||||
) || 1000;
|
||||
setVisible(container.getBoundingClientRect().width >= minWidth);
|
||||
// Reserve 64px gutters so hover-expanded ticks stay clear of the text.
|
||||
setVisible(
|
||||
style.getPropertyValue('--chat-content-width').trim() !== '100%' &&
|
||||
container.getBoundingClientRect().width >= minWidth + 128,
|
||||
);
|
||||
};
|
||||
update();
|
||||
const resize =
|
||||
|
||||
Reference in new issue
Block a user