Skip to content

Commit 4234f76

Browse files
committed
accept plain date strings in DateTime field filters
1 parent 39a0a28 commit 4234f76

2 files changed

Lines changed: 84 additions & 1 deletion

File tree

packages/orm/src/client/zod/factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ export class ZodSchemaFactory<
783783
allowedFilterKinds: string[] | undefined,
784784
): ZodType {
785785
return this.makeCommonPrimitiveFilterSchema(
786-
z.union([z.iso.datetime(), z.date()]),
786+
z.union([z.iso.date(), z.iso.datetime(), z.date()]),
787787
optional,
788788
() => z.lazy(() => this.makeDateTimeFilterSchema(optional, withAggregations, allowedFilterKinds)),
789789
withAggregations ? ['_count', '_min', '_max'] : undefined,
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { createTestClient } from '@zenstackhq/testtools';
2+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
3+
4+
// This test verifies that plain date strings are accepted for all DateTime fields.
5+
describe('plain date string filter tests for DateTime fields', () => {
6+
const schema = `
7+
model Event {
8+
id Int @id @default(autoincrement())
9+
name String
10+
eventDate DateTime @db.Date
11+
createdAt DateTime @default(now())
12+
}
13+
`;
14+
15+
let client: any;
16+
17+
beforeEach(async () => {
18+
client = await createTestClient(schema, {
19+
usePrismaPush: true,
20+
provider: 'postgresql',
21+
});
22+
});
23+
24+
afterEach(async () => {
25+
await client?.$disconnect();
26+
});
27+
28+
it('accepts a plain date string ("YYYY-MM-DD") in an equality filter on a @db.Date field', async () => {
29+
const filterSchema = client.$zod.makeFindManySchema('Event');
30+
const result = filterSchema.safeParse({ where: { eventDate: '2007-05-23' } });
31+
expect(result.success, `Expected plain date string to be accepted, got: ${JSON.stringify(result.error)}`).toBe(
32+
true,
33+
);
34+
});
35+
36+
it('accepts an ISO datetime string in a filter on a @db.Date field', async () => {
37+
const filterSchema = client.$zod.makeFindManySchema('Event');
38+
const result = filterSchema.safeParse({ where: { eventDate: '2007-05-23T00:00:00.000Z' } });
39+
expect(result.success).toBe(true);
40+
});
41+
42+
it('accepts a Date object in a filter on a @db.Date field', async () => {
43+
const filterSchema = client.$zod.makeFindManySchema('Event');
44+
const result = filterSchema.safeParse({ where: { eventDate: new Date('2007-05-23') } });
45+
expect(result.success).toBe(true);
46+
});
47+
48+
it('rejects an invalid date string in a filter on a @db.Date field', async () => {
49+
const filterSchema = client.$zod.makeFindManySchema('Event');
50+
const result = filterSchema.safeParse({ where: { eventDate: 'not-a-date' } });
51+
expect(result.success).toBe(false);
52+
});
53+
54+
it('filters records correctly using a plain date string', async () => {
55+
await client.event.create({ data: { name: 'Conference', eventDate: new Date('2007-05-23') } });
56+
await client.event.create({ data: { name: 'Workshop', eventDate: new Date('2024-01-15') } });
57+
58+
const found = await client.event.findMany({ where: { eventDate: '2007-05-23' } });
59+
expect(found).toHaveLength(1);
60+
expect(found[0].name).toBe('Conference');
61+
});
62+
63+
it('supports gt/lt filters with plain date strings on a @db.Date field', async () => {
64+
await client.event.create({ data: { name: 'Past', eventDate: new Date('2020-01-01') } });
65+
await client.event.create({ data: { name: 'Future', eventDate: new Date('2030-01-01') } });
66+
67+
const filterSchema = client.$zod.makeFindManySchema('Event');
68+
const result = filterSchema.safeParse({ where: { eventDate: { gt: '2025-01-01' } } });
69+
expect(result.success, `Expected gt filter to be accepted, got: ${JSON.stringify(result.error)}`).toBe(true);
70+
71+
const found = await client.event.findMany({ where: { eventDate: { gt: '2025-01-01' } } });
72+
expect(found).toHaveLength(1);
73+
expect(found[0].name).toBe('Future');
74+
});
75+
76+
it('plain date string is accepted on a regular DateTime field (no @db.Date)', async () => {
77+
// Plain date strings are accepted for all DateTime fields, not just @db.Date ones,
78+
// to decouple filter validation from migration-engine attributes.
79+
const filterSchema = client.$zod.makeFindManySchema('Event');
80+
const result = filterSchema.safeParse({ where: { createdAt: '2007-05-23' } });
81+
expect(result.success).toBe(true);
82+
});
83+
});

0 commit comments

Comments
 (0)