Files
portal/src/routes/api/v2/license/server.spec.ts
T
2026-08-07 14:06:20 -05:00

168 lines
4.9 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { isHttpError } from '@sveltejs/kit';
import { _clearRateLimits } from '$lib/server/v2-rate-limit';
vi.mock('$lib/db', () => ({
prisma: {
licenseKey: { findFirst: vi.fn() },
user: { findUnique: vi.fn() },
subscriptionLevel: { findFirst: vi.fn() }
}
}));
import { prisma } from '$lib/db';
import { POST } from './+server';
type POSTEvent = Parameters<typeof POST>[0];
const mockKeyFindFirst = prisma.licenseKey.findFirst as ReturnType<typeof vi.fn>;
const mockUserFindUnique = prisma.user.findUnique as ReturnType<typeof vi.fn>;
const mockLevelFindFirst = prisma.subscriptionLevel.findFirst as ReturnType<typeof vi.fn>;
function licenseRequest(body: unknown): Request {
return new Request('http://localhost/api/v2/license', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(body)
});
}
async function expectHttpError(promise: unknown, status: number, message: string) {
try {
await promise;
} catch (e) {
expect(isHttpError(e)).toBe(true);
const err = e as { status: number; body: { message: string } };
expect(err.status).toBe(status);
expect(err.body.message).toBe(message);
return;
}
throw new Error('expected handler to throw an HttpError');
}
const storedKey = {
id: 'key-1',
key: 'ABCD-EFGH-IJKL-MNOP',
active: true,
level: 'Advanced',
userId: 'user-1'
};
describe('POST /api/v2/license', () => {
beforeEach(() => {
vi.clearAllMocks();
_clearRateLimits();
});
it('returns the subscription_level object for a valid key', async () => {
mockKeyFindFirst.mockResolvedValue(storedKey);
mockUserFindUnique.mockResolvedValue({ id: 'user-1', email: 'user@example.com' });
mockLevelFindFirst.mockResolvedValue({
id: 2,
name: 'Advanced',
description: 'General + Specific'
});
const res = await POST({
request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' })
} as POSTEvent);
expect(res.status).toBe(200);
expect(await res.json()).toEqual({
key: storedKey.key,
email_address: 'user@example.com',
subscription_level: { id: 2, name: 'Advanced', description: 'General + Specific' }
});
});
it('falls back to a structurally consistent subscription_level for an unknown level name', async () => {
mockKeyFindFirst.mockResolvedValue({ ...storedKey, level: 'SomeCustomLevel' });
mockUserFindUnique.mockResolvedValue({ id: 'user-1', email: 'user@example.com' });
mockLevelFindFirst.mockResolvedValue(null);
const res = await POST({
request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' })
} as POSTEvent);
expect(res.status).toBe(200);
expect(await res.json()).toEqual({
key: storedKey.key,
email_address: 'user@example.com',
subscription_level: { id: null, name: 'SomeCustomLevel', description: null }
});
});
it('rejects a missing license_key', async () => {
await expectHttpError(
POST({ request: licenseRequest({ email_address: 'user@example.com' }) } as POSTEvent),
400,
'license_key is required'
);
});
it('rejects a missing email_address', async () => {
await expectHttpError(
POST({ request: licenseRequest({ license_key: storedKey.key }) } as POSTEvent),
400,
'email_address is required'
);
});
it('rejects an unknown key', async () => {
mockKeyFindFirst.mockResolvedValue(null);
await expectHttpError(
POST({
request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' })
} as POSTEvent),
400,
'license key not found'
);
});
it('rejects an inactive key', async () => {
mockKeyFindFirst.mockResolvedValue({ ...storedKey, active: false });
await expectHttpError(
POST({
request: licenseRequest({ license_key: storedKey.key, email_address: 'user@example.com' })
} as POSTEvent),
400,
'license key is not active'
);
});
it('rejects a nonexistent user', async () => {
mockKeyFindFirst.mockResolvedValue(storedKey);
mockUserFindUnique.mockResolvedValue(null);
await expectHttpError(
POST({
request: licenseRequest({ license_key: storedKey.key, email_address: 'nobody@example.com' })
} as POSTEvent),
400,
'user does not exist'
);
});
it('rejects a key owned by a different user', async () => {
mockKeyFindFirst.mockResolvedValue(storedKey);
mockUserFindUnique.mockResolvedValue({ id: 'user-2', email: 'other@example.com' });
await expectHttpError(
POST({
request: licenseRequest({ license_key: storedKey.key, email_address: 'other@example.com' })
} as POSTEvent),
400,
'key does not belong to specified user'
);
});
it('rejects a malformed license key format', async () => {
await expectHttpError(
POST({
request: licenseRequest({ license_key: 'not-a-key', email_address: 'user@example.com' })
} as POSTEvent),
400,
'license key not found'
);
expect(mockKeyFindFirst).not.toHaveBeenCalled();
});
});