enforce minimum 8 character slug on create/update. Closes #4376
This commit is contained in:
1 parent
735d85c7af
commit
a4a0167515
4 files changed
+138
-2
No files matched your search
@@ -0,0 +1,71 @@
|
||||
import { beforeEach, expect, test, vi } from 'vitest';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { canCreateTeamWebsite, canCreateWebsite } from '@/permissions';
|
||||
import { createLink } from '@/queries/prisma';
|
||||
import { POST } from './route';
|
||||
|
||||
vi.mock('@/lib/request', () => ({
|
||||
getQueryFilters: vi.fn(),
|
||||
parseRequest: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/permissions', () => ({
|
||||
canCreateTeamWebsite: vi.fn(),
|
||||
canCreateWebsite: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/queries/prisma', () => ({
|
||||
createLink: vi.fn(),
|
||||
getUserLinks: vi.fn(),
|
||||
}));
|
||||
|
||||
const parseRequestMock = vi.mocked(parseRequest);
|
||||
const canCreateTeamWebsiteMock = vi.mocked(canCreateTeamWebsite);
|
||||
const canCreateWebsiteMock = vi.mocked(canCreateWebsite);
|
||||
const createLinkMock = vi.mocked(createLink);
|
||||
|
||||
beforeEach(() => {
|
||||
parseRequestMock.mockReset();
|
||||
canCreateTeamWebsiteMock.mockReset();
|
||||
canCreateWebsiteMock.mockReset();
|
||||
createLinkMock.mockReset();
|
||||
});
|
||||
|
||||
test('POST requires link slugs to be at least 8 characters so create matches edit validation', async () => {
|
||||
parseRequestMock.mockResolvedValue({
|
||||
auth: {
|
||||
user: {
|
||||
id: 'user-1',
|
||||
},
|
||||
},
|
||||
body: {
|
||||
name: 'Docs',
|
||||
url: 'https://example.com',
|
||||
slug: 'abcdefgh',
|
||||
},
|
||||
error: undefined,
|
||||
});
|
||||
canCreateWebsiteMock.mockResolvedValue(true);
|
||||
createLinkMock.mockResolvedValue({ id: 'link-1' } as any);
|
||||
|
||||
const response = await POST(new Request('http://localhost/api/links', { method: 'POST' }));
|
||||
const schema = parseRequestMock.mock.calls[0][1] as {
|
||||
safeParse: (value: unknown) => { success: boolean };
|
||||
};
|
||||
|
||||
expect(schema.safeParse({ name: 'Docs', url: 'https://example.com', slug: '1234567' }).success).toBe(
|
||||
false,
|
||||
);
|
||||
expect(schema.safeParse({ name: 'Docs', url: 'https://example.com', slug: '12345678' }).success).toBe(
|
||||
true,
|
||||
);
|
||||
expect(createLinkMock).toHaveBeenCalledWith({
|
||||
id: expect.any(String),
|
||||
name: 'Docs',
|
||||
url: 'https://example.com',
|
||||
slug: 'abcdefgh',
|
||||
teamId: undefined,
|
||||
userId: 'user-1',
|
||||
});
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
@@ -30,7 +30,7 @@ export async function POST(request: Request) {
|
||||
const schema = z.object({
|
||||
name: z.string().max(100),
|
||||
url: z.string().max(500),
|
||||
slug: z.string().max(100),
|
||||
slug: z.string().min(8).max(100),
|
||||
teamId: z.string().nullable().optional(),
|
||||
id: z.uuid().nullable().optional(),
|
||||
});
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { beforeEach, expect, test, vi } from 'vitest';
|
||||
import { parseRequest } from '@/lib/request';
|
||||
import { canCreateTeamWebsite, canCreateWebsite } from '@/permissions';
|
||||
import { createPixel } from '@/queries/prisma';
|
||||
import { POST } from './route';
|
||||
|
||||
vi.mock('@/lib/request', () => ({
|
||||
getQueryFilters: vi.fn(),
|
||||
parseRequest: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/permissions', () => ({
|
||||
canCreateTeamWebsite: vi.fn(),
|
||||
canCreateWebsite: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@/queries/prisma', () => ({
|
||||
createPixel: vi.fn(),
|
||||
getUserPixels: vi.fn(),
|
||||
}));
|
||||
|
||||
const parseRequestMock = vi.mocked(parseRequest);
|
||||
const canCreateTeamWebsiteMock = vi.mocked(canCreateTeamWebsite);
|
||||
const canCreateWebsiteMock = vi.mocked(canCreateWebsite);
|
||||
const createPixelMock = vi.mocked(createPixel);
|
||||
|
||||
beforeEach(() => {
|
||||
parseRequestMock.mockReset();
|
||||
canCreateTeamWebsiteMock.mockReset();
|
||||
canCreateWebsiteMock.mockReset();
|
||||
createPixelMock.mockReset();
|
||||
});
|
||||
|
||||
test('POST requires pixel slugs to be at least 8 characters so create matches edit validation', async () => {
|
||||
parseRequestMock.mockResolvedValue({
|
||||
auth: {
|
||||
user: {
|
||||
id: 'user-1',
|
||||
},
|
||||
},
|
||||
body: {
|
||||
name: 'Pixel',
|
||||
slug: 'abcdefgh',
|
||||
},
|
||||
error: undefined,
|
||||
});
|
||||
canCreateWebsiteMock.mockResolvedValue(true);
|
||||
createPixelMock.mockResolvedValue({ id: 'pixel-1' } as any);
|
||||
|
||||
const response = await POST(new Request('http://localhost/api/pixels', { method: 'POST' }));
|
||||
const schema = parseRequestMock.mock.calls[0][1] as {
|
||||
safeParse: (value: unknown) => { success: boolean };
|
||||
};
|
||||
|
||||
expect(schema.safeParse({ name: 'Pixel', slug: '1234567' }).success).toBe(false);
|
||||
expect(schema.safeParse({ name: 'Pixel', slug: '12345678' }).success).toBe(true);
|
||||
expect(createPixelMock).toHaveBeenCalledWith({
|
||||
id: expect.any(String),
|
||||
name: 'Pixel',
|
||||
slug: 'abcdefgh',
|
||||
teamId: undefined,
|
||||
userId: 'user-1',
|
||||
});
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
@@ -29,7 +29,7 @@ export async function GET(request: Request) {
|
||||
export async function POST(request: Request) {
|
||||
const schema = z.object({
|
||||
name: z.string().max(100),
|
||||
slug: z.string().max(100),
|
||||
slug: z.string().min(8).max(100),
|
||||
teamId: z.string().nullable().optional(),
|
||||
id: z.uuid().nullable().optional(),
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user