Skip to content

Commit baa758b

Browse files
committed
Add e2e test for uploading a file to a workspace
1 parent 9a295ee commit baa758b

5 files changed

Lines changed: 85 additions & 9 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ sbt 'int:testOnly controllers.api.WorkspacesITest'
162162

163163
### End-to-end tests
164164

165-
Run `./scripts/test-e2e.sh` to test genesis account creation against disposable
166-
databases and a separate Giant instance. See [the E2E setup guide](frontend/e2e/README.md)
165+
Run `./scripts/test-e2e.sh` to test genesis account creation and workspace PDF
166+
uploads against disposable databases and a separate Giant instance. See [the E2E setup guide](frontend/e2e/README.md)
167167
for prerequisites, ports and debugging. The GitHub Actions E2E workflow runs the
168168
same script.
169169

backend/conf/e2e.conf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ s3.endpoint = "http://127.0.0.1:13900"
1414
pekko.remote.artery.canonical.port = 11234
1515
pekko.cluster.seed-nodes = ["pekko://pfi@localhost:11234"]
1616

17-
# Genesis needs storage and authentication, but no background extraction services.
18-
worker.enabled = false
17+
# Process uploads with the real local extractors.
18+
worker.enabled = true
19+
worker.interval = 1 second
1920
worker.useExternalExtractors = false
2021
ingestion.scratchPath = ${E2E_RUNTIME_DIR}"/ingestion"
2122
preview.workspace = ${E2E_RUNTIME_DIR}"/preview"

frontend/e2e/README.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
From the repository root, with Docker Compose, Java, sbt and Node installed:
44

5+
Install the PDF extraction tools first. On Ubuntu/Debian:
6+
7+
```sh
8+
sudo apt-get update
9+
sudo apt-get install -y ocrmypdf ghostscript qpdf poppler-utils tesseract-ocr-eng
10+
```
11+
12+
On macOS, the project's `Brewfile` includes the extraction tools.
13+
514
```sh
615
npm ci --prefix frontend
716
cd frontend
@@ -17,8 +26,12 @@ Elasticsearch and Garage containers, creates storage buckets, runs PostgreSQL
1726
migrations, starts the backend and Vite, then runs Playwright. GitHub Actions runs
1827
the same script. No AWS credentials or pre-existing Giant account are needed.
1928

20-
The single test creates the genesis user through the UI, skips optional 2FA,
21-
then logs in from a fresh browser context and checks administrator access.
29+
The genesis project creates the initial user through the UI, skips optional 2FA,
30+
then logs in from a fresh browser context and checks administrator access. The
31+
Chromium project depends on genesis and tests creating a workspace, uploading
32+
`toast_sandwich_en_wiki.pdf` through its upload dialog, and waiting up to three
33+
minutes for the file's processing icon to become a document icon. An error icon
34+
fails the test. The fixture uses the real document text and OCR extractors.
2235
Retries are disabled because genesis requires an empty user store. Rerun the
2336
script to get a fresh instance; running Playwright alone does not reset anything.
2437

@@ -32,6 +45,12 @@ Logs are saved in `frontend/e2e-artifacts/`, the HTML report in
3245
`frontend/playwright-report/`, and failure traces/screenshots in
3346
`frontend/test-results/`. CI uploads these even when a run fails.
3447

35-
Background workers are disabled for this genesis-only suite. Before adding
36-
upload/extraction coverage, enable the required workers in `backend/conf/e2e.conf`
37-
and install the extraction tools exercised by the fixtures in CI.
48+
To run just the upload scenario (including its genesis dependency):
49+
50+
```sh
51+
./scripts/test-e2e.sh workspace-upload.spec.ts
52+
```
53+
54+
Local extraction workers are enabled in `backend/conf/e2e.conf`; external
55+
extractors are disabled. The PDF fixture comes from Wikipedia's English
56+
"Toast sandwich" article: https://en.wikipedia.org/wiki/Toast_sandwich.
516 KB
Binary file not shown.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { expect, test } from "@playwright/test";
2+
import path from "node:path";
3+
4+
test("uploads a PDF to a new workspace and completes extraction", async ({
5+
page,
6+
}) => {
7+
test.setTimeout(240_000);
8+
const workspaceName = `Toast sandwich ${Date.now()}`;
9+
const filename = "toast_sandwich_en_wiki.pdf";
10+
11+
await page.goto("/workspaces");
12+
await page.getByPlaceholder("Username", { exact: true }).fill("genesis-e2e");
13+
await page
14+
.getByPlaceholder("Password", { exact: true })
15+
.fill("Genesis-e2e-password");
16+
await page.getByRole("button", { name: "Login", exact: true }).click();
17+
18+
await page
19+
.getByRole("button", { name: "New Workspace", exact: true })
20+
.click();
21+
await page.getByPlaceholder("Name", { exact: true }).fill(workspaceName);
22+
await page.getByRole("button", { name: "Create", exact: true }).click();
23+
await expect(
24+
page.getByRole("heading", { name: workspaceName }),
25+
).toBeVisible();
26+
27+
await page
28+
.getByRole("button", { name: "Upload to workspace", exact: true })
29+
.click();
30+
const fileChooser = page.waitForEvent("filechooser");
31+
await page.getByRole("button", { name: "Add Files", exact: true }).click();
32+
await (await fileChooser).setFiles(path.join(__dirname, filename));
33+
await page.getByRole("button", { name: "Upload", exact: true }).click();
34+
// Use the upload form's completion button, not the modal's corner dismiss.
35+
await page
36+
.locator("form")
37+
.getByRole("button", { name: "Close", exact: true })
38+
.click();
39+
40+
const fileRow = page.getByRole("row").filter({
41+
has: page.getByText(filename, { exact: true }),
42+
});
43+
await expect(fileRow).toBeVisible();
44+
45+
// A vanished spinner alone is insufficient: wait for either terminal icon,
46+
// then require the document icon so an extraction error cannot count as success.
47+
// The selectors correspond to Workspaces.renderIcon's processed/failed cases.
48+
await expect(
49+
fileRow.locator(
50+
"svg.file-browser__icon, i.exclamation.triangle.file-browser__icon",
51+
),
52+
).toBeVisible({ timeout: 180_000 });
53+
await expect(fileRow.locator("svg.file-browser__icon")).toBeVisible();
54+
await expect(fileRow.locator(".loader.file-browser__icon")).toHaveCount(0);
55+
await expect(fileRow.getByText("processed", { exact: true })).toBeVisible();
56+
});

0 commit comments

Comments
 (0)