Skip to content

Commit 6b34bae

Browse files
committed
修复 macOS 端到端交互稳定性
1 parent 4acc7f3 commit 6b34bae

2 files changed

Lines changed: 41 additions & 15 deletions

File tree

‎apps/desktop/e2e/prompt-rail.spec.ts‎

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,28 +211,43 @@ test('the pointer is always on a tick while it travels down the rail', async ({
211211
await expect
212212
.poll(async () => {
213213
const travel = await page.evaluate(() => {
214-
const ticks = [...document.querySelectorAll('.maka-prompt-rail-tick')];
214+
const ticks = [...document.querySelectorAll<HTMLElement>('.maka-prompt-rail-tick')];
215215
if (ticks.length < 2) throw new Error('the prompt rail needs at least two ticks');
216-
const first = ticks[0]!.getBoundingClientRect();
217-
const last = ticks[ticks.length - 1]!.getBoundingClientRect();
218-
const x = Math.round(first.left + first.width / 2);
216+
const boxes = ticks.map((tick) => tick.getBoundingClientRect());
217+
const first = boxes[0]!;
218+
const last = boxes[boxes.length - 1]!;
219219
const describe = (found: Element | null) =>
220220
found instanceof Element
221221
? `${found.tagName.toLowerCase()}.${found.className.toString().trim().replace(/\s+/g, '.')}`
222222
: 'null';
223-
const startY = Math.round(first.top + first.height / 2);
224-
const endY = Math.round(last.top + last.height / 2);
225-
const misses: Array<{ y: number; hit: string }> = [];
226-
for (let y = startY; y <= endY; y += 1) {
227-
const found = document.elementFromPoint(x, y);
228-
if (!found?.closest('.maka-prompt-rail-tick')) {
229-
misses.push({ y, hit: describe(found) });
223+
const misses: Array<{ index: number; kind: 'center' | 'seam'; hit: string }> = [];
224+
for (const [index, box] of boxes.entries()) {
225+
const found = document.elementFromPoint(
226+
box.left + box.width / 2,
227+
box.top + box.height / 2,
228+
);
229+
if (found?.closest('.maka-prompt-rail-tick') !== ticks[index]) {
230+
misses.push({ index, kind: 'center', hit: describe(found) });
231+
}
232+
}
233+
const gaps = boxes.slice(1).map((box, index) => box.top - boxes[index]!.bottom);
234+
for (let index = 0; index < boxes.length - 1; index += 1) {
235+
const before = boxes[index]!;
236+
const after = boxes[index + 1]!;
237+
const found = document.elementFromPoint(
238+
before.left + before.width / 2,
239+
(before.bottom + after.top) / 2,
240+
);
241+
const landed = found?.closest('.maka-prompt-rail-tick');
242+
if (landed !== ticks[index] && landed !== ticks[index + 1]) {
243+
misses.push({ index, kind: 'seam', hit: describe(found) });
230244
}
231245
}
232246
return {
233-
insideViewport: startY >= 0 && endY < window.innerHeight,
247+
insideViewport: first.top >= 0 && last.bottom <= window.innerHeight,
234248
misses: misses.length,
235-
hasSpan: endY > startY,
249+
hasSpan: last.bottom > first.top,
250+
continuousBoxes: Math.max(...gaps) <= 0.25,
236251
sample: misses.slice(0, 3),
237252
};
238253
});
@@ -242,6 +257,7 @@ test('the pointer is always on a tick while it travels down the rail', async ({
242257
insideViewport: true,
243258
misses: 0,
244259
hasSpan: true,
260+
continuousBoxes: true,
245261
});
246262
});
247263

‎apps/desktop/e2e/skill-draft-lifecycle.spec.ts‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,19 @@ async function composeWithSkill(page: Page, text: string, name: RegExp): Promise
5454
await composer.fill(text);
5555
await composer.click();
5656
await composer.pressSequentially(' /');
57-
const option = page.getByRole('listbox', { name: /技能/ }).getByRole('option', { name });
57+
const listbox = page.getByRole('listbox', { name: /技能/ });
58+
const option = listbox.getByRole('option', { name });
5859
await expect(option).toBeVisible();
59-
await option.click();
60+
// The suggestion list can re-rank once when the cold Skill projection
61+
// catches up. Walk its active-descendant state instead of racing a pointer
62+
// target that is being replaced under the cursor.
63+
const optionCount = await listbox.getByRole('option').count();
64+
for (let index = 0; index < optionCount; index += 1) {
65+
if ((await option.getAttribute('aria-selected')) === 'true') break;
66+
await composer.press('ArrowDown');
67+
}
68+
await expect(option).toHaveAttribute('aria-selected', 'true');
69+
await composer.press('Enter');
6070
}
6171

6272
async function beginRevision(page: Page): Promise<void> {

0 commit comments

Comments
 (0)