-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdraft-get-contract.test.ts
More file actions
110 lines (97 loc) · 3.9 KB
/
Copy pathdraft-get-contract.test.ts
File metadata and controls
110 lines (97 loc) · 3.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { existsSync, readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
const PROJECT_ROOT = dirname(fileURLToPath(import.meta.url));
const PRODUCT_ROOT = process.env["XQUIK_PRODUCT_ROOT"] ?? join(PROJECT_ROOT, "..", "xquik");
const page = readFileSync(join(PROJECT_ROOT, "api-reference/drafts/get.mdx"), "utf8");
const normalizedPage = page.replaceAll(/\s+/gu, " ");
const openapi = readFileSync(join(PROJECT_ROOT, "openapi.yaml"), "utf8");
const routePath = join(PRODUCT_ROOT, "app/api/v1/drafts/[id]/route.ts");
const getOperation = openapi.slice(
openapi.indexOf(" operationId: getDraft"),
openapi.indexOf(" delete:", openapi.indexOf(" operationId: getDraft")),
);
describe("get tweet draft documentation", (): void => {
it("keeps every response and authentication scheme aligned", (): void => {
expect.assertions(1);
expect({
apiKeyAuth: getOperation.includes("apiKey: []"),
oauthAuth: getOperation.includes("oauthBearer: []"),
statuses: ["200", "400", "401", "404", "429"].every((status) =>
getOperation.includes(` '${status}':`),
),
}).toStrictEqual({ apiKeyAuth: true, oauthAuth: true, statuses: true });
});
it("documents only the canonical draft response fields", (): void => {
expect.assertions(1);
expect({
canonicalFields: ["id", "text", "topic", "goal", "createdAt", "updatedAt"].every((field) =>
page.includes(`<ResponseField name="${field}"`),
),
mediaDenied: normalizedPage.includes(
"The canonical draft object contains no media, reply target, or tweet ID.",
),
threadDenied: normalizedPage.includes(
"It does not return thread order, media attachments, reply targets, or publishing results.",
),
}).toStrictEqual({
canonicalFields: true,
mediaDenied: true,
threadDenied: true,
});
});
it("separates retrieval from native drafts and write actions", (): void => {
expect.assertions(1);
expect({
nativeBoundary: normalizedPage.includes(
"Xquik drafts are separate from [X's native Unsent posts]",
),
noEdit: normalizedPage.includes("This route provides no edit operation."),
noPublish: normalizedPage.includes(
"Reading a draft never sends text to followers or creates likes and replies.",
),
readScope: page.includes("## Retrieve one tweet draft by ID"),
}).toStrictEqual({
nativeBoundary: true,
noEdit: true,
noPublish: true,
readScope: true,
});
});
it("preserves focused tweet draft retrieval search intent", (): void => {
expect.assertions(1);
expect(
[
'title: "Get a tweet draft by ID with the Xquik API"',
'"get tweet draft"',
'"retrieve tweet draft"',
"## Read the tweet draft fields",
"## Build a tweet draft review workflow",
"## Answer tweet draft retrieval questions",
].every((snippet) => page.includes(snippet)),
).toBe(true);
});
it("matches the product route when its source is available", (): void => {
expect.assertions(1);
if (!existsSync(routePath)) {
expect(existsSync(routePath)).toBe(false);
return;
}
const route = readFileSync(routePath, "utf8");
const getStart = route.indexOf("export async function GET(");
const deleteStart = route.indexOf("\nexport async function DELETE(", getStart);
const getSource = route.slice(getStart, deleteStart);
expect({
formatsDraft: getSource.includes("formatDraftRow(row)"),
invalidId: getSource.includes("error: 'invalid_id'"),
notFound: getSource.includes("error: 'draft_not_found'"),
routeFound: getStart >= 0 && deleteStart > getStart,
}).toStrictEqual({
formatsDraft: true,
invalidId: true,
notFound: true,
routeFound: true,
});
});
});