Files
homarr/e2e/assistant-docs-screenshots.spec.ts
T
Thomas 45d8bc9443 feat: add the community-funded Homarr assistant provider (#6563)
* Add Homarr provider proxy foundation

* Complete Homarr provider integration

* Harden Homarr provider integration

* Address Homarr provider review feedback

* Address CodeRabbit provider feedback

* Localize provider errors

* Handle provider activity load failures

* docs: improve workshop and homepage

* Harden Homarr provider limits

* fix: harden the Homarr provider

* fix: address provider review feedback

* fix: clarify provider request accounting

* feat: complete the Homarr provider endpoint

* fix: terminate invalid provider streams
2026-08-14 11:32:11 +02:00

100 lines
4.1 KiB
TypeScript

import { mkdir } from "node:fs/promises";
import path from "node:path";
import { chromium, expect } from "@playwright/test";
import type { Browser } from "@playwright/test";
import type { StartedTestContainer } from "testcontainers";
import { describe, test } from "vitest";
import * as sqliteSchema from "../packages/db/schema/sqlite";
import { createHomarrContainer } from "./shared/create-homarr-container";
import { createSqliteDbFileAsync } from "./shared/e2e-db";
import { seedAdminUserAsync } from "./shared/seed-admin-user";
const adminCredentials = {
username: "admin",
password: "Comp(exP4sswOrd",
};
// This is an opt-in documentation asset generator, not part of the normal E2E gate.
// Run it explicitly with UPDATE_DOCS_SCREENSHOTS=true when the documented UI changes.
describe.skipIf(process.env.UPDATE_DOCS_SCREENSHOTS !== "true")("Assistant documentation screenshots", () => {
test("captures the management page and conversation panel", async () => {
const { db, localMountPath } = await createSqliteDbFileAsync();
await seedAdminUserAsync(db, adminCredentials);
await db.insert(sqliteSchema.assistantConfigurations).values({
id: "default",
enabled: true,
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
modelDiscoveryPath: null,
encryptedApiKey: "encrypted.key",
modelId: "deepseek/deepseek-v4-flash",
});
const outputDirectory = path.resolve("apps/docs/static/img/assistant");
await mkdir(outputDirectory, { recursive: true });
let homarrContainer: StartedTestContainer | undefined;
let browser: Browser | undefined;
try {
homarrContainer = await createHomarrContainer({
environment: { AUTH_PROVIDERS: "credentials" },
mounts: { "/appdata": localMountPath },
}).start();
const baseUrl = `http://${homarrContainer.getHost()}:${homarrContainer.getMappedPort(7575)}`;
browser = await chromium.launch();
const context = await browser.newContext({
colorScheme: "dark",
deviceScaleFactor: 1,
viewport: { width: 1440, height: 1000 },
});
const page = await context.newPage();
await page.goto(`${baseUrl}/auth/login`);
await page.getByLabel("Username").fill(adminCredentials.username);
await page.locator("#password").fill(adminCredentials.password);
await page.getByRole("button", { name: "Login" }).click();
await expect(page).not.toHaveURL(/\/auth\/login/, { timeout: 30_000 });
await page.goto(`${baseUrl}/manage/assistant`);
await expect(page.getByRole("heading", { name: "Assistant" })).toBeVisible();
await expect(page.getByText("Connection ready")).toBeVisible();
await page
.getByRole("main")
.first()
.screenshot({
animations: "disabled",
path: path.join(outputDirectory, "configuration.png"),
});
await page.goto(baseUrl);
await expect(page.getByRole("main").first()).toBeVisible();
await page.locator("body").click({ position: { x: 12, y: 12 } });
await page.keyboard.press("Shift+A");
const assistantDialog = page.getByRole("dialog", { name: "Homarr Assistant" });
await expect(assistantDialog).toBeVisible();
await assistantDialog.screenshot({
animations: "disabled",
path: path.join(outputDirectory, "conversation.png"),
});
await db.update(sqliteSchema.assistantConfigurations).set({
provider: "homarr",
baseUrl: "https://homarr.dev/api/ai/v1",
modelDiscoveryPath: "/models",
encryptedApiKey: null,
modelId: "homarr/model",
});
await page.goto(`${baseUrl}/manage/assistant`);
await expect(page.getByRole("heading", { name: "Assistant" })).toBeVisible();
await expect(page.getByText("Homarr", { exact: true }).first()).toBeVisible();
await expect(page.getByRole("button", { name: "Refresh models" })).toBeVisible({ timeout: 15_000 });
await expect(page.getByText("Homarr model")).toBeVisible();
} finally {
await Promise.allSettled([browser?.close(), homarrContainer?.stop()]);
}
}, 120_000);
});