From bea5c3f5eec352f28ed64c0494709ec3f09f0ae1 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Wed, 22 Apr 2026 20:15:05 +0200 Subject: [PATCH] test: include Nextcloud CSRF token in chunk-context integration test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Astrolabe's ApiController endpoints (search, chunk-context) require a CSRF `requesttoken` header — axios picks it up from OC.requestToken automatically in the SPA, but page.request.get() does not. The first CI run failed on the search step with 412 CSRF check failed before reaching the chunk-context assertion that was supposed to surface the handler bug. Load the Astrolabe page, read OC.requestToken, and pass it on both calls. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../test_astrolabe_chunk_context.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_astrolabe_chunk_context.py b/tests/integration/test_astrolabe_chunk_context.py index ddcff90a..42523c6f 100644 --- a/tests/integration/test_astrolabe_chunk_context.py +++ b/tests/integration/test_astrolabe_chunk_context.py @@ -116,10 +116,24 @@ async def test_chunk_context_endpoint_uses_app_password( # Use the browser's session to drive Astrolabe end-to-end, the way a # real user would: this exercises astrolabe's OAuth token retrieval - # and the MCP server's handler under a real bearer. + # and the MCP server's handler under a real bearer. Nextcloud's + # controllers require a CSRF token (`requesttoken` header) that the + # rendered SPA picks up from `OC.requestToken`; direct page.request + # calls don't get it for free, so we load an Astrolabe page and + # forward the token on each subsequent API call. + await page.goto( + "http://localhost:8080/apps/astrolabe/", wait_until="networkidle" + ) + request_token = await page.evaluate("window.OC && OC.requestToken") + assert request_token, ( + "Could not read OC.requestToken from Astrolabe page — is the user logged in?" + ) + csrf_headers = {"requesttoken": request_token} + search_resp = await page.request.get( f"http://localhost:8080/apps/astrolabe/api/search" - f"?query={unique_term}&algorithm=hybrid&limit=5&include_pca=false" + f"?query={unique_term}&algorithm=hybrid&limit=5&include_pca=false", + headers=csrf_headers, ) assert search_resp.ok, ( f"Astrolabe search failed: {search_resp.status} {await search_resp.text()}" @@ -153,6 +167,7 @@ async def test_chunk_context_endpoint_uses_app_password( "start": str(start), "end": str(end), }, + headers=csrf_headers, ) assert chunk_resp.status == 200, ( f"chunk-context returned {chunk_resp.status}, body: "