Files
hideyoshi-blog/tests/lib/feature/user/user.service.test.ts

268 lines
7.9 KiB
TypeScript

import { SessionClaims } from '@/lib/feature/user/clerk.model';
import {
CreateUserModel,
UpdateUserModel,
} from '@/lib/feature/user/user.model';
import {
getUserByEmail,
saveUser,
syncUser,
updateUser,
} from '@/lib/feature/user/user.service';
import { clerkClient } from '@clerk/nextjs/server';
import { AbstractStartedContainer } from 'testcontainers';
import { startTestDB } from '~/tests/setup/setup-db';
jest.mock('@clerk/nextjs/server', () => ({
clerkClient: jest.fn(),
}));
describe('UserService', () => {
let container: AbstractStartedContainer;
beforeAll(async () => {
container = await startTestDB();
}, 1_000_000);
afterAll(async () => {
await container.stop();
}, 1_000_000);
test('can save user', async () => {
const userToSave: CreateUserModel = {
name: 'Test User',
email: 'test@email.com',
role: 'user',
};
const result = await saveUser(userToSave);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.id).toBeDefined();
expect(result.value.name).toBe(userToSave.name);
expect(result.value.email).toBe(userToSave.email);
expect(result.value.role).toBe(userToSave.role);
expect(result.value.externalId).toBeDefined();
});
test('cannot save user with existing email', async () => {
const userToSave: CreateUserModel = {
name: 'Test User',
email: 'test@email.com',
role: 'user',
};
const result = await saveUser(userToSave);
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.error.message).toContain(userToSave.email);
});
test('can getUserByEmail', async () => {
const result = await getUserByEmail('test@email.com');
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value?.email).toBe('test@email.com');
expect(result.value?.name).toBe('Test User');
expect(result.value?.role).toBe('user');
expect(result.value?.externalId).toBeDefined();
});
test('cannot getUserByEmail with non-existing email', async () => {
const result = await getUserByEmail('missing@email.com');
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value).toBeNull();
});
test('can update user', async () => {
const dataToUpdate: UpdateUserModel = {
name: 'Updated User',
role: 'admin',
};
const userResult = await getUserByEmail('test@email.com');
expect(userResult.ok).toBe(true);
if (!userResult.ok) return;
const user = userResult.value;
expect(user).toBeDefined();
const result = await updateUser(user!.id, dataToUpdate);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.id).toBe(user!.id);
expect(result.value.name).toBe(dataToUpdate.name);
expect(result.value.role).toBe(dataToUpdate.role);
expect(result.value.email).toBe(user!.email);
expect(result.value.externalId).toBeDefined();
});
test('cannot update non-existing user', async () => {
const dataToUpdate: UpdateUserModel = {
name: 'Updated User',
role: 'admin',
};
const result = await updateUser('9999', dataToUpdate);
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.error.message).toContain('9999');
});
test('can sync admin user', async () => {
process.env.CLERK_ORG_ID = 'test-org-id';
const mockGetOrganizationMembershipList = jest.fn().mockResolvedValue({
data: [
{
organization: {
id: process.env.CLERK_ORG_ID,
},
role: 'org:admin',
},
],
});
(clerkClient as jest.Mock).mockResolvedValue({
users: {
getOrganizationMembershipList:
mockGetOrganizationMembershipList,
},
});
const sessionClaims = {
user: {
full_name: 'Updated Name',
email: 'test@email.com',
username: 'test',
public_metadata: {
role: 'admin',
},
},
} as SessionClaims;
const result = await syncUser(sessionClaims);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.name).toBe('Updated Name');
expect(result.value.email).toBe('test@email.com');
expect(result.value.role).toBe('admin');
});
test('can sync internal user', async () => {
process.env.CLERK_ORG_ID = 'test-org-id';
const mockGetOrganizationMembershipList = jest.fn().mockResolvedValue({
data: [
{
organization: {
id: process.env.CLERK_ORG_ID,
},
role: 'org:member',
},
],
});
(clerkClient as jest.Mock).mockResolvedValue({
users: {
getOrganizationMembershipList:
mockGetOrganizationMembershipList,
},
});
const sessionClaims = {
user: {
full_name: 'Updated Name',
email: 'test@email.com',
username: 'test',
public_metadata: {
role: 'internal',
},
},
} as SessionClaims;
const result = await syncUser(sessionClaims);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.name).toBe('Updated Name');
expect(result.value.email).toBe('test@email.com');
expect(result.value.role).toBe('internal');
});
test('can sync user', async () => {
process.env.CLERK_ORG_ID = 'test-org-id';
const mockGetOrganizationMembershipList = jest.fn().mockResolvedValue({
data: [],
});
(clerkClient as jest.Mock).mockResolvedValue({
users: {
getOrganizationMembershipList:
mockGetOrganizationMembershipList,
},
});
const sessionClaims = {
user: {
full_name: 'Updated Name',
email: 'test@email.com',
username: 'test',
public_metadata: {
role: 'user',
},
},
} as SessionClaims;
const result = await syncUser(sessionClaims);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.name).toBe('Updated Name');
expect(result.value.email).toBe('test@email.com');
expect(result.value.role).toBe('user');
});
test('can sync saving new user', async () => {
process.env.CLERK_ORG_ID = 'test-org-id';
const mockGetOrganizationMembershipList = jest.fn().mockResolvedValue({
data: [],
});
(clerkClient as jest.Mock).mockResolvedValue({
users: {
getOrganizationMembershipList:
mockGetOrganizationMembershipList,
},
});
const sessionClaims = {
user: {
full_name: 'Updated Name',
email: 'new@email.com',
username: 'test',
public_metadata: {
role: 'user',
},
},
} as SessionClaims;
const result = await syncUser(sessionClaims);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.name).toBe('Updated Name');
expect(result.value.email).toBe('new@email.com');
expect(result.value.role).toBe('user');
});
});