Skip to content

Commit 020494f

Browse files
feat: add tests for /api/document (#932)
1 parent 5b4ad94 commit 020494f

File tree

6 files changed

+316
-19
lines changed

6 files changed

+316
-19
lines changed

app/(chat)/api/document/route.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export async function GET(request: Request) {
1616

1717
const session = await auth();
1818

19-
if (!session || !session.user) {
19+
if (!session?.user?.id) {
2020
return new Response('Unauthorized', { status: 401 });
2121
}
2222

@@ -25,11 +25,11 @@ export async function GET(request: Request) {
2525
const [document] = documents;
2626

2727
if (!document) {
28-
return new Response('Not Found', { status: 404 });
28+
return new Response('Not found', { status: 404 });
2929
}
3030

3131
if (document.userId !== session.user.id) {
32-
return new Response('Unauthorized', { status: 401 });
32+
return new Response('Forbidden', { status: 403 });
3333
}
3434

3535
return Response.json(documents, { status: 200 });
@@ -56,7 +56,7 @@ export async function POST(request: Request) {
5656
}: { content: string; title: string; kind: ArtifactKind } =
5757
await request.json();
5858

59-
const documents = await getDocumentsById({ id: id });
59+
const documents = await getDocumentsById({ id });
6060

6161
if (documents.length > 0) {
6262
const [document] = documents;
@@ -104,10 +104,10 @@ export async function DELETE(request: Request) {
104104
return new Response('Unauthorized', { status: 401 });
105105
}
106106

107-
await deleteDocumentsByIdAfterTimestamp({
107+
const documentsDeleted = await deleteDocumentsByIdAfterTimestamp({
108108
id,
109109
timestamp: new Date(timestamp),
110110
});
111111

112-
return new Response('Deleted', { status: 200 });
112+
return Response.json(documentsDeleted, { status: 200 });
113113
}

lib/db/queries.ts

+26-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
import 'server-only';
22

33
import { genSaltSync, hashSync } from 'bcrypt-ts';
4-
import { and, asc, desc, eq, gt, gte, inArray, lt, SQL } from 'drizzle-orm';
4+
import {
5+
and,
6+
asc,
7+
desc,
8+
eq,
9+
gt,
10+
gte,
11+
inArray,
12+
lt,
13+
type SQL,
14+
} from 'drizzle-orm';
515
import { drizzle } from 'drizzle-orm/postgres-js';
616
import postgres from 'postgres';
717

@@ -15,9 +25,9 @@ import {
1525
message,
1626
vote,
1727
type DBMessage,
18-
Chat,
28+
type Chat,
1929
} from './schema';
20-
import { ArtifactKind } from '@/components/artifact';
30+
import type { ArtifactKind } from '@/components/artifact';
2131

2232
// Optionally, if not using email/pass login, you can
2333
// use the Drizzle adapter for Auth.js / NextAuth
@@ -241,14 +251,17 @@ export async function saveDocument({
241251
userId: string;
242252
}) {
243253
try {
244-
return await db.insert(document).values({
245-
id,
246-
title,
247-
kind,
248-
content,
249-
userId,
250-
createdAt: new Date(),
251-
});
254+
return await db
255+
.insert(document)
256+
.values({
257+
id,
258+
title,
259+
kind,
260+
content,
261+
userId,
262+
createdAt: new Date(),
263+
})
264+
.returning();
252265
} catch (error) {
253266
console.error('Failed to save document in database');
254267
throw error;
@@ -304,7 +317,8 @@ export async function deleteDocumentsByIdAfterTimestamp({
304317

305318
return await db
306319
.delete(document)
307-
.where(and(eq(document.id, id), gt(document.createdAt, timestamp)));
320+
.where(and(eq(document.id, id), gt(document.createdAt, timestamp)))
321+
.returning();
308322
} catch (error) {
309323
console.error(
310324
'Failed to delete documents by id after timestamp from database',

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ai-chatbot",
3-
"version": "3.0.2",
3+
"version": "3.0.3",
44
"private": true,
55
"scripts": {
66
"dev": "next dev --turbo",

playwright.config.ts

+8
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ export default defineConfig({
9191
storageState: 'playwright/.auth/session.json',
9292
},
9393
},
94+
{
95+
name: 'routes',
96+
testMatch: /routes\/.*.test.ts/,
97+
dependencies: [],
98+
use: {
99+
...devices['Desktop Chrome'],
100+
},
101+
},
94102

95103
// {
96104
// name: 'firefox',

tests/auth-helper.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import {
4+
type APIRequestContext,
5+
type Browser,
6+
type BrowserContext,
7+
expect,
8+
type Page,
9+
} from '@playwright/test';
10+
import { generateId } from 'ai';
11+
import { getUnixTime } from 'date-fns';
12+
13+
export type UserContext = {
14+
context: BrowserContext;
15+
page: Page;
16+
request: APIRequestContext;
17+
};
18+
19+
export async function createAuthenticatedContext({
20+
browser,
21+
name,
22+
}: {
23+
browser: Browser;
24+
name: string;
25+
}): Promise<UserContext> {
26+
const authDir = path.join(__dirname, '../playwright/.auth');
27+
28+
if (!fs.existsSync(authDir)) {
29+
fs.mkdirSync(authDir, { recursive: true });
30+
}
31+
32+
const storageFile = path.join(authDir, `${name}.json`);
33+
34+
const context = await browser.newContext();
35+
const page = await context.newPage();
36+
37+
const email = `test-${name}-${getUnixTime(new Date())}@playwright.com`;
38+
const password = generateId(16);
39+
40+
await page.goto('http://localhost:3000/register');
41+
await page.getByPlaceholder('[email protected]').click();
42+
await page.getByPlaceholder('[email protected]').fill(email);
43+
await page.getByLabel('Password').click();
44+
await page.getByLabel('Password').fill(password);
45+
await page.getByRole('button', { name: 'Sign Up' }).click();
46+
47+
await expect(page.getByTestId('toast')).toContainText(
48+
'Account created successfully!',
49+
);
50+
51+
await context.storageState({ path: storageFile });
52+
await page.close();
53+
54+
const newContext = await browser.newContext({ storageState: storageFile });
55+
const newPage = await newContext.newPage();
56+
57+
return {
58+
context: newContext,
59+
page: newPage,
60+
request: newContext.request,
61+
};
62+
}

0 commit comments

Comments
 (0)