chore: ran linting

This commit is contained in:
Anish Sarkar 2026-05-09 05:16:20 +05:30
parent 2f540ee065
commit dbf575fbd0
23 changed files with 89 additions and 96 deletions

View file

@ -239,7 +239,9 @@ class _AuthConfigs(_StrictFakeMixin):
# SDK lets you have multiple, but one is enough for E2E. # SDK lets you have multiple, but one is enough for E2E.
return _AuthConfigsListResult( return _AuthConfigsListResult(
items=[ items=[
_AuthConfig(config_id="auth-config-googledrive", toolkit_slug="googledrive"), _AuthConfig(
config_id="auth-config-googledrive", toolkit_slug="googledrive"
),
_AuthConfig(config_id="auth-config-gmail", toolkit_slug="gmail"), _AuthConfig(config_id="auth-config-gmail", toolkit_slug="gmail"),
_AuthConfig( _AuthConfig(
config_id="auth-config-googlecalendar", config_id="auth-config-googlecalendar",
@ -289,7 +291,9 @@ class _Tools(_StrictFakeMixin):
if slug == "GOOGLEDRIVE_GET_CHANGES_START_PAGE_TOKEN": if slug == "GOOGLEDRIVE_GET_CHANGES_START_PAGE_TOKEN":
return {"data": {"startPageToken": "fake-start-page-token-1"}} return {"data": {"startPageToken": "fake-start-page-token-1"}}
if slug == "GOOGLEDRIVE_LIST_CHANGES": if slug == "GOOGLEDRIVE_LIST_CHANGES":
return {"data": {"changes": [], "newStartPageToken": "fake-start-page-token-1"}} return {
"data": {"changes": [], "newStartPageToken": "fake-start-page-token-1"}
}
if slug == "GOOGLEDRIVE_GET_ABOUT": if slug == "GOOGLEDRIVE_GET_ABOUT":
# Used by ComposioService.get_connected_account_email for # Used by ComposioService.get_connected_account_email for
# googledrive. Returning a fake email lets the connector get a # googledrive. Returning a fake email lets the connector get a
@ -381,7 +385,9 @@ def _extract_quoted_value(q: str, anchor: str) -> str | None:
return after_first_quote[:second_quote_idx] return after_first_quote[:second_quote_idx]
def _filter_drive_files_for_query(q: str, files: list[dict[str, Any]]) -> list[dict[str, Any]]: def _filter_drive_files_for_query(
q: str, files: list[dict[str, Any]]
) -> list[dict[str, Any]]:
filtered = list(files) filtered = list(files)
if "trashed = false" in q: if "trashed = false" in q:

View file

@ -31,7 +31,9 @@ class _FakeConfluenceHistoryConnector:
include_comments: bool = False, include_comments: bool = False,
) -> tuple[list[dict[str, Any]], None]: ) -> tuple[list[dict[str, Any]], None]:
if not start_date or not end_date: if not start_date or not end_date:
raise ValueError("Confluence indexer fake expected start_date and end_date.") raise ValueError(
"Confluence indexer fake expected start_date and end_date."
)
del include_comments del include_comments
return _FIXTURE["pages"], None return _FIXTURE["pages"], None

View file

@ -75,7 +75,9 @@ class _FakeHttpxAsyncClient(_StrictFakeMixin):
f"Unexpected fake Confluence OAuth code: {data.get('code')!r}" f"Unexpected fake Confluence OAuth code: {data.get('code')!r}"
) )
if not data.get("client_id") or not data.get("client_secret"): if not data.get("client_id") or not data.get("client_secret"):
raise ValueError("Confluence OAuth token exchange missing client creds.") raise ValueError(
"Confluence OAuth token exchange missing client creds."
)
if "/api/v1/auth/confluence/connector/callback" not in str( if "/api/v1/auth/confluence/connector/callback" not in str(
data.get("redirect_uri", "") data.get("redirect_uri", "")
): ):

View file

@ -37,9 +37,7 @@ def fake_embed_texts(texts: list[str]) -> list[np.ndarray]:
if not texts: if not texts:
return [] return []
dim = _embedding_dim() dim = _embedding_dim()
return [ return [np.full(shape=(dim,), fill_value=0.1, dtype=np.float32) for _ in texts]
np.full(shape=(dim,), fill_value=0.1, dtype=np.float32) for _ in texts
]
def install(patches: list[Any]) -> None: def install(patches: list[Any]) -> None:
@ -60,7 +58,10 @@ def install(patches: list[Any]) -> None:
("app.indexing_pipeline.document_embedder.embed_text", fake_embed_text), ("app.indexing_pipeline.document_embedder.embed_text", fake_embed_text),
("app.indexing_pipeline.document_embedder.embed_texts", fake_embed_texts), ("app.indexing_pipeline.document_embedder.embed_texts", fake_embed_texts),
# Pipeline service binding (the actual call site for indexing.index) # Pipeline service binding (the actual call site for indexing.index)
("app.indexing_pipeline.indexing_pipeline_service.embed_texts", fake_embed_texts), (
"app.indexing_pipeline.indexing_pipeline_service.embed_texts",
fake_embed_texts,
),
] ]
for target, replacement in targets: for target, replacement in targets:
try: try:

View file

@ -85,18 +85,15 @@ async def _call_tool(
raise ValueError( raise ValueError(
f"Unexpected Jira getAccessibleAtlassianResources args: {arguments!r}" f"Unexpected Jira getAccessibleAtlassianResources args: {arguments!r}"
) )
text = ( text = f"{site['name']}\ncloud_id: {site['cloud_id']}\nurl: {site['url']}"
f"{site['name']}\n"
f"cloud_id: {site['cloud_id']}\n"
f"url: {site['url']}"
)
return SimpleNamespace(content=[SimpleNamespace(text=text)]) return SimpleNamespace(content=[SimpleNamespace(text=text)])
if tool_name == "searchJiraIssuesUsingJql": if tool_name == "searchJiraIssuesUsingJql":
jql = str(arguments.get("jql", "")) jql = str(arguments.get("jql", ""))
if issue["summary"].lower() not in jql.lower() and issue[ if (
"key" issue["summary"].lower() not in jql.lower()
].lower() not in jql.lower(): and issue["key"].lower() not in jql.lower()
):
raise ValueError(f"Unexpected Jira JQL query: {jql!r}") raise ValueError(f"Unexpected Jira JQL query: {jql!r}")
text = _issue_text(issue) text = _issue_text(issue)
return SimpleNamespace(content=[SimpleNamespace(text=text)]) return SimpleNamespace(content=[SimpleNamespace(text=text)])

View file

@ -92,8 +92,7 @@ async def _fake_discover_oauth_metadata(
raise NotImplementedError(f"Unexpected MCP OAuth discovery url={mcp_url!r}") raise NotImplementedError(f"Unexpected MCP OAuth discovery url={mcp_url!r}")
if origin_override != handler.expected_origin_override: if origin_override != handler.expected_origin_override:
raise ValueError( raise ValueError(
f"Unexpected MCP OAuth origin_override for {mcp_url!r}: " f"Unexpected MCP OAuth origin_override for {mcp_url!r}: {origin_override!r}"
f"{origin_override!r}"
) )
return dict(handler.discovery_metadata) return dict(handler.discovery_metadata)

View file

@ -64,9 +64,11 @@ class _FakeStreamableHttpClient(_StrictFakeMixin):
self.handler = handler self.handler = handler
async def __aenter__(self) -> tuple[_FakeEndpoint, _FakeEndpoint, None]: async def __aenter__(self) -> tuple[_FakeEndpoint, _FakeEndpoint, None]:
return _FakeEndpoint(self.url, self.handler), _FakeEndpoint( return (
self.url, self.handler _FakeEndpoint(self.url, self.handler),
), None _FakeEndpoint(self.url, self.handler),
None,
)
async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None: async def __aexit__(self, exc_type: Any, exc: Any, tb: Any) -> None:
del exc_type, exc, tb del exc_type, exc, tb

View file

@ -63,7 +63,9 @@ class _StrictFakeMixin:
class _FakeFlow(_StrictFakeMixin): class _FakeFlow(_StrictFakeMixin):
_component_name = "Flow" _component_name = "Flow"
def __init__(self, *, redirect_uri: str | None = None, scopes: list[str] | None = None): def __init__(
self, *, redirect_uri: str | None = None, scopes: list[str] | None = None
):
self.redirect_uri = redirect_uri self.redirect_uri = redirect_uri
self.scopes = scopes or [] self.scopes = scopes or []
self.code_verifier: str | None = None self.code_verifier: str | None = None
@ -88,9 +90,7 @@ class _FakeFlow(_StrictFakeMixin):
query = parse_qs(parsed.query) query = parse_qs(parsed.query)
query["code"] = ["fake-native-drive-oauth-code"] query["code"] = ["fake-native-drive-oauth-code"]
query["state"] = [state] query["state"] = [state]
redirect = urlunparse( redirect = urlunparse(parsed._replace(query=urlencode(query, doseq=True)))
parsed._replace(query=urlencode(query, doseq=True))
)
return redirect, state return redirect, state
def fetch_token(self, *, code: str, **_: Any) -> None: def fetch_token(self, *, code: str, **_: Any) -> None:
@ -213,7 +213,9 @@ class _FakeGmailUsers(_StrictFakeMixin):
def getProfile(self, **kwargs: Any) -> _FakeRequest: # noqa: N802 def getProfile(self, **kwargs: Any) -> _FakeRequest: # noqa: N802
user_id = kwargs.get("userId") user_id = kwargs.get("userId")
if user_id != "me": if user_id != "me":
raise NotImplementedError(f"Unexpected fake Gmail profile userId={user_id!r}") raise NotImplementedError(
f"Unexpected fake Gmail profile userId={user_id!r}"
)
return _FakeRequest({"emailAddress": "native-drive-e2e@surfsense.example"}) return _FakeRequest({"emailAddress": "native-drive-e2e@surfsense.example"})
def messages(self) -> _FakeGmailMessages: def messages(self) -> _FakeGmailMessages:
@ -326,7 +328,9 @@ def _extract_quoted_value(q: str, anchor: str) -> str | None:
return after_first_quote[:second_quote_idx] return after_first_quote[:second_quote_idx]
def _filter_drive_files_for_query(q: str, files: list[dict[str, Any]]) -> list[dict[str, Any]]: def _filter_drive_files_for_query(
q: str, files: list[dict[str, Any]]
) -> list[dict[str, Any]]:
filtered = list(files) filtered = list(files)
if "trashed = false" in q: if "trashed = false" in q:
@ -386,14 +390,14 @@ def _calendar_event_in_range(
parsed_max = _parse_rfc3339(time_max) parsed_max = _parse_rfc3339(time_max)
if parsed_min and event_start < parsed_min: if parsed_min and event_start < parsed_min:
return False return False
if parsed_max and event_start > parsed_max: return not (parsed_max and event_start > parsed_max)
return False
return True
def _gmail_detail_to_native_message(detail: dict[str, Any]) -> dict[str, Any]: def _gmail_detail_to_native_message(detail: dict[str, Any]) -> dict[str, Any]:
message_text = detail.get("messageText", "") message_text = detail.get("messageText", "")
encoded_body = base64.urlsafe_b64encode(message_text.encode("utf-8")).decode("ascii") encoded_body = base64.urlsafe_b64encode(message_text.encode("utf-8")).decode(
"ascii"
)
return { return {
"id": detail.get("id"), "id": detail.get("id"),
@ -429,10 +433,12 @@ def install(active_patches: list[Any]) -> None:
("app.agents.new_chat.tools.google_calendar.update_event.build", _fake_build), ("app.agents.new_chat.tools.google_calendar.update_event.build", _fake_build),
("app.agents.new_chat.tools.google_calendar.delete_event.build", _fake_build), ("app.agents.new_chat.tools.google_calendar.delete_event.build", _fake_build),
("googleapiclient.http.MediaIoBaseDownload", _FakeMediaIoBaseDownload), ("googleapiclient.http.MediaIoBaseDownload", _FakeMediaIoBaseDownload),
("app.connectors.google_drive.client._build_thread_http", lambda credentials: None), (
"app.connectors.google_drive.client._build_thread_http",
lambda credentials: None,
),
] ]
for target, replacement in targets: for target, replacement in targets:
p = patch(target, replacement) p = patch(target, replacement)
p.start() p.start()
active_patches.append(p) active_patches.append(p)

View file

@ -84,8 +84,16 @@ class _FakeOneDriveClient(_StrictFakeMixin):
if delta_link: if delta_link:
folder_key = delta_link.rsplit("/", 1)[-1].removesuffix("-delta") folder_key = delta_link.rsplit("/", 1)[-1].removesuffix("-delta")
if folder_key not in _ONEDRIVE_FIXTURE: if folder_key not in _ONEDRIVE_FIXTURE:
return [], None, f"E2E OneDrive fake has no delta for folder={folder_key!r}." return (
return [], f"https://graph.microsoft.com/v1.0/fake-delta/{folder_key}-delta", None [],
None,
f"E2E OneDrive fake has no delta for folder={folder_key!r}.",
)
return (
[],
f"https://graph.microsoft.com/v1.0/fake-delta/{folder_key}-delta",
None,
)
class _FakeAsyncClient(_StrictFakeMixin): class _FakeAsyncClient(_StrictFakeMixin):
@ -170,7 +178,10 @@ def install(active_patches: list[Any]) -> None:
targets = [ targets = [
("app.routes.onedrive_add_connector_route.httpx", _FakeHttpxModule()), ("app.routes.onedrive_add_connector_route.httpx", _FakeHttpxModule()),
("app.routes.onedrive_add_connector_route.OneDriveClient", _FakeOneDriveClient), ("app.routes.onedrive_add_connector_route.OneDriveClient", _FakeOneDriveClient),
("app.tasks.connector_indexers.onedrive_indexer.OneDriveClient", _FakeOneDriveClient), (
"app.tasks.connector_indexers.onedrive_indexer.OneDriveClient",
_FakeOneDriveClient,
),
("app.connectors.onedrive.client.httpx", _FakeHttpxModule()), ("app.connectors.onedrive.client.httpx", _FakeHttpxModule()),
] ]
for target, replacement in targets: for target, replacement in targets:

View file

@ -131,7 +131,7 @@ async def _fake_exchange_code_for_tokens(
timeout: float = 30.0, timeout: float = 30.0,
) -> dict[str, Any]: ) -> dict[str, Any]:
if token_endpoint != _TOKEN_URL: if token_endpoint != _TOKEN_URL:
return await mcp_oauth_runtime._fake_exchange_code_for_tokens( # noqa: SLF001 return await mcp_oauth_runtime._fake_exchange_code_for_tokens(
token_endpoint, token_endpoint,
code, code,
redirect_uri, redirect_uri,

View file

@ -77,9 +77,7 @@ logging.basicConfig(
datefmt="%Y-%m-%d %H:%M:%S", datefmt="%Y-%m-%d %H:%M:%S",
) )
logger = logging.getLogger("surfsense.e2e.celery") logger = logging.getLogger("surfsense.e2e.celery")
logger.warning( logger.warning("*** SURFSENSE E2E CELERY WORKER — fake Composio + LLM + embeddings ***")
"*** SURFSENSE E2E CELERY WORKER — fake Composio + LLM + embeddings ***"
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View file

@ -47,7 +47,9 @@ def test_extract_text_content_ignores_thinking_blocks_and_keeps_markdown_text()
assert extract_text_content(content).strip() == markdown.strip() assert extract_text_content(content).strip() == markdown.strip()
def test_extract_text_content_returns_empty_when_only_thinking_blocks_are_present() -> None: def test_extract_text_content_returns_empty_when_only_thinking_blocks_are_present() -> (
None
):
content = [ content = [
{"type": "thinking", "thinking": "No durable fact."}, {"type": "thinking", "thinking": "No durable fact."},
{"type": "thinking", "thinking": "Return no update."}, {"type": "thinking", "thinking": "Return no update."},

View file

@ -141,9 +141,7 @@ class TestNormalizeDecision:
assert _normalize_permission_decision(decision) == {"decision_type": "reject"} assert _normalize_permission_decision(decision) == {"decision_type": "reject"}
def test_lc_envelope_reject_with_message_carries_feedback(self) -> None: def test_lc_envelope_reject_with_message_carries_feedback(self) -> None:
decision = { decision = {"decisions": [{"type": "reject", "message": "wrong recipient"}]}
"decisions": [{"type": "reject", "message": "wrong recipient"}]
}
out = _normalize_permission_decision(decision) out = _normalize_permission_decision(decision)
assert out == {"decision_type": "reject", "feedback": "wrong recipient"} assert out == {"decision_type": "reject", "feedback": "wrong recipient"}

View file

@ -119,8 +119,7 @@ export default function PurchaseSuccessPage() {
"Stripe reported the checkout as failed or expired. Your card was not charged."} "Stripe reported the checkout as failed or expired. Your card was not charged."}
{state.kind === "error" && {state.kind === "error" &&
"Don't worry — if your card was charged, your purchase will still apply within a minute or two."} "Don't worry — if your card was charged, your purchase will still apply within a minute or two."}
{state.kind === "no_session" && {state.kind === "no_session" && "Your purchase is being applied to your account."}
"Your purchase is being applied to your account."}
</CardDescription> </CardDescription>
</CardHeader> </CardHeader>
<CardContent className="space-y-3 text-center"> <CardContent className="space-y-3 text-center">
@ -134,7 +133,8 @@ export default function PurchaseSuccessPage() {
)} )}
{state.kind === "completed" && state.data.purchase_type === "premium_tokens" && ( {state.kind === "completed" && state.data.purchase_type === "premium_tokens" && (
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
New premium credit balance: {formatCredit(state.data.premium_credit_micros_limit ?? 0)} New premium credit balance:{" "}
{formatCredit(state.data.premium_credit_micros_limit ?? 0)}
</p> </p>
)} )}
{state.kind === "error" && ( {state.kind === "error" && (

View file

@ -34,7 +34,9 @@ test.describe("ClickUp connector journey", () => {
client_id: "fake-clickup-mcp-client-id", client_id: "fake-clickup-mcp-client-id",
token_endpoint: "https://mcp.clickup.com/token", token_endpoint: "https://mcp.clickup.com/token",
}); });
expect((clickupConnector.config.mcp_oauth as Record<string, unknown>).access_token).toBeTruthy(); expect(
(clickupConnector.config.mcp_oauth as Record<string, unknown>).access_token
).toBeTruthy();
expect(clickupConnector.config.access_token).toBeUndefined(); expect(clickupConnector.config.access_token).toBeUndefined();
expect(clickupConnector.config.refresh_token).toBeUndefined(); expect(clickupConnector.config.refresh_token).toBeUndefined();

View file

@ -1,8 +1,4 @@
import { import { type ConnectorRow, deleteConnector, runComposioOAuth } from "../../helpers/api/connectors";
type ConnectorRow,
deleteConnector,
runComposioOAuth,
} from "../../helpers/api/connectors";
import { searchSpaceFixtures } from "../search-space.fixture"; import { searchSpaceFixtures } from "../search-space.fixture";
export type ComposioDriveFixtures = { export type ComposioDriveFixtures = {
@ -16,12 +12,7 @@ export type ComposioDriveFixtures = {
export const composioDriveFixtures = searchSpaceFixtures.extend<ComposioDriveFixtures>({ export const composioDriveFixtures = searchSpaceFixtures.extend<ComposioDriveFixtures>({
composioDriveConnector: async ({ request, apiToken, searchSpace }, use) => { composioDriveConnector: async ({ request, apiToken, searchSpace }, use) => {
const { connector } = await runComposioOAuth( const { connector } = await runComposioOAuth(request, apiToken, searchSpace.id, "googledrive");
request,
apiToken,
searchSpace.id,
"googledrive"
);
if (!connector) { if (!connector) {
throw new Error( throw new Error(
"composioDriveConnector fixture: OAuth completed but no connector was created. " + "composioDriveConnector fixture: OAuth completed but no connector was created. " +

View file

@ -1,8 +1,4 @@
import { import { type ConnectorRow, deleteConnector, runComposioOAuth } from "../../helpers/api/connectors";
type ConnectorRow,
deleteConnector,
runComposioOAuth,
} from "../../helpers/api/connectors";
import { searchSpaceFixtures } from "../search-space.fixture"; import { searchSpaceFixtures } from "../search-space.fixture";
export type ComposioGmailFixtures = { export type ComposioGmailFixtures = {
@ -16,12 +12,7 @@ export type ComposioGmailFixtures = {
export const composioGmailFixtures = searchSpaceFixtures.extend<ComposioGmailFixtures>({ export const composioGmailFixtures = searchSpaceFixtures.extend<ComposioGmailFixtures>({
composioGmailConnector: async ({ request, apiToken, searchSpace }, use) => { composioGmailConnector: async ({ request, apiToken, searchSpace }, use) => {
const { connector } = await runComposioOAuth( const { connector } = await runComposioOAuth(request, apiToken, searchSpace.id, "gmail");
request,
apiToken,
searchSpace.id,
"gmail"
);
if (!connector) { if (!connector) {
throw new Error( throw new Error(
"composioGmailConnector fixture: OAuth completed but no connector was created. " + "composioGmailConnector fixture: OAuth completed but no connector was created. " +

View file

@ -16,11 +16,7 @@ export type NativeCalendarFixtures = {
export const nativeCalendarFixtures = searchSpaceFixtures.extend<NativeCalendarFixtures>({ export const nativeCalendarFixtures = searchSpaceFixtures.extend<NativeCalendarFixtures>({
nativeCalendarConnector: async ({ request, apiToken, searchSpace }, use) => { nativeCalendarConnector: async ({ request, apiToken, searchSpace }, use) => {
const { connector } = await runNativeGoogleCalendarOAuth( const { connector } = await runNativeGoogleCalendarOAuth(request, apiToken, searchSpace.id);
request,
apiToken,
searchSpace.id
);
if (!connector) { if (!connector) {
throw new Error( throw new Error(
"nativeCalendarConnector fixture: OAuth completed but no GOOGLE_CALENDAR_CONNECTOR was created. " + "nativeCalendarConnector fixture: OAuth completed but no GOOGLE_CALENDAR_CONNECTOR was created. " +

View file

@ -45,10 +45,10 @@
*/ */
export { expect } from "@playwright/test"; export { expect } from "@playwright/test";
export { chatThreadFixtures } from "./chat-thread.fixture"; export { chatThreadFixtures } from "./chat-thread.fixture";
export { clickupFixtures } from "./connectors/clickup.fixture";
export { composioCalendarFixtures } from "./connectors/composio-calendar.fixture"; export { composioCalendarFixtures } from "./connectors/composio-calendar.fixture";
export { composioDriveFixtures } from "./connectors/composio-drive.fixture"; export { composioDriveFixtures } from "./connectors/composio-drive.fixture";
export { composioGmailFixtures } from "./connectors/composio-gmail.fixture"; export { composioGmailFixtures } from "./connectors/composio-gmail.fixture";
export { clickupFixtures } from "./connectors/clickup.fixture";
export { confluenceFixtures } from "./connectors/confluence.fixture"; export { confluenceFixtures } from "./connectors/confluence.fixture";
export { jiraFixtures } from "./connectors/jira.fixture"; export { jiraFixtures } from "./connectors/jira.fixture";
export { linearFixtures } from "./connectors/linear.fixture"; export { linearFixtures } from "./connectors/linear.fixture";
@ -62,10 +62,10 @@ export { slackFixtures } from "./connectors/slack.fixture";
export { searchSpaceFixtures } from "./search-space.fixture"; export { searchSpaceFixtures } from "./search-space.fixture";
import { type ChatThreadFixtures, chatThreadFixtures } from "./chat-thread.fixture"; import { type ChatThreadFixtures, chatThreadFixtures } from "./chat-thread.fixture";
import { clickupFixtures } from "./connectors/clickup.fixture";
import { composioCalendarFixtures } from "./connectors/composio-calendar.fixture"; import { composioCalendarFixtures } from "./connectors/composio-calendar.fixture";
import { composioDriveFixtures } from "./connectors/composio-drive.fixture"; import { composioDriveFixtures } from "./connectors/composio-drive.fixture";
import { composioGmailFixtures } from "./connectors/composio-gmail.fixture"; import { composioGmailFixtures } from "./connectors/composio-gmail.fixture";
import { clickupFixtures } from "./connectors/clickup.fixture";
import { confluenceFixtures } from "./connectors/confluence.fixture"; import { confluenceFixtures } from "./connectors/confluence.fixture";
import { jiraFixtures } from "./connectors/jira.fixture"; import { jiraFixtures } from "./connectors/jira.fixture";
import { linearFixtures } from "./connectors/linear.fixture"; import { linearFixtures } from "./connectors/linear.fixture";

View file

@ -1,11 +1,11 @@
import { test as base } from "@playwright/test"; import { test as base } from "@playwright/test";
import { loginAsTestUser } from "../helpers/api/auth"; import { loginAsTestUser } from "../helpers/api/auth";
import { uniqueSearchSpaceName } from "../helpers/canary";
import { import {
createSearchSpace, createSearchSpace,
deleteSearchSpace, deleteSearchSpace,
type SearchSpaceRow, type SearchSpaceRow,
} from "../helpers/api/search-spaces"; } from "../helpers/api/search-spaces";
import { uniqueSearchSpaceName } from "../helpers/canary";
export type SearchSpaceFixtures = { export type SearchSpaceFixtures = {
/** /**

View file

@ -9,8 +9,7 @@ import type { APIRequestContext } from "@playwright/test";
* is set up separately by tests/auth.setup.ts. * is set up separately by tests/auth.setup.ts.
*/ */
export const BACKEND_URL = export const BACKEND_URL = process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "http://localhost:8000";
process.env.NEXT_PUBLIC_FASTAPI_BACKEND_URL || "http://localhost:8000";
const TEST_USER_EMAIL = process.env.PLAYWRIGHT_TEST_EMAIL || "test@surfsense.net"; const TEST_USER_EMAIL = process.env.PLAYWRIGHT_TEST_EMAIL || "test@surfsense.net";
const TEST_USER_PASSWORD = process.env.PLAYWRIGHT_TEST_PASSWORD || "TestPassword123!"; const TEST_USER_PASSWORD = process.env.PLAYWRIGHT_TEST_PASSWORD || "TestPassword123!";
@ -43,10 +42,7 @@ export async function loginAsTestUser(request: APIRequestContext): Promise<strin
* X-E2E-Scenario header that the test-only ScenarioMiddleware in * X-E2E-Scenario header that the test-only ScenarioMiddleware in
* surfsense_backend/tests/e2e/run_backend.py reads to flip fake behavior. * surfsense_backend/tests/e2e/run_backend.py reads to flip fake behavior.
*/ */
export function authHeaders( export function authHeaders(token: string, extra?: Record<string, string>): Record<string, string> {
token: string,
extra?: Record<string, string>
): Record<string, string> {
return { return {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
"Content-Type": "application/json", "Content-Type": "application/json",

View file

@ -25,17 +25,14 @@ export async function listDocuments(
{ headers: authHeaders(token) } { headers: authHeaders(token) }
); );
if (!response.ok()) { if (!response.ok()) {
throw new Error( throw new Error(`listDocuments failed (${response.status()}): ${await response.text()}`);
`listDocuments failed (${response.status()}): ${await response.text()}`
);
} }
const body = (await response.json()) as Paginated<DocumentRow> | DocumentRow[]; const body = (await response.json()) as Paginated<DocumentRow> | DocumentRow[];
return Array.isArray(body) ? body : (body.items ?? []); return Array.isArray(body) ? body : (body.items ?? []);
} }
export function isDocumentReady(doc: DocumentRow): boolean { export function isDocumentReady(doc: DocumentRow): boolean {
const state = const state = typeof doc.status === "string" ? doc.status : doc.status?.state;
typeof doc.status === "string" ? doc.status : doc.status?.state;
return state === "ready" || state === "READY"; return state === "ready" || state === "READY";
} }
@ -61,9 +58,7 @@ export async function getEditorContent(
{ headers: authHeaders(token) } { headers: authHeaders(token) }
); );
if (!response.ok()) { if (!response.ok()) {
throw new Error( throw new Error(`getEditorContent failed (${response.status()}): ${await response.text()}`);
`getEditorContent failed (${response.status()}): ${await response.text()}`
);
} }
return (await response.json()) as EditorContent; return (await response.json()) as EditorContent;
} }

View file

@ -18,9 +18,7 @@ export async function createSearchSpace(
data: { name, description }, data: { name, description },
}); });
if (!response.ok()) { if (!response.ok()) {
throw new Error( throw new Error(`createSearchSpace failed (${response.status()}): ${await response.text()}`);
`createSearchSpace failed (${response.status()}): ${await response.text()}`
);
} }
return (await response.json()) as SearchSpaceRow; return (await response.json()) as SearchSpaceRow;
} }