I'm calling an API which uses empty strings instead of null or a result object or anything better, and I don't want empty strings to leak into the codebase. I am trying to make Zod transform these empty strings into an instance of a URL or null.
import { z } from 'astro/zod';
export const authorSchema = z.object({
type: z.string(),
name: z.string(),
photo: z.string(),
// url: z.string()
// .refine((val) => val === '' || z.string().url().safeParse(val).success)
// .transform((val) => (val === '' ? null : val)),
url: z.string()
.transform((val) => {
if (val === '') return null;
try {
return new URL(val);
} catch {
return null;
}
})
.refine((val) => val === null || val instanceof URL)
});
And these are the tests I have:
const emptyAuthor = authorSchema.safeParse({
type: 'card',
name: '',
url: '',
photo: '',
});
const goodAuthor = authorSchema.safeParse({
type: 'card',
name: faker.person.firstName(),
url: new URL(faker.internet.url()),
photo: faker.image.avatar(),
});
it('transforms empty string url to null and validates non-empty urls', () => {
expect(emptyAuthor.success).toBe(true);
expect(emptyAuthor.data?.url).toBe(null);
});
it('transforms non-empty string url to url and validates the urls', () => {
console.log(goodAuthor.error?.errors);
expect(goodAuthor.success).toBe(true);
expect(goodAuthor.data?.url).toBeInstanceOf(URL);
});
However this fails with:
[
{
code: 'invalid_type',
expected: 'string',
received: 'object',
path: [ 'url' ],
message: 'Expected string, received object'
}
]
...
AssertionError: expected false to be true // Object.is equality
- Expected
+ Received
- true
+ false
❯ design/article/webmentions/webmentions.spec.ts:72:40
70| it('transforms non-empty string url to url and validates the urls', () => {
71| console.log(goodAuthor.error?.errors);
72| expect(goodAuthor.success).toBe(true);
I tried a couple of different approaches for the URL but I keep coming back to the same problems:
- Zod returns a string
- Can't seem to get an actual URL, closest I come to is an object but it fails the
instanceofcheck