Skip to content

Commit fab0c9f

Browse files
committed
Generate test code by AI agents
Prompt: DB 스키마에서 `instance` 를 Local/Remote 로 분리하고 API 를 수정하면서 기존 스키마/API 에 맞춰놨던 일부 테스트가 문제 되고 있습니다. [instance.test.ts](packages/graphql/src/instance.test.ts) 파일의 20419ce 커밋 변경 사항을 참고해서 문제되는 파일들의 코드를 직접 수정하세요. 문제되는 파일들은 `mise check`, `mise test` 로 찾을 수 있습니다. 추가적으로 리모트 인스턴스를 위한 테스트도 추가하세요. 너무 복잡한 테스트 말고, 생성, host 유일성 체크 정도만 추가하세요. Assisted-by: Codex:gpt-5-6-sol
1 parent 0ef857b commit fab0c9f

4 files changed

Lines changed: 143 additions & 28 deletions

File tree

‎packages/graphql/src/account.test.ts‎

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ const accountInstancesQuery = `
5252
admin
5353
node {
5454
uuid
55-
slug
55+
location
56+
host
5657
}
5758
}
5859
}
@@ -82,7 +83,8 @@ const accountInstancesResponse = {
8283
admin: true,
8384
node: {
8485
uuid: acceptedInstanceId,
85-
slug: "test-instance",
86+
location: "Local",
87+
host: "test-instance.drfed.org",
8688
},
8789
},
8890
],
@@ -148,20 +150,7 @@ async function seedAccounts(db: Database): Promise<void> {
148150

149151
async function seedMembershipGraph(db: Database): Promise<void> {
150152
await seedAccounts(db);
151-
await db.insert(schema.instances).values([
152-
{
153-
id: acceptedInstanceId,
154-
slug: "test-instance",
155-
created,
156-
expires,
157-
},
158-
{
159-
id: pendingInstanceId,
160-
slug: "pending-instance",
161-
created,
162-
expires,
163-
},
164-
]);
153+
await seedLocalInstances(db);
165154
await db.insert(schema.instanceMembers).values([
166155
{
167156
accountId,
@@ -193,3 +182,30 @@ async function seedMembershipGraph(db: Database): Promise<void> {
193182
},
194183
]);
195184
}
185+
186+
async function seedLocalInstances(db: Database): Promise<void> {
187+
await db.insert(schema.instances).values([
188+
{
189+
id: acceptedInstanceId,
190+
location: "Local",
191+
created,
192+
},
193+
{
194+
id: pendingInstanceId,
195+
location: "Local",
196+
created,
197+
},
198+
]);
199+
await db.insert(schema.localInstances).values([
200+
{
201+
id: acceptedInstanceId,
202+
slug: "test-instance",
203+
expires,
204+
},
205+
{
206+
id: pendingInstanceId,
207+
slug: "pending-instance",
208+
expires,
209+
},
210+
]);
211+
}

‎packages/graphql/src/builder.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616

1717
import { type Database, normalizeEmail, relations } from "@drfed/models";
18-
import type { Account, Session, Location } from "@drfed/models/schema";
18+
import type { Account, Session } from "@drfed/models/schema";
1919
import { Template } from "@fedify/uri-template";
2020
import SchemaBuilder, { type ObjectRef } from "@pothos/core";
2121
import DrizzlePlugin from "@pothos/plugin-drizzle";
@@ -90,10 +90,6 @@ export interface SchemaTypes {
9090
Input: string;
9191
Output: string;
9292
};
93-
Location: {
94-
Input: Location;
95-
Output: Location;
96-
};
9793
UUID: {
9894
Input: string;
9995
Output: string;

‎packages/graphql/src/instance.test.ts‎

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import assert from "node:assert/strict";
1919

2020
import { type Database, schema } from "@drfed/models";
2121
import { describe, it } from "@logtape/testing-node/autoload";
22+
import { DrizzleQueryError } from "drizzle-orm";
2223

2324
import { withTestHarness } from "./harness.test.ts";
2425

@@ -31,9 +32,26 @@ const accountId = "00000000-0000-4000-8000-000000000001";
3132
const memberId = "00000000-0000-4000-8000-000000000002";
3233
const pendingMemberId = "00000000-0000-4000-8000-000000000003";
3334
const instanceId = "00000000-0000-4000-8000-000000000101";
35+
const duplicateRemoteInstanceId = "00000000-0000-4000-8000-000000000102";
3436
const sessionId = "00000000-0000-4000-8000-000000000201";
3537
const accessToken = "test-access-token";
3638

39+
const remoteInstanceQuery = `
40+
query RemoteInstance($uuid: UUID!) {
41+
accountByUuid(uuid: $uuid) {
42+
instances {
43+
edges {
44+
node {
45+
uuid
46+
location
47+
host
48+
}
49+
}
50+
}
51+
}
52+
}
53+
`;
54+
3755
const instanceMembersQuery = `
3856
query InstanceMembers($uuid: UUID!) {
3957
accountByUuid(uuid: $uuid) {
@@ -122,7 +140,8 @@ const createInstanceMutation = `
122140
__typename
123141
... on Instance {
124142
uuid
125-
slug
143+
location
144+
host
126145
}
127146
... on CreateInstanceError {
128147
type
@@ -146,15 +165,16 @@ describe("Mutation.createInstance", () => {
146165
const body = await response.json();
147166
assert.equal(body.errors, undefined);
148167
assert.equal(body.data.createInstance.__typename, "Instance");
149-
assert.equal(body.data.createInstance.slug, "my-instance");
168+
assert.equal(body.data.createInstance.location, "Local");
169+
assert.equal(body.data.createInstance.host, "my-instance.drfed.org");
150170
assert.equal(typeof body.data.createInstance.uuid, "string");
151171

152172
const instances = await db.select().from(schema.instances);
153173
assert.equal(instances.length, 1);
154174
const instance = instances[0]!;
155175
assert.equal(instance.location, "Local");
156176
const local = await db.query.localInstances.findFirst({
157-
where: instance,
177+
where: { id: instance.id },
158178
});
159179
assert.equal(local?.slug, "my-instance");
160180

@@ -231,6 +251,61 @@ describe("Mutation.createInstance", () => {
231251
});
232252
});
233253

254+
describe("Remote instance", () => {
255+
it("returns a created remote instance", async () => {
256+
await withTestHarness(async ({ db, post }) => {
257+
await seedRemoteInstance(db);
258+
259+
const response = await post({
260+
query: remoteInstanceQuery,
261+
variables: { uuid: accountId },
262+
});
263+
264+
assert.equal(response.status, ok);
265+
assert.deepEqual(await response.json(), {
266+
data: {
267+
accountByUuid: {
268+
instances: {
269+
edges: [
270+
{
271+
node: {
272+
uuid: instanceId,
273+
location: "Remote",
274+
host: "remote.example.com",
275+
},
276+
},
277+
],
278+
},
279+
},
280+
},
281+
});
282+
});
283+
});
284+
285+
it("requires a unique host", async () => {
286+
await withTestHarness(async ({ db }) => {
287+
await seedRemoteInstance(db);
288+
await db.insert(schema.instances).values({
289+
id: duplicateRemoteInstanceId,
290+
location: "Remote",
291+
created,
292+
});
293+
294+
await assert.rejects(
295+
db.insert(schema.remoteInstances).values({
296+
id: duplicateRemoteInstanceId,
297+
host: "remote.example.com",
298+
}),
299+
(error: unknown) =>
300+
error instanceof DrizzleQueryError &&
301+
error.cause != null &&
302+
"constraint" in error.cause &&
303+
error.cause.constraint === "remote_instances_host_key",
304+
);
305+
});
306+
});
307+
});
308+
234309
/**
235310
* Seeds an account and an authenticated session, then returns the request
236311
* options carrying the session's bearer token.
@@ -331,3 +406,27 @@ async function seedInstanceMembers(db: Database): Promise<void> {
331406
},
332407
]);
333408
}
409+
410+
async function seedRemoteInstance(db: Database): Promise<void> {
411+
await db.insert(schema.accounts).values({
412+
id: accountId,
413+
email: "owner@example.com",
414+
name: "Owner",
415+
created,
416+
});
417+
await db.insert(schema.instances).values({
418+
id: instanceId,
419+
location: "Remote",
420+
created,
421+
});
422+
await db.insert(schema.remoteInstances).values({
423+
id: instanceId,
424+
host: "remote.example.com",
425+
});
426+
await db.insert(schema.instanceMembers).values({
427+
accountId,
428+
instanceId,
429+
accepted,
430+
created,
431+
});
432+
}

‎packages/graphql/src/instance.ts‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
// oxlint-disable max-lines-per-function
1818
import { schema } from "@drfed/models";
19-
import { instanceMembers } from "@drfed/models/schema";
19+
import { instanceMembers, locationEnum } from "@drfed/models/schema";
2020
import { drizzleConnectionHelpers } from "@pothos/plugin-drizzle";
2121
import { DrizzleQueryError } from "drizzle-orm";
2222
import { and, eq, isNotNull } from "drizzle-orm/sql/expressions";
@@ -26,6 +26,10 @@ import { v7 as uuid } from "uuid";
2626
import { Account } from "./account.ts";
2727
import builder, { type DrFedObjectRef } from "./builder.ts";
2828

29+
const Location = builder.enumType("Location", {
30+
values: locationEnum.enumValues,
31+
});
32+
2933
const InstanceRef = builder.drizzleNode("instances", {
3034
name: "Instance",
3135
description: "Represents an `Instance` in the DrFed platform.",
@@ -41,7 +45,7 @@ const InstanceRef = builder.drizzleNode("instances", {
4145
description: "The UUID of the `Instance`.",
4246
}),
4347
location: t.expose("location", {
44-
type: "Location",
48+
type: Location,
4549
description: 'The location of the `Instance`: "Local" | "Remote"',
4650
}),
4751
host: t.string({
@@ -258,7 +262,7 @@ builder.mutationFields((t) => ({
258262
tooManyInstances = true;
259263
tx.rollback();
260264
}
261-
tx.insert(schema.localInstances).values({
265+
await tx.insert(schema.localInstances).values({
262266
id,
263267
slug,
264268
expires: new Date(
@@ -278,7 +282,7 @@ builder.mutationFields((t) => ({
278282
e instanceof DrizzleQueryError &&
279283
e.cause != null &&
280284
"constraint" in e.cause &&
281-
e.cause.constraint === "instances_slug_key"
285+
e.cause.constraint === "local_instances_slug_key"
282286
) {
283287
return {
284288
message: `The slug ${JSON.stringify(slug)} is already taken.`,

0 commit comments

Comments
 (0)