feat(validation): rename contributionTier → contributionAmount in Zod schemas
This commit is contained in:
parent
55af652263
commit
e4dade18b9
3 changed files with 49 additions and 35 deletions
|
|
@ -9,7 +9,7 @@ export const memberCreateSchema = z.object({
|
||||||
email: z.string().trim().toLowerCase().email(),
|
email: z.string().trim().toLowerCase().email(),
|
||||||
name: z.string().min(1).max(200),
|
name: z.string().min(1).max(200),
|
||||||
circle: z.enum(['community', 'founder', 'practitioner']),
|
circle: z.enum(['community', 'founder', 'practitioner']),
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50'])
|
contributionAmount: z.number().int().min(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const memberProfileUpdateSchema = z.object({
|
export const memberProfileUpdateSchema = z.object({
|
||||||
|
|
@ -57,7 +57,7 @@ export const helcimCustomerSchema = z.object({
|
||||||
name: z.string().min(1).max(200),
|
name: z.string().min(1).max(200),
|
||||||
email: z.string().trim().toLowerCase().email(),
|
email: z.string().trim().toLowerCase().email(),
|
||||||
circle: z.enum(['community', 'founder', 'practitioner']).optional(),
|
circle: z.enum(['community', 'founder', 'practitioner']).optional(),
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50']).optional(),
|
contributionAmount: z.number().int().min(0).optional(),
|
||||||
agreedToGuidelines: z.literal(true)
|
agreedToGuidelines: z.literal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ export const helcimInitializePaymentSchema = z.object({
|
||||||
|
|
||||||
export const helcimSubscriptionSchema = z.object({
|
export const helcimSubscriptionSchema = z.object({
|
||||||
customerId: z.union([z.string().min(1), z.number()]),
|
customerId: z.union([z.string().min(1), z.number()]),
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50']),
|
contributionAmount: z.number().int().min(0),
|
||||||
customerCode: z.union([z.string().min(1).max(200), z.number()]).transform(String),
|
customerCode: z.union([z.string().min(1).max(200), z.number()]).transform(String),
|
||||||
cardToken: z.string().max(500).optional().nullable(),
|
cardToken: z.string().max(500).optional().nullable(),
|
||||||
cadence: z.enum(['monthly', 'annual']).default('monthly')
|
cadence: z.enum(['monthly', 'annual']).default('monthly')
|
||||||
|
|
@ -140,7 +140,7 @@ export const eventPaymentSchema = z.object({
|
||||||
// --- Member schemas ---
|
// --- Member schemas ---
|
||||||
|
|
||||||
export const updateContributionSchema = z.object({
|
export const updateContributionSchema = z.object({
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50']),
|
contributionAmount: z.number().int().min(0),
|
||||||
cadence: z.enum(['monthly', 'annual']).default('monthly')
|
cadence: z.enum(['monthly', 'annual']).default('monthly')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -294,14 +294,14 @@ export const adminMemberCreateSchema = z.object({
|
||||||
name: z.string().min(1).max(200),
|
name: z.string().min(1).max(200),
|
||||||
email: z.string().trim().toLowerCase().email(),
|
email: z.string().trim().toLowerCase().email(),
|
||||||
circle: z.enum(['community', 'founder', 'practitioner']),
|
circle: z.enum(['community', 'founder', 'practitioner']),
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50'])
|
contributionAmount: z.number().int().min(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const adminMemberUpdateSchema = z.object({
|
export const adminMemberUpdateSchema = z.object({
|
||||||
name: z.string().min(1).max(200),
|
name: z.string().min(1).max(200),
|
||||||
email: z.string().trim().toLowerCase().email(),
|
email: z.string().trim().toLowerCase().email(),
|
||||||
circle: z.enum(['community', 'founder', 'practitioner']),
|
circle: z.enum(['community', 'founder', 'practitioner']),
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50']),
|
contributionAmount: z.number().int().min(0),
|
||||||
status: z.enum(['pending_payment', 'active', 'suspended', 'cancelled'])
|
status: z.enum(['pending_payment', 'active', 'suspended', 'cancelled'])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -314,7 +314,7 @@ export const bulkMemberImportSchema = z.object({
|
||||||
name: z.string().min(1).max(200),
|
name: z.string().min(1).max(200),
|
||||||
email: z.string().trim().toLowerCase().email(),
|
email: z.string().trim().toLowerCase().email(),
|
||||||
circle: z.enum(['community', 'founder', 'practitioner']),
|
circle: z.enum(['community', 'founder', 'practitioner']),
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50'])
|
contributionAmount: z.number().int().min(0)
|
||||||
})).min(1).max(100)
|
})).min(1).max(100)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -351,7 +351,7 @@ export const inviteAcceptSchema = z.object({
|
||||||
location: z.string().max(200).optional(),
|
location: z.string().max(200).optional(),
|
||||||
circle: z.enum(['community', 'founder', 'practitioner']),
|
circle: z.enum(['community', 'founder', 'practitioner']),
|
||||||
motivation: z.string().max(5000).optional(),
|
motivation: z.string().max(5000).optional(),
|
||||||
contributionTier: z.enum(['0', '5', '15', '30', '50']),
|
contributionAmount: z.number().int().min(0),
|
||||||
agreedToGuidelines: z.literal(true),
|
agreedToGuidelines: z.literal(true),
|
||||||
token: z.string().min(1)
|
token: z.string().min(1)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -138,16 +138,16 @@ describe('helcimSubscriptionSchema', () => {
|
||||||
it('accepts valid subscription data', () => {
|
it('accepts valid subscription data', () => {
|
||||||
const result = helcimSubscriptionSchema.safeParse({
|
const result = helcimSubscriptionSchema.safeParse({
|
||||||
customerId: '12345',
|
customerId: '12345',
|
||||||
contributionTier: '15',
|
contributionAmount: 15,
|
||||||
customerCode: 'CST123'
|
customerCode: 'CST123'
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rejects invalid contribution tier', () => {
|
it('rejects negative contributionAmount', () => {
|
||||||
const result = helcimSubscriptionSchema.safeParse({
|
const result = helcimSubscriptionSchema.safeParse({
|
||||||
customerId: '12345',
|
customerId: '12345',
|
||||||
contributionTier: '999',
|
contributionAmount: -1,
|
||||||
customerCode: 'CST123'
|
customerCode: 'CST123'
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(false)
|
expect(result.success).toBe(false)
|
||||||
|
|
@ -156,7 +156,7 @@ describe('helcimSubscriptionSchema', () => {
|
||||||
it('rejects missing customerCode', () => {
|
it('rejects missing customerCode', () => {
|
||||||
const result = helcimSubscriptionSchema.safeParse({
|
const result = helcimSubscriptionSchema.safeParse({
|
||||||
customerId: '12345',
|
customerId: '12345',
|
||||||
contributionTier: '15'
|
contributionAmount: 15
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(false)
|
expect(result.success).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
@ -164,7 +164,7 @@ describe('helcimSubscriptionSchema', () => {
|
||||||
it('accepts cadence: monthly', () => {
|
it('accepts cadence: monthly', () => {
|
||||||
const result = helcimSubscriptionSchema.safeParse({
|
const result = helcimSubscriptionSchema.safeParse({
|
||||||
customerId: '12345',
|
customerId: '12345',
|
||||||
contributionTier: '15',
|
contributionAmount: 15,
|
||||||
customerCode: 'CST123',
|
customerCode: 'CST123',
|
||||||
cadence: 'monthly'
|
cadence: 'monthly'
|
||||||
})
|
})
|
||||||
|
|
@ -175,7 +175,7 @@ describe('helcimSubscriptionSchema', () => {
|
||||||
it('accepts cadence: annual', () => {
|
it('accepts cadence: annual', () => {
|
||||||
const result = helcimSubscriptionSchema.safeParse({
|
const result = helcimSubscriptionSchema.safeParse({
|
||||||
customerId: '12345',
|
customerId: '12345',
|
||||||
contributionTier: '15',
|
contributionAmount: 15,
|
||||||
customerCode: 'CST123',
|
customerCode: 'CST123',
|
||||||
cadence: 'annual'
|
cadence: 'annual'
|
||||||
})
|
})
|
||||||
|
|
@ -186,7 +186,7 @@ describe('helcimSubscriptionSchema', () => {
|
||||||
it('rejects cadence: weekly', () => {
|
it('rejects cadence: weekly', () => {
|
||||||
const result = helcimSubscriptionSchema.safeParse({
|
const result = helcimSubscriptionSchema.safeParse({
|
||||||
customerId: '12345',
|
customerId: '12345',
|
||||||
contributionTier: '15',
|
contributionAmount: 15,
|
||||||
customerCode: 'CST123',
|
customerCode: 'CST123',
|
||||||
cadence: 'weekly'
|
cadence: 'weekly'
|
||||||
})
|
})
|
||||||
|
|
@ -196,7 +196,7 @@ describe('helcimSubscriptionSchema', () => {
|
||||||
it('defaults cadence to monthly when omitted', () => {
|
it('defaults cadence to monthly when omitted', () => {
|
||||||
const result = helcimSubscriptionSchema.safeParse({
|
const result = helcimSubscriptionSchema.safeParse({
|
||||||
customerId: '12345',
|
customerId: '12345',
|
||||||
contributionTier: '15',
|
contributionAmount: 15,
|
||||||
customerCode: 'CST123'
|
customerCode: 'CST123'
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
|
|
@ -334,19 +334,26 @@ describe('eventPaymentSchema', () => {
|
||||||
// --- Member schemas ---
|
// --- Member schemas ---
|
||||||
|
|
||||||
describe('updateContributionSchema', () => {
|
describe('updateContributionSchema', () => {
|
||||||
it('accepts valid contribution tier', () => {
|
it('accepts valid contributionAmount', () => {
|
||||||
const result = updateContributionSchema.safeParse({ contributionTier: '15' })
|
const result = updateContributionSchema.safeParse({ contributionAmount: 15 })
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rejects invalid tier', () => {
|
it('accepts contributionAmount: 0, 7, 9999', () => {
|
||||||
const result = updateContributionSchema.safeParse({ contributionTier: '100' })
|
expect(updateContributionSchema.safeParse({ contributionAmount: 0 }).success).toBe(true)
|
||||||
expect(result.success).toBe(false)
|
expect(updateContributionSchema.safeParse({ contributionAmount: 7 }).success).toBe(true)
|
||||||
|
expect(updateContributionSchema.safeParse({ contributionAmount: 9999 }).success).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('rejects invalid contributionAmount values', () => {
|
||||||
|
expect(updateContributionSchema.safeParse({ contributionAmount: -1 }).success).toBe(false)
|
||||||
|
expect(updateContributionSchema.safeParse({ contributionAmount: 1.5 }).success).toBe(false)
|
||||||
|
expect(updateContributionSchema.safeParse({ contributionAmount: '15' }).success).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('strips unknown fields', () => {
|
it('strips unknown fields', () => {
|
||||||
const result = updateContributionSchema.safeParse({
|
const result = updateContributionSchema.safeParse({
|
||||||
contributionTier: '15',
|
contributionAmount: 15,
|
||||||
role: 'admin'
|
role: 'admin'
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
|
|
@ -354,24 +361,24 @@ describe('updateContributionSchema', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('accepts cadence: monthly', () => {
|
it('accepts cadence: monthly', () => {
|
||||||
const result = updateContributionSchema.safeParse({ contributionTier: '15', cadence: 'monthly' })
|
const result = updateContributionSchema.safeParse({ contributionAmount: 15, cadence: 'monthly' })
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
expect(result.data.cadence).toBe('monthly')
|
expect(result.data.cadence).toBe('monthly')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('accepts cadence: annual', () => {
|
it('accepts cadence: annual', () => {
|
||||||
const result = updateContributionSchema.safeParse({ contributionTier: '15', cadence: 'annual' })
|
const result = updateContributionSchema.safeParse({ contributionAmount: 15, cadence: 'annual' })
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
expect(result.data.cadence).toBe('annual')
|
expect(result.data.cadence).toBe('annual')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rejects cadence: weekly', () => {
|
it('rejects cadence: weekly', () => {
|
||||||
const result = updateContributionSchema.safeParse({ contributionTier: '15', cadence: 'weekly' })
|
const result = updateContributionSchema.safeParse({ contributionAmount: 15, cadence: 'weekly' })
|
||||||
expect(result.success).toBe(false)
|
expect(result.success).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('defaults cadence to monthly when omitted', () => {
|
it('defaults cadence to monthly when omitted', () => {
|
||||||
const result = updateContributionSchema.safeParse({ contributionTier: '15' })
|
const result = updateContributionSchema.safeParse({ contributionAmount: 15 })
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
expect(result.data.cadence).toBe('monthly')
|
expect(result.data.cadence).toBe('monthly')
|
||||||
})
|
})
|
||||||
|
|
@ -425,7 +432,7 @@ describe('adminMemberCreateSchema', () => {
|
||||||
name: 'Admin Created',
|
name: 'Admin Created',
|
||||||
email: 'admin-created@example.com',
|
email: 'admin-created@example.com',
|
||||||
circle: 'founder',
|
circle: 'founder',
|
||||||
contributionTier: '30'
|
contributionAmount: 30
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
@ -435,7 +442,7 @@ describe('adminMemberCreateSchema', () => {
|
||||||
name: 'Admin Created',
|
name: 'Admin Created',
|
||||||
email: 'admin-created@example.com',
|
email: 'admin-created@example.com',
|
||||||
circle: 'founder',
|
circle: 'founder',
|
||||||
contributionTier: '30',
|
contributionAmount: 30,
|
||||||
role: 'admin'
|
role: 'admin'
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
|
|
@ -447,7 +454,7 @@ describe('adminMemberCreateSchema', () => {
|
||||||
name: 'Admin Created',
|
name: 'Admin Created',
|
||||||
email: 'admin-created@example.com',
|
email: 'admin-created@example.com',
|
||||||
circle: 'founder',
|
circle: 'founder',
|
||||||
contributionTier: '30',
|
contributionAmount: 30,
|
||||||
status: 'active'
|
status: 'active'
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(true)
|
expect(result.success).toBe(true)
|
||||||
|
|
@ -459,7 +466,7 @@ describe('adminMemberCreateSchema', () => {
|
||||||
name: 'Admin Created',
|
name: 'Admin Created',
|
||||||
email: 'admin-created@example.com',
|
email: 'admin-created@example.com',
|
||||||
circle: 'superadmin',
|
circle: 'superadmin',
|
||||||
contributionTier: '30'
|
contributionAmount: 30
|
||||||
})
|
})
|
||||||
expect(result.success).toBe(false)
|
expect(result.success).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ describe('memberCreateSchema', () => {
|
||||||
email: 'new@example.com',
|
email: 'new@example.com',
|
||||||
name: 'Test User',
|
name: 'Test User',
|
||||||
circle: 'community',
|
circle: 'community',
|
||||||
contributionTier: '0'
|
contributionAmount: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
it('accepts valid member data', () => {
|
it('accepts valid member data', () => {
|
||||||
|
|
@ -80,9 +80,16 @@ describe('memberCreateSchema', () => {
|
||||||
expect(result.success).toBe(false)
|
expect(result.success).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rejects invalid contributionTier enum', () => {
|
it('accepts contributionAmount: 0, 7, 9999', () => {
|
||||||
const result = memberCreateSchema.safeParse({ ...validMember, contributionTier: '999' })
|
expect(memberCreateSchema.safeParse({ ...validMember, contributionAmount: 0 }).success).toBe(true)
|
||||||
expect(result.success).toBe(false)
|
expect(memberCreateSchema.safeParse({ ...validMember, contributionAmount: 7 }).success).toBe(true)
|
||||||
|
expect(memberCreateSchema.safeParse({ ...validMember, contributionAmount: 9999 }).success).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('rejects invalid contributionAmount values', () => {
|
||||||
|
expect(memberCreateSchema.safeParse({ ...validMember, contributionAmount: -1 }).success).toBe(false)
|
||||||
|
expect(memberCreateSchema.safeParse({ ...validMember, contributionAmount: 1.5 }).success).toBe(false)
|
||||||
|
expect(memberCreateSchema.safeParse({ ...validMember, contributionAmount: '15' }).success).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('rejects missing required fields', () => {
|
it('rejects missing required fields', () => {
|
||||||
|
|
@ -246,7 +253,7 @@ describe('validateBody', () => {
|
||||||
it('strips unknown fields from output', async () => {
|
it('strips unknown fields from output', async () => {
|
||||||
const event = createMockEvent({
|
const event = createMockEvent({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: { email: 'test@example.com', name: 'Test', circle: 'community', contributionTier: '0', role: 'admin', _id: 'fake' }
|
body: { email: 'test@example.com', name: 'Test', circle: 'community', contributionAmount: 0, role: 'admin', _id: 'fake' }
|
||||||
})
|
})
|
||||||
const data = await validateBody(event, memberCreateSchema)
|
const data = await validateBody(event, memberCreateSchema)
|
||||||
expect(data).not.toHaveProperty('role')
|
expect(data).not.toHaveProperty('role')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue