fix: restore GeoIntel and upgrade Atlas workbench
This commit is contained in:
@@ -1,524 +0,0 @@
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
|
||||
const browserErrors = new WeakMap<Page, string[]>();
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
const errors: string[] = [];
|
||||
browserErrors.set(page, errors);
|
||||
page.on("console", (message) => {
|
||||
if (message.type() === "error") errors.push(message.text());
|
||||
});
|
||||
page.on("pageerror", (error) => errors.push(error.message));
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
expect(browserErrors.get(page) ?? []).toEqual([]);
|
||||
});
|
||||
|
||||
const openSettings = async (
|
||||
page: import("@playwright/test").Page,
|
||||
projectName: string,
|
||||
) => {
|
||||
if (["mobile-chromium", "tablet-chromium"].includes(projectName)) {
|
||||
await page
|
||||
.getByRole("navigation", { name: "Mobiele navigatie" })
|
||||
.getByRole("button", { name: "Instellingen" })
|
||||
.click();
|
||||
return;
|
||||
}
|
||||
await page.getByRole("button", { name: "Instellingen openen" }).click();
|
||||
};
|
||||
|
||||
test("dashboard en Quick Launch vormen de primaire startflow", async ({
|
||||
page,
|
||||
context,
|
||||
}, testInfo) => {
|
||||
test.skip(
|
||||
testInfo.project.name !== "desktop-chromium",
|
||||
"De desktopflow wordt eenmaal uitgevoerd",
|
||||
);
|
||||
|
||||
await page.goto("/");
|
||||
await expect(page.getByRole("main")).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("navigation", { name: "Dashboardnavigatie" }),
|
||||
).toBeVisible();
|
||||
await expect(page.getByLabel(/graden.*Mol/)).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("complementary", {
|
||||
name: "Favorieten en deckstatus",
|
||||
}),
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("Live inzicht", { exact: true })).toBeVisible();
|
||||
await page.locator(".dashboard-insights-panel > summary").click();
|
||||
await expect(
|
||||
page.getByRole("region", { name: "Servicepanelen" }),
|
||||
).toBeVisible();
|
||||
|
||||
const refreshResponse = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().endsWith("/api/discovery/sync") &&
|
||||
response.request().method() === "POST",
|
||||
);
|
||||
await page
|
||||
.getByRole("button", { name: "Statussen vernieuwen" })
|
||||
.first()
|
||||
.click();
|
||||
expect((await refreshResponse).status()).toBe(200);
|
||||
|
||||
await page.keyboard.press("Control+K");
|
||||
const search = page.getByLabel("Zoek apps, favorieten of Google");
|
||||
await expect(search).toBeFocused();
|
||||
await search.fill("Google");
|
||||
const favoriteResults = page
|
||||
.locator(".result-group")
|
||||
.filter({ has: page.getByRole("heading", { name: "Favorieten" }) });
|
||||
await expect(
|
||||
favoriteResults.locator(".app-icon-image, .app-brand-icon"),
|
||||
).toHaveCount(1);
|
||||
await search.fill("Plex");
|
||||
await expect(
|
||||
page.getByRole("option", { name: /Plex Media Server/ }),
|
||||
).toBeVisible();
|
||||
|
||||
const googlePopupPromise = context.waitForEvent("page");
|
||||
await page.getByRole("option", { name: /Zoeken op Google naar/ }).click();
|
||||
const googlePopup = await googlePopupPromise;
|
||||
expect(googlePopup.url()).toContain("google.com/search");
|
||||
await googlePopup.close();
|
||||
});
|
||||
|
||||
test("dashboardcategorieën filteren de zichtbare snelkoppelingen", async ({
|
||||
page,
|
||||
request,
|
||||
}, testInfo) => {
|
||||
test.skip(
|
||||
testInfo.project.name !== "desktop-chromium",
|
||||
"De desktopflow wordt eenmaal uitgevoerd",
|
||||
);
|
||||
|
||||
const dashboard = await (await request.get("/api/dashboard")).json();
|
||||
const [firstApp, secondApp] = dashboard.apps;
|
||||
const [firstCategory, secondCategory] = dashboard.categories;
|
||||
expect(firstApp).toBeTruthy();
|
||||
expect(secondApp).toBeTruthy();
|
||||
expect(firstCategory).toBeTruthy();
|
||||
expect(secondCategory).toBeTruthy();
|
||||
await request.patch(`/api/apps/${firstApp.id}`, {
|
||||
data: { visible: true, categoryId: firstCategory.id },
|
||||
});
|
||||
await request.patch(`/api/apps/${secondApp.id}`, {
|
||||
data: { visible: true, categoryId: secondCategory.id },
|
||||
});
|
||||
|
||||
await page.goto("/");
|
||||
const categoryButton = page
|
||||
.locator(".category-tabs button")
|
||||
.filter({ hasText: firstCategory.name })
|
||||
.first();
|
||||
await categoryButton.click();
|
||||
|
||||
await expect(categoryButton).toHaveClass(/active/);
|
||||
await expect(page.locator(".dashboard-groups .app-section")).toHaveCount(1);
|
||||
await expect(page.locator(".dashboard-groups .app-section h2")).toContainText(
|
||||
firstCategory.name,
|
||||
);
|
||||
});
|
||||
|
||||
test("compact appbeheer opent een toegankelijke detail-drawer", async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
test.skip(
|
||||
testInfo.project.name !== "desktop-chromium",
|
||||
"De desktopflow wordt eenmaal uitgevoerd",
|
||||
);
|
||||
|
||||
await page.goto("/");
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "App Beheer", exact: true }),
|
||||
).toBeVisible();
|
||||
await page.getByLabel("Apps zoeken").fill("Plex");
|
||||
const row = page.getByRole("article").filter({ hasText: "Plex" });
|
||||
await expect(row).toBeVisible();
|
||||
const visibilitySwitch = row.getByRole("switch");
|
||||
const knob = visibilitySwitch.locator(".visibility-toggle-track > span");
|
||||
const initialVisibility = await visibilitySwitch.getAttribute("aria-checked");
|
||||
const initialKnob = await knob.boundingBox();
|
||||
await visibilitySwitch.click();
|
||||
await expect(visibilitySwitch).toHaveAttribute(
|
||||
"aria-checked",
|
||||
initialVisibility === "true" ? "false" : "true",
|
||||
);
|
||||
await expect
|
||||
.poll(async () => {
|
||||
const movedKnob = await knob.boundingBox();
|
||||
return Math.abs((movedKnob?.x ?? 0) - (initialKnob?.x ?? 0));
|
||||
})
|
||||
.toBeGreaterThan(18);
|
||||
await visibilitySwitch.click();
|
||||
await row.getByRole("button", { name: /Bewerken/ }).click();
|
||||
|
||||
const drawer = page.getByRole("dialog", { name: /Plex/ });
|
||||
await expect(drawer).toBeVisible();
|
||||
await expect(drawer.getByLabel("Weergavenaam")).toHaveValue(/Plex/);
|
||||
await expect(
|
||||
drawer.getByText("Automatisch ontdekt", { exact: true }),
|
||||
).toBeVisible();
|
||||
await drawer.getByRole("button", { name: "Sluiten" }).click();
|
||||
await expect(drawer).toBeHidden();
|
||||
await expect(row.getByRole("button", { name: /Bewerken/ })).toBeFocused();
|
||||
});
|
||||
|
||||
test("weergavevoorkeuren en geavanceerde read-only status blijven werken", async ({
|
||||
page,
|
||||
request,
|
||||
}, testInfo) => {
|
||||
test.skip(
|
||||
testInfo.project.name !== "desktop-chromium",
|
||||
"De desktopflow wordt eenmaal uitgevoerd",
|
||||
);
|
||||
|
||||
await request.patch("/api/preferences", {
|
||||
data: { reducedMotion: false, pollingIntervalMs: 30000 },
|
||||
});
|
||||
await page.goto("/");
|
||||
await openSettings(page, testInfo.project.name);
|
||||
const settingsNavigation = page.getByRole("navigation", {
|
||||
name: "Instellingensecties",
|
||||
});
|
||||
|
||||
await settingsNavigation.getByRole("button", { name: "Weergave" }).click();
|
||||
await page.getByRole("button", { name: /Haven/ }).click();
|
||||
await expect(page.locator("html")).toHaveAttribute("data-theme", "harbor");
|
||||
await page.locator(".appearance-advanced > summary").click();
|
||||
await page.getByRole("switch", { name: "Verminderde beweging" }).click();
|
||||
await page.getByLabel("Verversingsinterval").selectOption("60000");
|
||||
await expect(page.locator("html")).toHaveAttribute(
|
||||
"data-reduced-motion",
|
||||
"true",
|
||||
);
|
||||
await page.reload();
|
||||
await expect(page.locator("html")).toHaveAttribute("data-theme", "harbor");
|
||||
await expect(page.locator("html")).toHaveAttribute(
|
||||
"data-reduced-motion",
|
||||
"true",
|
||||
);
|
||||
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await page.getByLabel("Instellingen zoeken").fill("diagnostiek");
|
||||
await expect(
|
||||
page
|
||||
.getByRole("navigation", { name: "Instellingensecties" })
|
||||
.getByRole("button", { name: "Algemeen" }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page
|
||||
.getByRole("navigation", { name: "Instellingensecties" })
|
||||
.getByRole("button", { name: "Apps" }),
|
||||
).toHaveCount(0);
|
||||
await page
|
||||
.getByRole("navigation", { name: "Instellingensecties" })
|
||||
.getByRole("button", { name: "Algemeen" })
|
||||
.click();
|
||||
await expect(
|
||||
page.getByRole("region", { name: "Paneelstudio" }),
|
||||
).toBeVisible();
|
||||
await page.getByRole("button", { name: "Systeemstatus" }).click();
|
||||
await page.getByRole("button", { name: "Diagnostiek uitvoeren" }).click();
|
||||
await expect(page.locator(".diagnostics-result")).toContainText("Database");
|
||||
});
|
||||
|
||||
test("achtergrondpresets en een geüploade wallpaper wijzigen de zichtbare canvas", async ({
|
||||
page,
|
||||
request,
|
||||
}, testInfo) => {
|
||||
test.skip(
|
||||
testInfo.project.name !== "desktop-chromium",
|
||||
"De visuele achtergrondflow wordt eenmaal uitgevoerd",
|
||||
);
|
||||
|
||||
await request.delete("/api/wallpaper");
|
||||
await request.patch("/api/preferences", {
|
||||
data: {
|
||||
backgroundStyle: "aurora",
|
||||
wallpaperFit: "contain",
|
||||
wallpaperPositionX: 50,
|
||||
wallpaperPositionY: 50,
|
||||
wallpaperZoom: 100,
|
||||
},
|
||||
});
|
||||
await page.goto("/");
|
||||
|
||||
const selectBackground = async (
|
||||
name: "Aurora" | "Blauwdruk" | "Minimaal",
|
||||
) => {
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await page
|
||||
.getByRole("navigation", { name: "Instellingensecties" })
|
||||
.getByRole("button", { name: "Weergave" })
|
||||
.click();
|
||||
await page.locator(".appearance-advanced > summary").click();
|
||||
await page.getByRole("button", { name: new RegExp(`^${name}`) }).click();
|
||||
await expect(page.locator("html")).toHaveAttribute(
|
||||
"data-background",
|
||||
{ Aurora: "aurora", Blauwdruk: "grid", Minimaal: "minimal" }[name],
|
||||
);
|
||||
await page
|
||||
.locator(".settings-topbar nav")
|
||||
.getByRole("button", { name: "Dashboard" })
|
||||
.click();
|
||||
return page.locator(".dashboard-canvas").evaluate((element) => ({
|
||||
image: getComputedStyle(element).backgroundImage,
|
||||
size: getComputedStyle(element).backgroundSize,
|
||||
}));
|
||||
};
|
||||
|
||||
const aurora = await selectBackground("Aurora");
|
||||
const grid = await selectBackground("Blauwdruk");
|
||||
const minimal = await selectBackground("Minimaal");
|
||||
expect(new Set([aurora.image, grid.image, minimal.image]).size).toBe(3);
|
||||
expect(grid.size).toContain("40px");
|
||||
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await page
|
||||
.getByRole("navigation", { name: "Instellingensecties" })
|
||||
.getByRole("button", { name: "Weergave" })
|
||||
.click();
|
||||
await page.locator(".appearance-advanced > summary").click();
|
||||
await page
|
||||
.locator('.wallpaper-settings input[type="file"]')
|
||||
.setInputFiles("public/dockdeck-icon.png");
|
||||
await expect(
|
||||
page.locator(".wallpaper-editor-preview .wallpaper-preview-image"),
|
||||
).toBeVisible();
|
||||
await page.getByRole("button", { name: "Vullend" }).click();
|
||||
await page.getByLabel("Horizontale wallpaperfocus").fill("32");
|
||||
await page.getByLabel("Verticale wallpaperfocus").fill("68");
|
||||
await page.getByLabel("Wallpaperzoom").fill("120");
|
||||
await page.getByRole("button", { name: "Toepassen" }).click();
|
||||
await page
|
||||
.locator(".settings-topbar nav")
|
||||
.getByRole("button", { name: "Dashboard" })
|
||||
.click();
|
||||
await expect(page.locator(".dashboard")).toHaveClass(/has-wallpaper/);
|
||||
const wallpaperStage = page.locator(".dashboard-wallpaper-stage");
|
||||
const wallpaperImage = wallpaperStage.locator(".dashboard-wallpaper-image");
|
||||
const wallpaperAmbient = wallpaperStage.locator(
|
||||
".dashboard-wallpaper-ambient",
|
||||
);
|
||||
await expect(wallpaperStage).toBeVisible();
|
||||
await expect(wallpaperImage).toHaveAttribute("src", /\/api\/wallpaper/);
|
||||
await expect(wallpaperAmbient).toHaveAttribute("src", /\/api\/wallpaper/);
|
||||
await expect
|
||||
.poll(() =>
|
||||
wallpaperImage.evaluate((element) => ({
|
||||
fit: getComputedStyle(element).objectFit,
|
||||
position: getComputedStyle(element).objectPosition,
|
||||
transform: getComputedStyle(element).transform,
|
||||
})),
|
||||
)
|
||||
.toMatchObject({
|
||||
fit: "cover",
|
||||
position: "32% 68%",
|
||||
});
|
||||
const stageBeforeScroll = await wallpaperStage.boundingBox();
|
||||
const canvasBackground = await page
|
||||
.locator(".dashboard-canvas")
|
||||
.evaluate((element) => ({
|
||||
color: getComputedStyle(element).backgroundColor,
|
||||
image: getComputedStyle(element).backgroundImage,
|
||||
}));
|
||||
expect(stageBeforeScroll?.x).toBe(0);
|
||||
expect(stageBeforeScroll?.width).toBe(testInfo.project.use.viewport!.width);
|
||||
expect(stageBeforeScroll?.y).toBe(72);
|
||||
expect(stageBeforeScroll?.height).toBe(
|
||||
testInfo.project.use.viewport!.height - 72,
|
||||
);
|
||||
expect(canvasBackground.image).toBe("none");
|
||||
expect(canvasBackground.color).toBe("rgba(0, 0, 0, 0)");
|
||||
await page.evaluate(() => window.scrollTo(0, 900));
|
||||
await page.waitForTimeout(100);
|
||||
const stageAfterScroll = await wallpaperStage.boundingBox();
|
||||
expect(stageBeforeScroll?.height).toBeLessThanOrEqual(
|
||||
testInfo.project.use.viewport!.height,
|
||||
);
|
||||
expect(stageAfterScroll?.y).toBeLessThanOrEqual(stageBeforeScroll!.y);
|
||||
expect(stageAfterScroll?.y).toBeGreaterThanOrEqual(71);
|
||||
|
||||
await request.delete("/api/wallpaper");
|
||||
await request.patch("/api/preferences", {
|
||||
data: {
|
||||
backgroundStyle: "aurora",
|
||||
wallpaperFit: "contain",
|
||||
wallpaperPositionX: 50,
|
||||
wallpaperPositionY: 50,
|
||||
wallpaperZoom: 100,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("dashboard en instellingen blijven bruikbaar zonder horizontale overflow", async ({
|
||||
page,
|
||||
}, testInfo) => {
|
||||
await page.goto("/");
|
||||
const compact = ["mobile-chromium", "tablet-chromium"].includes(
|
||||
testInfo.project.name,
|
||||
);
|
||||
await expect(
|
||||
page.getByRole("navigation", {
|
||||
name: compact ? "Mobiele navigatie" : "Dashboardnavigatie",
|
||||
}),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByLabel(
|
||||
testInfo.project.name === "mobile-chromium"
|
||||
? "Zoek apps en favorieten mobiel"
|
||||
: "Zoek apps, favorieten of Google",
|
||||
),
|
||||
).toBeVisible();
|
||||
if (testInfo.project.name === "ultrawide-chromium") {
|
||||
const widgetDock = page.locator(".dashboard-insights-panel");
|
||||
await expect(widgetDock).toHaveAttribute("open", "");
|
||||
const dockBox = await widgetDock.boundingBox();
|
||||
const groupsBox = await page.locator(".dashboard-groups").boundingBox();
|
||||
expect(dockBox).not.toBeNull();
|
||||
expect(groupsBox).not.toBeNull();
|
||||
expect(dockBox!.x).toBeGreaterThan(groupsBox!.x);
|
||||
}
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "App Beheer", exact: true }),
|
||||
).toBeVisible();
|
||||
const overflow = await page.evaluate(
|
||||
() => document.documentElement.scrollWidth - window.innerWidth,
|
||||
);
|
||||
expect(overflow).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
test("legt de finale Stitch-compositie op de canonieke viewports vast", async ({
|
||||
page,
|
||||
request,
|
||||
}, testInfo) => {
|
||||
const dashboardResponse = await request.get("/api/dashboard");
|
||||
const dashboard = (await dashboardResponse.json()) as {
|
||||
apps: Array<{ id: string; technicalName: string }>;
|
||||
categories: Array<{ id: string; name: string }>;
|
||||
favorites: Array<{ id: string }>;
|
||||
};
|
||||
let smartHome = dashboard.categories.find(
|
||||
(category) => category.name === "Smart Home",
|
||||
);
|
||||
if (!smartHome) {
|
||||
const response = await request.post("/api/categories", {
|
||||
data: { name: "Smart Home", icon: "House", sortOrder: 20 },
|
||||
});
|
||||
smartHome = (await response.json()) as { id: string; name: string };
|
||||
}
|
||||
const media = dashboard.categories.find(
|
||||
(category) => category.name === "Media",
|
||||
);
|
||||
const tools = dashboard.categories.find(
|
||||
(category) => category.name === "Tools",
|
||||
);
|
||||
for (const app of dashboard.apps) {
|
||||
const isHome = /home/i.test(app.technicalName);
|
||||
const isMedia = /plex|immich/i.test(app.technicalName);
|
||||
await request.patch(`/api/apps/${app.id}`, {
|
||||
data: {
|
||||
visible: !/paperless/i.test(app.technicalName),
|
||||
categoryId: isHome
|
||||
? smartHome.id
|
||||
: isMedia
|
||||
? (media?.id ?? null)
|
||||
: (tools?.id ?? null),
|
||||
},
|
||||
});
|
||||
}
|
||||
if (dashboard.favorites.length === 0) {
|
||||
for (const [index, favorite] of [
|
||||
["Google", "https://google.com"],
|
||||
["YouTube", "https://youtube.com"],
|
||||
["GitHub", "https://github.com"],
|
||||
].entries()) {
|
||||
await request.post("/api/favorites", {
|
||||
data: {
|
||||
name: favorite[0],
|
||||
url: favorite[1],
|
||||
icon: null,
|
||||
categoryId: null,
|
||||
sortOrder: index,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
await request.patch("/api/preferences", { data: { theme: "dark" } });
|
||||
await page.goto("/");
|
||||
await expect(page.getByRole("main")).toBeVisible();
|
||||
const inferredAppIcons = page.locator(".app-tile .app-brand-icon");
|
||||
expect(await inferredAppIcons.count()).toBeGreaterThan(0);
|
||||
await expect(page.locator(".app-monogram")).toHaveCount(0);
|
||||
|
||||
const screenshotRoot = "docs/design/dockdeck-canon-v1/implementation";
|
||||
if (testInfo.project.name === "desktop-chromium") {
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/dashboard-dark-desktop-1440x900.png`,
|
||||
});
|
||||
await page.keyboard.press("Control+K");
|
||||
await page.getByLabel("Zoek apps, favorieten of Google").fill("Plex");
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/quick-launch-dark-desktop-1440x900.png`,
|
||||
});
|
||||
await page.keyboard.press("Escape");
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/settings-apps-dark-desktop-1440x900.png`,
|
||||
});
|
||||
await page
|
||||
.getByRole("button", { name: /Bewerken/ })
|
||||
.first()
|
||||
.click();
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/app-drawer-dark-desktop-1440x900.png`,
|
||||
});
|
||||
await page
|
||||
.getByRole("dialog")
|
||||
.getByRole("button", { name: "Sluiten", exact: true })
|
||||
.click();
|
||||
await request.patch("/api/preferences", { data: { theme: "light" } });
|
||||
await page.goto("/");
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/dashboard-light-desktop-1440x900.png`,
|
||||
});
|
||||
await page.keyboard.press("Control+K");
|
||||
await page.getByLabel("Zoek apps, favorieten of Google").fill("Plex");
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/quick-launch-light-desktop-1440x900.png`,
|
||||
});
|
||||
await page.keyboard.press("Escape");
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/settings-apps-light-desktop-1440x900.png`,
|
||||
});
|
||||
} else if (testInfo.project.name === "mobile-chromium") {
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/dashboard-dark-mobile-390x844.png`,
|
||||
});
|
||||
await openSettings(page, testInfo.project.name);
|
||||
await page
|
||||
.getByRole("button", { name: /Bewerken/ })
|
||||
.first()
|
||||
.click();
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/app-drawer-mobile-390x844.png`,
|
||||
});
|
||||
} else if (testInfo.project.name === "tablet-chromium") {
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/dashboard-dark-tablet-768x1024.png`,
|
||||
});
|
||||
} else {
|
||||
await page.screenshot({
|
||||
path: `${screenshotRoot}/dashboard-dark-ultrawide-3440x1440.png`,
|
||||
});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user