Merge branch 'v1422/fixes' into release/v1.42.2

This commit is contained in:
Marc-André Bombeck committed 2026-10-11 13:28:29 +02:00
commit 3c4e053dcd
83 files changed
+1808 -258

No files matched your search

+19 -5
View File
@@ -185,12 +185,26 @@ test.describe("Coach: a saved conversation opens at its end", () => {
waitUntil: "domcontentloaded",
});
const thread = page.locator('[data-slot="coach-message-thread"]');
await expect(thread).toBeVisible({ timeout: 15_000 });
// The empty state carries the same `coach-message-thread` slot, so the
// thread being visible says nothing about the conversation having
// arrived; the height used to be read from the empty state on a slow
// run. Wait for the frame only a loaded thread renders, and for every
// stored answer in it.
await expect(
page.locator('[data-slot="coach-message-thread-frame"]'),
).toBeVisible({ timeout: 15_000 });
await expect(
page.locator('[data-slot="coach-assistant-turn"]'),
).toHaveCount(8, { timeout: 15_000 });
const thread = page.locator(
'[data-slot="coach-message-thread-frame"] [data-slot="coach-message-thread"]',
);
// The thread scrolls at all: otherwise "at the end" proves nothing.
expect(
await thread.evaluate((el) => el.scrollHeight > el.clientHeight + 200),
).toBe(true);
await expect
.poll(() =>
thread.evaluate((el) => el.scrollHeight > el.clientHeight + 200),
)
.toBe(true);
const chart = page.locator(
'[data-slot="coach-result-chart"][data-ref="r1"]',
+19
View File
@@ -275,6 +275,25 @@ test.describe("the day view", () => {
),
)
.toBe(true);
// On a phone the calendar is a sheet over the day's own sheet. Focus
// arrives before Radix has handed it the Escape key: in between, the day
// underneath still holds it. The handover shows as the day's layer
// turning inert (`pointer-events: none`) once the calendar is the top
// layer; wait for that, not for a fixed time. The docked column is no
// dialog and has no such handover.
if (!desktop)
await expect
.poll(() =>
panel(page).evaluate(
(el) =>
new Promise<string>((resolve) =>
requestAnimationFrame(() =>
setTimeout(() => resolve(getComputedStyle(el).pointerEvents)),
),
),
),
)
.toBe("none");
await page.keyboard.press("Escape");
await expect(picker).toHaveCount(0);
await expect(panel(page)).toBeVisible();
+39
View File
@@ -232,6 +232,45 @@ test.describe("document vault", () => {
await expect(sheet.locator("iframe")).toBeVisible({ timeout: 5_000 });
});
test("a PDF opens in a new browser tab from the fetched bytes", async ({
page,
}) => {
// Headless Chromium has no PDF viewer and turns a PDF tab into a
// download, so the tab itself is not observable here. Record what the
// control hands to `window.open` instead, and read the bytes behind it.
await page.addInitScript(() => {
const calls: unknown[][] = [];
(window as unknown as { __opened: unknown[][] }).__opened = calls;
window.open = (...args: unknown[]) => {
calls.push(args);
return null;
};
});
await page.goto(`/documents?episode=${KNIE_EPISODE_ID}&view=compact&q=MRT`);
await openButton(page, "MRT Knie").click();
const sheet = page.getByRole("dialog", { name: "MRT Knie" });
await expect(sheet.locator("iframe")).toBeVisible({ timeout: 5_000 });
const open = sheet.locator('[data-slot="document-open-in-tab"]');
// Enabled once the preview's bytes are in hand.
await expect(open).toBeEnabled();
if (process.env.E2E_SHOT_DIR) {
await page.screenshot({
path: `${process.env.E2E_SHOT_DIR}/open-in-tab-${test.info().project.name}.png`,
});
}
await open.click();
const opened = await page.evaluate(
() => (window as unknown as { __opened: string[][] }).__opened,
);
// The object URL the preview already shows, not the serve route: a bare
// navigation would carry no record-session assertion.
const previewSrc = await sheet.locator("iframe").getAttribute("src");
expect(previewSrc).toMatch(/^blob:/);
expect(opened).toEqual([[previewSrc, "_blank", "noopener"]]);
// The sheet stays where it was.
await expect(sheet).toBeVisible();
});
test("doctor flow B: the condition filter reaches the MRT report", async ({
page,
}) => {