mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 15:02:20 +02:00
The decomposition lanes have two safety nets and neither covers the product. The checkpoint benchmark measures the agent runtime; the computed-style snapshot pins the CSS. Nothing checked that Notes, Calendar, Documents, Email, Memory, Cookbook or Settings still worked after a route package moved or a 17,000-line module was split - and the unit suite does not, since a byte-identical file move can break tests that pass on the base branch with CI green throughout. The 28 Playwright specs we do have are all under tests/e2e/photo-editor/ and no workflow runs them. scripts/odysseus-smoke boots this worktree through `odysseus dev` and runs tests/smoke/: one scenario per area, each asserting a user-visible outcome rather than a status code. Models come from a deterministic OpenAI-compatible stub on an ephemeral loopback port; email reuses the existing ODYSSEUS_EMAIL_FIXTURE path rather than inventing a second mechanism. No scenario touches a live endpoint or the network. The report is a per-area table that prints the areas the suite does not cover next to the ones it does, and builds its rows from the registry rather than from what happened to run, so an area cannot go missing by having its module deleted or renamed. Under a plain pytest with nothing booted every scenario skips with the reason, so the full suite stays green.
57 lines
2.4 KiB
Python
57 lines
2.4 KiB
Python
"""Documents (RAG): an uploaded file is chunked, indexed and then listed.
|
|
|
|
This is the one area whose dependency is not satisfiable from a clean
|
|
checkout. `requirements.txt` pins `chromadb-client`, the HTTP client;
|
|
the ChromaDB *server* is a separate install, and without one reachable
|
|
the app returns a deliberate 503 from the upload route rather than
|
|
indexing into nothing. So the scenario skips with that reason printed in
|
|
the table instead of being quietly dropped - a row saying SKIP and why
|
|
is the honest report, and it goes green as soon as a vector service is
|
|
there.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
PERSONAL_PATH = "/api/personal"
|
|
UPLOAD_PATH = "/api/personal/upload"
|
|
|
|
# The route uniquifies the stored name and lists it under the owner's
|
|
# upload dir, so assertions match on the stem rather than the filename.
|
|
STEM = "odysseus-smoke-corpus"
|
|
FILENAME = f"{STEM}.txt"
|
|
CONTENT = (
|
|
"The release smoke suite indexed this file. "
|
|
"It exists so the retrieval path has something deterministic to chunk."
|
|
)
|
|
# The route's own 503 text when no vector store answers.
|
|
UNAVAILABLE_MARKER = "RAG system is not available"
|
|
|
|
|
|
def test_an_uploaded_file_is_indexed_and_listed(client):
|
|
response = client.post(UPLOAD_PATH,
|
|
files={"files": (FILENAME, CONTENT.encode("utf-8"), "text/plain")})
|
|
if response.status_code == 503 and UNAVAILABLE_MARKER in response.text:
|
|
pytest.skip(
|
|
"no vector service reachable, so indexing is unavailable. "
|
|
"requirements.txt pins chromadb-client, not the server; install "
|
|
"chromadb in the venv and re-run to cover this area."
|
|
)
|
|
assert response.status_code == 200, response.text
|
|
body = response.json()
|
|
try:
|
|
assert body.get("indexed_count", 0) > 0, f"nothing was indexed: {body}"
|
|
assert body.get("failed_count", 1) == 0, f"a chunk failed to index: {body}"
|
|
assert FILENAME in (body.get("uploaded") or []), body
|
|
|
|
listed = client.get(PERSONAL_PATH)
|
|
assert listed.status_code == 200, listed.text
|
|
names = [str(f.get("name")) for f in listed.json().get("files") or []]
|
|
assert any(STEM in name for name in names), names
|
|
finally:
|
|
listed = client.get(PERSONAL_PATH).json().get("files") or []
|
|
for entry in listed:
|
|
if STEM in str(entry.get("name")):
|
|
client.request("DELETE", "/api/personal/file",
|
|
params={"filepath": entry.get("path")})
|