-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Consolidate quest editing UI, add
formFields
table (#315)
- Loading branch information
Showing
52 changed files
with
1,400 additions
and
1,309 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"namesake": minor | ||
--- | ||
|
||
Allow editing all quest details directly from quest page |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
import { convexTest } from "convex-test"; | ||
import { describe, expect, it } from "vitest"; | ||
import { api } from "./_generated/api"; | ||
import schema from "./schema"; | ||
import { modules } from "./test.setup"; | ||
|
||
describe("formFields", () => { | ||
describe("getById", () => { | ||
it("should return a form field by its ID", async () => { | ||
const t = convexTest(schema, modules); | ||
|
||
const userId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("users", { | ||
email: "test@example.com", | ||
role: "user", | ||
}); | ||
}); | ||
|
||
const asUser = t.withIdentity({ subject: userId }); | ||
|
||
const fieldId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("formFields", { | ||
type: "shortText", | ||
label: "First Name", | ||
name: "firstName", | ||
required: true, | ||
}); | ||
}); | ||
|
||
const field = await asUser.query(api.formFields.getById, { fieldId }); | ||
expect(field).toBeTruthy(); | ||
expect(field?.label).toBe("First Name"); | ||
expect(field?.name).toBe("firstName"); | ||
expect(field?.type).toBe("shortText"); | ||
expect(field?.required).toBe(true); | ||
}); | ||
}); | ||
|
||
describe("getByIds", () => { | ||
it("should return multiple form fields by their IDs", async () => { | ||
const t = convexTest(schema, modules); | ||
|
||
const userId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("users", { | ||
email: "test@example.com", | ||
role: "user", | ||
}); | ||
}); | ||
|
||
const asUser = t.withIdentity({ subject: userId }); | ||
|
||
const fieldIds = await t.run(async (ctx) => { | ||
const field1Id = await ctx.db.insert("formFields", { | ||
type: "shortText", | ||
label: "First Name", | ||
name: "firstName", | ||
required: true, | ||
}); | ||
|
||
const field2Id = await ctx.db.insert("formFields", { | ||
type: "email", | ||
label: "Email", | ||
name: "email", | ||
required: true, | ||
}); | ||
|
||
return [field1Id, field2Id]; | ||
}); | ||
|
||
const fields = await asUser.query(api.formFields.getByIds, { fieldIds }); | ||
expect(fields).toHaveLength(2); | ||
expect(fields.map((f) => f.label)).toContain("First Name"); | ||
expect(fields.map((f) => f.label)).toContain("Email"); | ||
}); | ||
}); | ||
|
||
describe("getAll", () => { | ||
it("should return all form fields", async () => { | ||
const t = convexTest(schema, modules); | ||
|
||
const userId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("users", { | ||
email: "test@example.com", | ||
role: "user", | ||
}); | ||
}); | ||
|
||
const asUser = t.withIdentity({ subject: userId }); | ||
|
||
await t.run(async (ctx) => { | ||
await ctx.db.insert("formFields", { | ||
type: "shortText", | ||
label: "First Name", | ||
name: "firstName", | ||
required: true, | ||
}); | ||
|
||
await ctx.db.insert("formFields", { | ||
type: "email", | ||
label: "Email", | ||
name: "email", | ||
required: true, | ||
}); | ||
}); | ||
|
||
const fields = await asUser.query(api.formFields.getAll); | ||
expect(fields.length).toBeGreaterThanOrEqual(2); | ||
expect(fields.some((f) => f.label === "First Name")).toBeTruthy(); | ||
expect(fields.some((f) => f.label === "Email")).toBeTruthy(); | ||
}); | ||
}); | ||
|
||
describe("create", () => { | ||
it("should create a new form field", async () => { | ||
const t = convexTest(schema, modules); | ||
|
||
const userId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("users", { | ||
email: "test@example.com", | ||
role: "user", | ||
}); | ||
}); | ||
|
||
const asUser = t.withIdentity({ subject: userId }); | ||
|
||
const fieldId = await asUser.mutation(api.formFields.create, { | ||
type: "shortText", | ||
label: "Phone Number", | ||
name: "phoneNumber", | ||
required: false, | ||
}); | ||
|
||
await t.run(async (ctx) => { | ||
const field = await ctx.db.get(fieldId); | ||
expect(field).toBeTruthy(); | ||
expect(field?.label).toBe("Phone Number"); | ||
expect(field?.name).toBe("phoneNumber"); | ||
expect(field?.type).toBe("shortText"); | ||
expect(field?.required).toBe(false); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("update", () => { | ||
it("should update an existing form field", async () => { | ||
const t = convexTest(schema, modules); | ||
|
||
const userId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("users", { | ||
email: "test@example.com", | ||
role: "user", | ||
}); | ||
}); | ||
|
||
const asUser = t.withIdentity({ subject: userId }); | ||
|
||
const fieldId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("formFields", { | ||
type: "shortText", | ||
label: "Original Label", | ||
name: "originalName", | ||
required: false, | ||
}); | ||
}); | ||
|
||
await asUser.mutation(api.formFields.update, { | ||
fieldId, | ||
type: "email", | ||
label: "Updated Label", | ||
name: "updatedName", | ||
required: true, | ||
}); | ||
|
||
await t.run(async (ctx) => { | ||
const field = await ctx.db.get(fieldId); | ||
expect(field).toBeTruthy(); | ||
expect(field?.label).toBe("Updated Label"); | ||
expect(field?.name).toBe("updatedName"); | ||
expect(field?.type).toBe("email"); | ||
expect(field?.required).toBe(true); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("remove", () => { | ||
it("should remove a form field", async () => { | ||
const t = convexTest(schema, modules); | ||
|
||
const userId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("users", { | ||
email: "test@example.com", | ||
role: "user", | ||
}); | ||
}); | ||
|
||
const asUser = t.withIdentity({ subject: userId }); | ||
|
||
const fieldId = await t.run(async (ctx) => { | ||
return await ctx.db.insert("formFields", { | ||
type: "shortText", | ||
label: "To Be Deleted", | ||
name: "toBeDeleted", | ||
required: false, | ||
}); | ||
}); | ||
|
||
await asUser.mutation(api.formFields.remove, { fieldId }); | ||
|
||
await t.run(async (ctx) => { | ||
const field = await ctx.db.get(fieldId); | ||
expect(field).toBeNull(); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { v } from "convex/values"; | ||
import { query } from "./_generated/server"; | ||
import { userMutation } from "./helpers"; | ||
import { formField } from "./validators"; | ||
|
||
export const getById = query({ | ||
args: { fieldId: v.id("formFields") }, | ||
handler: async (ctx, { fieldId }) => { | ||
return await ctx.db.get(fieldId); | ||
}, | ||
}); | ||
|
||
export const getByIds = query({ | ||
args: { fieldIds: v.array(v.id("formFields")) }, | ||
handler: async (ctx, { fieldIds }) => { | ||
return await ctx.db | ||
.query("formFields") | ||
.filter((q) => fieldIds.some((id) => q.eq(q.field("_id"), id))) | ||
.collect(); | ||
}, | ||
}); | ||
|
||
export const getAll = query({ | ||
handler: async (ctx) => { | ||
return await ctx.db.query("formFields").collect(); | ||
}, | ||
}); | ||
|
||
export const create = userMutation({ | ||
args: { | ||
type: formField, | ||
label: v.string(), | ||
name: v.string(), | ||
required: v.optional(v.boolean()), | ||
}, | ||
handler: async (ctx, args) => { | ||
return await ctx.db.insert("formFields", { | ||
type: args.type, | ||
label: args.label, | ||
name: args.name, | ||
required: args.required, | ||
}); | ||
}, | ||
}); | ||
|
||
export const update = userMutation({ | ||
args: { | ||
fieldId: v.id("formFields"), | ||
type: formField, | ||
label: v.string(), | ||
name: v.string(), | ||
required: v.optional(v.boolean()), | ||
}, | ||
handler: async (ctx, args) => { | ||
return await ctx.db.patch(args.fieldId, { | ||
type: args.type, | ||
label: args.label, | ||
name: args.name, | ||
required: args.required, | ||
}); | ||
}, | ||
}); | ||
|
||
export const remove = userMutation({ | ||
args: { fieldId: v.id("formFields") }, | ||
handler: async (ctx, { fieldId }) => { | ||
return await ctx.db.delete(fieldId); | ||
}, | ||
}); |
Oops, something went wrong.