Initial Commit
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Integration test — exercises the Altair plugin's full surface against
|
||||
* a real `Router` instance, end to end.
|
||||
*
|
||||
* Stage-7 spec notes the desired Playwright + Yoga integration; that
|
||||
* arrives once `@suaveplan/api-graphql-yoga` lands. This file pins the
|
||||
* structural integration the engine package will then layer Playwright
|
||||
* on top of — HTML response, asset response, OTel observation, and
|
||||
* collision detection — using only the dependencies actually present
|
||||
* in the genesis tree today.
|
||||
*/
|
||||
import type { Counter, Meter, MeterProvider } from "@opentelemetry/api";
|
||||
import { Router } from "@suaveplan/api-router";
|
||||
import { describe, expect, it } from "@suaveplan/testing/runner";
|
||||
import {
|
||||
createAltairInstruments,
|
||||
createAltairUi,
|
||||
GRAPHQL_UI_ALTAIR_CODES,
|
||||
GraphqlUiAltairError,
|
||||
} from "../../src/index.js";
|
||||
|
||||
interface FakeCounter {
|
||||
readonly name: string;
|
||||
addCalls: Array<{
|
||||
value: number;
|
||||
attrs?: Readonly<Record<string, unknown>>;
|
||||
}>;
|
||||
}
|
||||
|
||||
function buildFakeMeterProvider(): {
|
||||
provider: MeterProvider;
|
||||
counters: FakeCounter[];
|
||||
} {
|
||||
const counters: FakeCounter[] = [];
|
||||
const provider: MeterProvider = {
|
||||
getMeter(): Meter {
|
||||
const meter: Meter = {
|
||||
createCounter(n: string) {
|
||||
const c: FakeCounter = { name: n, addCalls: [] };
|
||||
counters.push(c);
|
||||
return {
|
||||
add(value, attrs) {
|
||||
c.addCalls.push({ value, attrs });
|
||||
},
|
||||
} as Counter;
|
||||
},
|
||||
} as unknown as Meter;
|
||||
return meter;
|
||||
},
|
||||
} as MeterProvider;
|
||||
return { provider, counters };
|
||||
}
|
||||
|
||||
describe("integration — altair end-to-end", () => {
|
||||
it("GET /graphql/ui → 200 HTML with embedded config", {
|
||||
timeout: 30000,
|
||||
}, () => {
|
||||
const { provider, counters } = buildFakeMeterProvider();
|
||||
const instruments = createAltairInstruments({
|
||||
meterProvider: provider,
|
||||
});
|
||||
const router = new Router();
|
||||
const plugin = createAltairUi(undefined, { instruments });
|
||||
plugin.mount(router);
|
||||
const match = router.match("GET", "/graphql/ui");
|
||||
expect(match).not.toBeNull();
|
||||
const res = (match as NonNullable<typeof match>).handler() as {
|
||||
status: number;
|
||||
headers: Record<string, string>;
|
||||
body: string;
|
||||
};
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers["Content-Type"]).toContain("text/html");
|
||||
expect(res.body).toContain("Altair GraphQL Client");
|
||||
expect(res.body).toContain('"graphqlEndpoint":"/graphql"');
|
||||
// Counter observed.
|
||||
expect(counters[0]?.name).toBe("graphql.ui.requests_total");
|
||||
expect(counters[0]?.addCalls[0]?.attrs).toEqual({ ui: "altair" });
|
||||
});
|
||||
|
||||
it("asset request → 200 with correct content-type and Cache-Control", {
|
||||
timeout: 30000,
|
||||
}, () => {
|
||||
const router = new Router();
|
||||
const plugin = createAltairUi();
|
||||
plugin.mount(router);
|
||||
const html = plugin.renderHtml().body;
|
||||
const jsRef = html.match(
|
||||
/\/graphql\/ui\/assets\/([0-9a-f]{16})\/altair\.js/
|
||||
);
|
||||
if (!jsRef) throw new Error("js hash not found");
|
||||
const hash = jsRef[1] as string;
|
||||
const m = router.match("GET", `/graphql/ui/assets/${hash}/altair.js`);
|
||||
expect(m).not.toBeNull();
|
||||
const res = (m as NonNullable<typeof m>).handler({
|
||||
params: { hash, name: "altair.js" },
|
||||
}) as {
|
||||
status: number;
|
||||
headers: Record<string, string>;
|
||||
body: string;
|
||||
};
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.headers["Content-Type"]).toContain("application/javascript");
|
||||
expect(res.headers["Cache-Control"]).toContain("immutable");
|
||||
});
|
||||
|
||||
it("collision against pre-mounted GET /graphql/ui refused with typed error", {
|
||||
timeout: 30000,
|
||||
}, () => {
|
||||
const router = new Router({ plugin: "first-owner" });
|
||||
router.get("/graphql/ui", () => ({
|
||||
status: 200,
|
||||
headers: {},
|
||||
body: "<other>",
|
||||
streaming: false,
|
||||
}));
|
||||
try {
|
||||
createAltairUi().mount(router);
|
||||
throw new Error("expected throw");
|
||||
} catch (err) {
|
||||
expect(err).toBeInstanceOf(GraphqlUiAltairError);
|
||||
expect((err as GraphqlUiAltairError).altairCode).toBe(
|
||||
GRAPHQL_UI_ALTAIR_CODES.ENDPOINT_COLLISION
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user