mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-12 09:12:40 +02:00
chore: ran linting
This commit is contained in:
parent
2f540ee065
commit
dbf575fbd0
23 changed files with 89 additions and 96 deletions
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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", "")
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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)])
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 ***"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -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."},
|
||||||
|
|
|
||||||
|
|
@ -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"}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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" && (
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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. " +
|
||||||
|
|
|
||||||
|
|
@ -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. " +
|
||||||
|
|
|
||||||
|
|
@ -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. " +
|
||||||
|
|
|
||||||
4
surfsense_web/tests/fixtures/index.ts
vendored
4
surfsense_web/tests/fixtures/index.ts
vendored
|
|
@ -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";
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue