Skip to content

Commit 638ceaf

Browse files
committed
MVP 🚀
1 parent 3ac3d97 commit 638ceaf

File tree

21 files changed

+458
-297
lines changed

21 files changed

+458
-297
lines changed

‎drizzle/0000_unknown_swordsman.sql‎ renamed to ‎drizzle/0000_numerous_madame_masque.sql‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ CREATE TABLE "test" (
1919
"id" serial PRIMARY KEY NOT NULL,
2020
"created_at" timestamp DEFAULT now() NOT NULL,
2121
"label" text NOT NULL,
22-
"task" text NOT NULL,
2322
"evaluation" text NOT NULL,
2423
"suite_id" integer NOT NULL
2524
);
@@ -30,7 +29,7 @@ CREATE TABLE "test_run" (
3029
"started_at" timestamp DEFAULT now(),
3130
"finished_at" timestamp,
3231
"test_id" integer NOT NULL,
33-
"suite_run_id" integer NOT NULL,
32+
"suite_run_id" integer,
3433
"status" "run_status" NOT NULL,
3534
"error" text,
3635
"browser_use_id" text,

‎drizzle/meta/0000_snapshot.json‎

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"id": "f958ebed-6ec4-405b-b868-19f8baec5c46",
2+
"id": "6840acd0-cdec-46b7-b319-c5129d7ce4c9",
33
"prevId": "00000000-0000-0000-0000-000000000000",
44
"version": "7",
55
"dialect": "postgresql",
@@ -131,12 +131,6 @@
131131
"primaryKey": false,
132132
"notNull": true
133133
},
134-
"task": {
135-
"name": "task",
136-
"type": "text",
137-
"primaryKey": false,
138-
"notNull": true
139-
},
140134
"evaluation": {
141135
"name": "evaluation",
142136
"type": "text",
@@ -212,7 +206,7 @@
212206
"name": "suite_run_id",
213207
"type": "integer",
214208
"primaryKey": false,
215-
"notNull": true
209+
"notNull": false
216210
},
217211
"status": {
218212
"name": "status",

‎drizzle/meta/_journal.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
{
66
"idx": 0,
77
"version": "7",
8-
"when": 1753436163092,
9-
"tag": "0000_unknown_swordsman",
8+
"when": 1753444295471,
9+
"tag": "0000_numerous_madame_masque",
1010
"breakpoints": true
1111
}
1212
]

‎src/app/actions.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export async function seedSuiteAction() {
4949
.insert(schema.test)
5050
.values({
5151
label: test.label,
52-
task: test.task,
5352
evaluation: test.evaluation,
5453
suiteId: insertedSuite.id,
5554
})
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { serve } from 'inngest/next'
22

33
import { inngest } from '@/lib/inngest/client'
4-
import { helloWorld, runTestSuite } from '@/lib/inngest/functions'
4+
import { helloWorld, runTest, runTestSuite } from '@/lib/inngest/functions'
55

66
// Create an API that serves zero functions
77
export const { GET, POST, PUT } = serve({
@@ -10,5 +10,6 @@ export const { GET, POST, PUT } = serve({
1010
//
1111
helloWorld,
1212
runTestSuite,
13+
runTest,
1314
],
1415
})

‎src/app/layout.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export default function RootLayout({
2828
<html lang="en">
2929
<body className={`${geistSans.variable} ${geistMono.variable} antialiased bg-gray-50`}>
3030
<div className="min-h-screen">
31-
<div className="max-w-6xl mx-auto px-3 py-12 md:py-24">{children}</div>
31+
<div className="max-w-6xl mx-auto px-3 py-12 md:py-16">{children}</div>
3232
</div>
3333
</body>
3434
</html>

‎src/app/suite/[suiteId]/actions.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ export async function runSuiteAction(suiteId: number, _: FormData) {
3737
.returning()
3838

3939
for (const test of suite.tests) {
40+
// NOTE: We skip test runs with no steps because they won't do anything.
41+
if (test.steps.length === 0) {
42+
continue
43+
}
44+
4045
const [newTestRun] = await tx
4146
.insert(schema.testRun)
4247
.values({
@@ -76,7 +81,6 @@ export async function runSuiteAction(suiteId: number, _: FormData) {
7681

7782
const zCreateTest = z.object({
7883
label: z.string().min(1),
79-
task: z.string().min(1),
8084
suiteId: z.number(),
8185
})
8286

@@ -91,7 +95,6 @@ export async function createTestAction(suiteId: number, formData: FormData) {
9195
.insert(schema.test)
9296
.values({
9397
label: data.label,
94-
task: data.task,
9598
evaluation: '',
9699
suiteId: data.suiteId,
97100
})

‎src/app/suite/[suiteId]/run/[suiteRunId]/loader.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export async function loader({ suiteRunId }: { suiteRunId: number }) {
1414
with: {
1515
test: true,
1616
},
17-
orderBy: [asc(schema.testRun.createdAt)],
17+
orderBy: [asc(schema.testRun.id)],
1818
},
1919
},
2020
})
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use server'
2+
3+
import { eq } from 'drizzle-orm'
4+
import { revalidatePath } from 'next/cache'
5+
import { redirect, RedirectType } from 'next/navigation'
6+
7+
import { db } from '@/lib/db/db'
8+
import * as schema from '@/lib/db/schema'
9+
import { inngest } from '@/lib/inngest/client'
10+
11+
export async function runTestAction(testId: number, _: FormData) {
12+
// NOTE: First we create a new suite run and all related test runs.
13+
14+
const { test, testRunId } = await db.transaction(async (tx) => {
15+
const test = await db.query.test.findFirst({
16+
where: eq(schema.test.id, testId),
17+
with: {
18+
steps: true,
19+
suite: true,
20+
},
21+
})
22+
23+
if (!test) {
24+
throw new Error(`Test not found: ${testId}`)
25+
}
26+
27+
const [newTestRun] = await tx
28+
.insert(schema.testRun)
29+
.values({
30+
testId: test.id,
31+
status: 'pending',
32+
})
33+
.returning()
34+
35+
for (const step of test.steps) {
36+
await tx.insert(schema.testRunStep).values({
37+
testRunId: newTestRun.id,
38+
stepId: step.id,
39+
status: 'pending',
40+
})
41+
}
42+
43+
return { test, testRunId: newTestRun.id }
44+
})
45+
46+
try {
47+
await inngest.send({
48+
name: 'test/run',
49+
data: {
50+
testRunId,
51+
},
52+
})
53+
54+
revalidatePath(`/suite/${test.suiteId}/test/${testId}`)
55+
} catch (error) {
56+
console.error('Failed to trigger suite run:', error)
57+
}
58+
59+
redirect(`/suite/${test.suiteId}/test/${testId}/run/${testRunId}`, RedirectType.push)
60+
}

‎src/app/suite/[suiteId]/test/[testId]/edit/actions.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as schema from '@/lib/db/schema'
99
import { ExhaustiveSwitchCheck } from '@/lib/types'
1010

1111
export async function saveTest(id: number, test: State, _: FormData): Promise<void> {
12-
const { label, task, evaluation, steps } = test
12+
const { label, evaluation, steps } = test
1313

1414
const dbTest = await db.query.test.findFirst({
1515
where: eq(schema.test.id, id),
@@ -23,7 +23,6 @@ export async function saveTest(id: number, test: State, _: FormData): Promise<vo
2323
.update(schema.test)
2424
.set({
2525
label,
26-
task,
2726
evaluation,
2827
})
2928
.where(eq(schema.test.id, id))

0 commit comments

Comments
 (0)