mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-24 05:48:59 +08:00
160 lines
4.2 KiB
TypeScript
160 lines
4.2 KiB
TypeScript
import { nanoid } from 'nanoid';
|
|
import type { Mock } from 'vitest';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import { gqlFetcherFactory } from '../fetcher';
|
|
import type { GraphQLQuery } from '../graphql';
|
|
import {
|
|
generateRandUTF16Chars,
|
|
SPAN_ID_BYTES,
|
|
TRACE_ID_BYTES,
|
|
TraceReporter,
|
|
} from '../utils';
|
|
|
|
const query: GraphQLQuery = {
|
|
id: 'query',
|
|
query: 'query { field }',
|
|
operationName: 'query',
|
|
definitionName: 'query',
|
|
};
|
|
|
|
let fetch: Mock;
|
|
describe('GraphQL fetcher', () => {
|
|
beforeEach(() => {
|
|
fetch = vi.fn(() =>
|
|
Promise.resolve(
|
|
new Response(JSON.stringify({ data: { field: 1 } }), {
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
},
|
|
})
|
|
)
|
|
);
|
|
vi.stubGlobal('fetch', fetch);
|
|
});
|
|
|
|
afterEach(() => {
|
|
fetch.mockReset();
|
|
});
|
|
|
|
const gql = gqlFetcherFactory('https://example.com/graphql');
|
|
|
|
it('should send POST request to given endpoint', async () => {
|
|
await gql(
|
|
// @ts-expect-error variables is actually optional
|
|
{ query }
|
|
);
|
|
|
|
expect(fetch).toBeCalledTimes(1);
|
|
expect(fetch.mock.lastCall[0]).toBe('https://example.com/graphql');
|
|
const ctx = fetch.mock.lastCall[1] as RequestInit;
|
|
expect(ctx.method).toBe('POST');
|
|
});
|
|
|
|
it('should send with correct graphql JSON body', async () => {
|
|
await gql({
|
|
query,
|
|
// @ts-expect-error forgive the fake variables
|
|
variables: { a: 1, b: '2', c: { d: false } },
|
|
});
|
|
|
|
expect(fetch.mock.lastCall[1]).toEqual(
|
|
expect.objectContaining({
|
|
body: '{"query":"query { field }","variables":{"a":1,"b":"2","c":{"d":false}},"operationName":"query"}',
|
|
headers: expect.objectContaining({
|
|
'content-type': 'application/json',
|
|
'x-definition-name': 'query',
|
|
'x-operation-name': 'query',
|
|
'x-request-id': expect.any(String),
|
|
}),
|
|
method: 'POST',
|
|
})
|
|
);
|
|
});
|
|
|
|
it('should correctly ignore nil variables', async () => {
|
|
await gql({
|
|
query,
|
|
// @ts-expect-error forgive the fake variables
|
|
variables: { a: false, b: null, c: undefined },
|
|
});
|
|
|
|
expect(fetch.mock.lastCall[1].body).toMatchInlineSnapshot(
|
|
'"{\\"query\\":\\"query { field }\\",\\"variables\\":{\\"a\\":false,\\"b\\":null},\\"operationName\\":\\"query\\"}"'
|
|
);
|
|
|
|
await gql({
|
|
query,
|
|
// @ts-expect-error forgive the fake variables
|
|
variables: { a: false, b: null, c: undefined },
|
|
keepNilVariables: false,
|
|
});
|
|
|
|
expect(fetch.mock.lastCall[1].body).toMatchInlineSnapshot(
|
|
'"{\\"query\\":\\"query { field }\\",\\"variables\\":{\\"a\\":false},\\"operationName\\":\\"query\\"}"'
|
|
);
|
|
});
|
|
|
|
it('should correct handle graphql error', async () => {
|
|
fetch.mockResolvedValue(
|
|
new Response(
|
|
JSON.stringify({
|
|
data: null,
|
|
errors: [{ message: 'error', path: ['field'] }],
|
|
}),
|
|
{
|
|
headers: {
|
|
'content-type': 'application/json',
|
|
},
|
|
status: 400,
|
|
}
|
|
)
|
|
);
|
|
|
|
await expect(gql({ query, variables: void 0 })).rejects
|
|
.toMatchInlineSnapshot(`
|
|
[
|
|
[GraphQLError: error],
|
|
]
|
|
`);
|
|
});
|
|
});
|
|
|
|
describe('Trace Reporter', () => {
|
|
const startTime = new Date().toISOString();
|
|
const traceId = generateRandUTF16Chars(TRACE_ID_BYTES);
|
|
const spanId = generateRandUTF16Chars(SPAN_ID_BYTES);
|
|
const requestId = nanoid();
|
|
|
|
it('spanId, traceId should be right format', () => {
|
|
expect(
|
|
new RegExp(`^[0-9a-f]{${SPAN_ID_BYTES * 2}}$`).test(
|
|
generateRandUTF16Chars(SPAN_ID_BYTES)
|
|
)
|
|
).toBe(true);
|
|
expect(
|
|
new RegExp(`^[0-9a-f]{${TRACE_ID_BYTES * 2}}$`).test(
|
|
generateRandUTF16Chars(TRACE_ID_BYTES)
|
|
)
|
|
).toBe(true);
|
|
});
|
|
|
|
it('test createTraceSpan', () => {
|
|
const traceSpan = TraceReporter.createTraceSpan(
|
|
traceId,
|
|
spanId,
|
|
startTime,
|
|
{ requestId }
|
|
);
|
|
expect(traceSpan.startTime).toBe(startTime);
|
|
expect(
|
|
traceSpan.name ===
|
|
`projects/{GCP_PROJECT_ID}/traces/${traceId}/spans/${spanId}`
|
|
).toBe(true);
|
|
expect(traceSpan.spanId).toBe(spanId);
|
|
expect(traceSpan.attributes.attributeMap.requestId?.stringValue.value).toBe(
|
|
requestId
|
|
);
|
|
});
|
|
});
|