mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
* docs: rebrand from image-only to multi-modality across docs and metadata SnapOtter expanded from image-only to 157 tools across 5 modalities (image, video, audio, document/PDF, data). Update all product-level copy, metadata, and i18n that still framed it as an image-only tool. - README, package.json, root llms.txt: multi-modality framing, 157 tools - OpenAPI info + tags, generated /llms.txt tagline (docs.ts) - VitePress docs site: hero, getting-started, architecture, security, deployment, configuration, developer, supported-formats - i18n: 10 product keys across all 21 locales (hero, app description, privacy notes, AI features, progress messages, getting-started) - web/demo/landing meta + privacy copy, COMMUNITY_GUIDE, .env.example Stale tool counts (53/50+/52/70+/35) corrected to 157 throughout. Database/container deployment claims left unchanged (out of scope). * docs: fix stale post-rebrand test assertions and README language list - tests/e2e-docs/homepage.spec.ts: assert the current docs homepage (file toolkit, 157 tools, 5 modalities) instead of the old image-only strings - tests/unit/api/docs-route.test.ts: sync the reproduced llms.txt tagline with docs.ts - README.md: 21 languages with the correct list (add Swedish and Chinese Traditional, drop Czech which is not supported) * docs: correct 2.0 architecture references (Postgres 17 + Redis 8, 3-container stack) The docs and metadata still described the 1.x stack (SQLite, single container, p-queue). Update them to the current 2.0 reality. - README: replace the broken single-container `docker run` quick-start with the real Docker Compose stack (app + Postgres 17 + Redis 8); fix the "no Redis, no Postgres" feature bullet - package.json: description no longer claims a single container - apps/docs: rewrite database.md for Postgres; configuration.md DB_PATH -> DATABASE_URL + REDIS_URL; architecture.md SQLite/p-queue/better-sqlite3 -> Postgres/BullMQ/pg and add media-engine + doc-engine; developer/security/deployment/docker-tags/getting-started/contributing compose examples now include postgres + redis; index.md + api/ai.md AI count 16 -> 19 - SECURITY.md: Drizzle (SQLite) -> (PostgreSQL) - landing: enterprise/FeatureHighlights single-container wording; TrustSignals/ToolGrid 150+ -> 157 (dynamic); Pricing/FAQ 15 -> 19 AI tools * docs(api): document all video, audio, document, and data tool endpoints in OpenAPI The spec covered only image tools; the Scalar UI and the generated /llms.txt and /llms-full.txt inherited that gap. Add the 104 missing tool endpoints so the API docs match the code. - Video: 29 endpoints (most long/async; auto-subtitles is AI) - Audio: 17 (transcribe-audio is AI) - Document/PDF: 36 (ocr-pdf is AI; conversions are long/async) - Data: 10 - Image: 12 newer tools (background-replace, blur-background AI; histogram/lqip-placeholder/sprite-sheet custom responses; barcode-generate uses a JSON body) Each schema is derived from the tool's Zod validator and executionHint (fast -> 200, long -> 202+SSE, AI adds 501 FeatureNotInstalledError, multi-file inputs as arrays), referencing the existing shared schemas. Tool path entries: 64 -> 168. Spec parses as valid YAML with no duplicate paths and only known $refs.
76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
|
|
test.describe("Docs Homepage", () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto("/");
|
|
});
|
|
|
|
test("page loads with correct title", async ({ page }) => {
|
|
await expect(page).toHaveTitle(/SnapOtter/);
|
|
});
|
|
|
|
test("hero renders site name and tagline", async ({ page }) => {
|
|
await expect(page.getByText("SnapOtter").first()).toBeVisible();
|
|
await expect(page.getByText("Self-Hosted File Toolkit")).toBeVisible();
|
|
await expect(
|
|
page.getByText("157 tools for image, video, audio, PDF, and data processing"),
|
|
).toBeVisible();
|
|
});
|
|
|
|
test("hero renders action buttons", async ({ page }) => {
|
|
const getStarted = page.getByRole("link", { name: "Get started", exact: true });
|
|
await expect(getStarted).toBeVisible();
|
|
await expect(getStarted).toHaveAttribute("href", /getting-started/);
|
|
|
|
const apiRef = page.getByRole("link", { name: "API reference", exact: true });
|
|
await expect(apiRef).toBeVisible();
|
|
await expect(apiRef).toHaveAttribute("href", /\/api\/rest/);
|
|
});
|
|
|
|
test("features section renders all 6 feature cards", async ({ page }) => {
|
|
const features = [
|
|
"157 Tools, 5 Modalities",
|
|
"Local AI",
|
|
"Pipelines",
|
|
"REST API",
|
|
"File Library",
|
|
"Teams & Access Control",
|
|
];
|
|
for (const feature of features) {
|
|
await expect(page.getByRole("heading", { name: feature }).first()).toBeVisible();
|
|
}
|
|
});
|
|
|
|
test("Docker quick-start code block is visible", async ({ page }) => {
|
|
await expect(page.getByText("docker run", { exact: false }).first()).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe("Docs Navbar", () => {
|
|
test("renders nav links", async ({ page }) => {
|
|
await page.goto("/");
|
|
await expect(page.getByRole("link", { name: "Guide" }).first()).toBeVisible();
|
|
await expect(page.getByRole("link", { name: "API Reference" }).first()).toBeVisible();
|
|
});
|
|
|
|
test("Guide nav link navigates to getting-started", async ({ page }) => {
|
|
await page.goto("/");
|
|
await page.getByRole("link", { name: "Guide" }).first().click();
|
|
await expect(page).toHaveURL(/getting-started/);
|
|
await expect(page.getByRole("heading", { name: "Getting Started" })).toBeVisible();
|
|
});
|
|
|
|
test("API Reference nav link navigates to REST API", async ({ page }) => {
|
|
await page.goto("/");
|
|
await page.getByRole("link", { name: "API Reference" }).first().click();
|
|
await expect(page).toHaveURL(/\/api\/rest/);
|
|
await expect(page.getByText("REST API Reference")).toBeVisible();
|
|
});
|
|
|
|
test("logo links back to homepage", async ({ page }) => {
|
|
await page.goto("/guide/getting-started");
|
|
await page.locator(".VPNavBarTitle a, .title a").first().click();
|
|
await expect(page).toHaveURL("/");
|
|
});
|
|
});
|