mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
Every first-party Python caller and test now names the mount the API actually answers on. Mechanical: URL literals only, and only where the /api/ was ours -- a preceding word character means it was a module path like insights/api/ or a third-party host like slack.com/api/, and those are untouched. Left saying /api/, each for a reason rather than for safety: - products/warehouse_sources/.../sources/** is a catalogue of vendor endpoints - services/llm-gateway deploys separately and is under a code freeze, so moving its two calls would break it during the skew - the mcp_store and Slack/Teams redirect_uris are registered with third parties and must byte-match what was registered - the Wizard and Raycast client-metadata paths are OAuth client_ids - /api/surveys and /api/feature_flag/local_evaluation are SDK aliases the ingress routes to the Rust fleets, held by released SDK versions Test URLconfs moved with the requests that call them, and the Datastore user-selection fixtures now carry the leading slash that request.path has.
62 lines
2.6 KiB
TypeScript
62 lines
2.6 KiB
TypeScript
import { expect, test } from '@playwright/test'
|
|
|
|
/**
|
|
* The API surface a signed-in user's session actually depends on.
|
|
*
|
|
* smoke.spec.ts opens scenes and catches anything that breaks while a scene
|
|
* loads. That misses endpoints no scene calls on mount -- `POST /v1/projects/:id/fn/`
|
|
* answered 500 in production for every request because of an unbound name, and
|
|
* no amount of scene-mounting would have found it.
|
|
*
|
|
* Read-only, deliberately. This runs against a real tenant with real data, so a
|
|
* write here would leave objects behind on every release; worse, a write that
|
|
* only passes because it fails is a test that starts creating junk the day the
|
|
* bug is fixed. Endpoints that only break under a write are covered by unit
|
|
* tests, not here.
|
|
*
|
|
* The session arrives as storageState from auth.setup.ts, so `request` is already
|
|
* signed in.
|
|
*/
|
|
|
|
// What this build carries. A 5xx is a fault anywhere; these must also not be 404,
|
|
// because a missing route here means a product surface lost its backend.
|
|
const CARRIED = [
|
|
'/v1/users/@me/',
|
|
'/v1/organizations/@current/',
|
|
'/v1/projects/1/',
|
|
'/v1/projects/1/event_definitions/?limit=5',
|
|
'/v1/projects/1/property_definitions/?limit=5',
|
|
'/v1/projects/1/insights/?limit=5',
|
|
'/v1/projects/1/dashboards/?limit=5',
|
|
'/v1/projects/1/feature_flags/?limit=5',
|
|
'/v1/projects/1/cohorts/?limit=5',
|
|
'/v1/projects/1/actions/?limit=5',
|
|
'/v1/projects/1/annotations/?limit=5',
|
|
'/v1/projects/1/surveys/?limit=5',
|
|
'/v1/projects/1/notebooks/?limit=5',
|
|
'/v1/projects/1/session_recordings/?limit=3',
|
|
]
|
|
|
|
// Implemented in upstream's separately-licensed ee/ tree, which this fork does not
|
|
// ship, so they have no viewset at all. Pinned as 404 rather than left unlisted:
|
|
// if one of these starts answering 500 it means something half-wired it back, and
|
|
// if one starts answering 200 the honest-state UI in capabilities.ts is now lying.
|
|
const NOT_CARRIED = ['/v1/projects/1/experiments/', '/v1/projects/1/groups_types/']
|
|
|
|
test.describe('the API a session depends on', () => {
|
|
for (const path of CARRIED) {
|
|
test(`GET ${path.split('?')[0]} works`, async ({ request }) => {
|
|
const r = await request.get(path)
|
|
expect(r.status(), `${path} -> ${r.status()}: ${(await r.text()).slice(0, 200)}`).toBeLessThan(400)
|
|
})
|
|
}
|
|
|
|
for (const path of NOT_CARRIED) {
|
|
test(`GET ${path} is absent, not broken`, async ({ request }) => {
|
|
// 404 is the honest answer for a feature this build does not carry.
|
|
// A 5xx would mean it is half-present and throwing.
|
|
expect(await request.get(path).then((r) => r.status())).toBe(404)
|
|
})
|
|
}
|
|
})
|