Initial Upload
Some checks failed
CI / Lint & Typecheck (push) Has been cancelled
CI / Test (routes) (push) Has been cancelled
CI / Test (security) (push) Has been cancelled
CI / Test (services) (push) Has been cancelled
CI / Test (unit) (push) Has been cancelled
CI / Test (integration) (push) Has been cancelled
CI / Test Coverage (push) Has been cancelled
CI / Build (push) Has been cancelled

This commit is contained in:
2025-12-17 12:32:50 +13:00
commit 3015f48118
471 changed files with 141143 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
/**
* User Service Integration Tests
*
* Tests userService functions against a real database.
* Uses global integration test setup for database management.
*
* Run with: pnpm test:integration
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { randomUUID } from 'node:crypto';
import { db } from '../../src/db/client.js';
import { servers } from '../../src/db/schema.js';
import {
batchSyncUsersFromMediaServer,
syncUserFromMediaServer,
getServerUsersByServer,
getServerUserByExternalId,
} from '../../src/services/userService.js';
import type { MediaUser } from '../../src/services/userService.js';
describe('userService integration tests', () => {
let testServerId: string;
// Create a fresh server before each test (after global reset)
beforeEach(async () => {
const [server] = await db
.insert(servers)
.values({
name: 'Integration Test Server',
type: 'plex',
url: 'http://localhost:32400',
token: 'encrypted-test-token',
})
.returning();
testServerId = server.id;
});
describe('syncUserFromMediaServer', () => {
it('should create a new user and server user when none exists', async () => {
const mediaUser: MediaUser = {
id: `ext-${randomUUID().slice(0, 8)}`,
username: 'newuser',
email: 'newuser@example.com',
thumb: 'https://example.com/thumb.jpg',
isAdmin: false,
};
const result = await syncUserFromMediaServer(testServerId, mediaUser);
expect(result.created).toBe(true);
expect(result.serverUser.externalId).toBe(mediaUser.id);
expect(result.serverUser.username).toBe(mediaUser.username);
expect(result.user.username).toBe(mediaUser.username);
// Verify in database
const dbServerUser = await getServerUserByExternalId(testServerId, mediaUser.id);
expect(dbServerUser).not.toBeNull();
expect(dbServerUser?.username).toBe(mediaUser.username);
});
it('should update existing server user when already exists', async () => {
const externalId = `ext-${randomUUID().slice(0, 8)}`;
const mediaUser: MediaUser = {
id: externalId,
username: 'originalname',
isAdmin: false,
};
// First create
const createResult = await syncUserFromMediaServer(testServerId, mediaUser);
expect(createResult.created).toBe(true);
// Then update with new username
const updatedMediaUser: MediaUser = {
id: externalId,
username: 'updatedname',
email: 'updated@example.com',
isAdmin: true,
};
const updateResult = await syncUserFromMediaServer(testServerId, updatedMediaUser);
expect(updateResult.created).toBe(false);
expect(updateResult.serverUser.username).toBe('updatedname');
});
});
describe('batchSyncUsersFromMediaServer', () => {
it('should return zeros for empty input', async () => {
const result = await batchSyncUsersFromMediaServer(testServerId, []);
expect(result.added).toBe(0);
expect(result.updated).toBe(0);
});
it('should create multiple new users', async () => {
const mediaUsers: MediaUser[] = [
{ id: `batch-1-${randomUUID().slice(0, 8)}`, username: 'batchuser1', isAdmin: false },
{ id: `batch-2-${randomUUID().slice(0, 8)}`, username: 'batchuser2', isAdmin: false },
{ id: `batch-3-${randomUUID().slice(0, 8)}`, username: 'batchuser3', isAdmin: true },
];
const result = await batchSyncUsersFromMediaServer(testServerId, mediaUsers);
expect(result.added).toBe(3);
expect(result.updated).toBe(0);
// Verify all users exist in database
const serverUsersMap = await getServerUsersByServer(testServerId);
expect(serverUsersMap.size).toBe(3);
expect(serverUsersMap.get(mediaUsers[0].id)?.username).toBe('batchuser1');
expect(serverUsersMap.get(mediaUsers[1].id)?.username).toBe('batchuser2');
expect(serverUsersMap.get(mediaUsers[2].id)?.username).toBe('batchuser3');
});
it('should handle mix of new and existing users', async () => {
// Create one user first
const existingExternalId = `existing-${randomUUID().slice(0, 8)}`;
await syncUserFromMediaServer(testServerId, {
id: existingExternalId,
username: 'existinguser',
isAdmin: false,
});
// Now batch sync with mix of existing and new
const mediaUsers: MediaUser[] = [
{ id: existingExternalId, username: 'existinguser-updated', isAdmin: false },
{ id: `new-1-${randomUUID().slice(0, 8)}`, username: 'newuser1', isAdmin: false },
{ id: `new-2-${randomUUID().slice(0, 8)}`, username: 'newuser2', isAdmin: false },
];
const result = await batchSyncUsersFromMediaServer(testServerId, mediaUsers);
expect(result.added).toBe(2);
expect(result.updated).toBe(1);
// Verify the existing user was updated
const updatedUser = await getServerUserByExternalId(testServerId, existingExternalId);
expect(updatedUser?.username).toBe('existinguser-updated');
});
it('should handle all existing users (update only)', async () => {
// Create users first
const externalIds = [
`preexist-1-${randomUUID().slice(0, 8)}`,
`preexist-2-${randomUUID().slice(0, 8)}`,
];
for (const extId of externalIds) {
await syncUserFromMediaServer(testServerId, {
id: extId,
username: `user-${extId.slice(0, 8)}`,
isAdmin: false,
});
}
// Batch sync with updates only
const mediaUsers: MediaUser[] = externalIds.map((extId) => ({
id: extId,
username: `updated-${extId.slice(0, 8)}`,
isAdmin: true,
}));
const result = await batchSyncUsersFromMediaServer(testServerId, mediaUsers);
expect(result.added).toBe(0);
expect(result.updated).toBe(2);
});
});
describe('getServerUsersByServer', () => {
it('should return empty map for server with no users', async () => {
const result = await getServerUsersByServer(testServerId);
expect(result.size).toBe(0);
});
it('should return map of all server users keyed by externalId', async () => {
// Create some users
const mediaUsers: MediaUser[] = [
{ id: `map-1-${randomUUID().slice(0, 8)}`, username: 'mapuser1', isAdmin: false },
{ id: `map-2-${randomUUID().slice(0, 8)}`, username: 'mapuser2', isAdmin: true },
];
await batchSyncUsersFromMediaServer(testServerId, mediaUsers);
const result = await getServerUsersByServer(testServerId);
expect(result.size).toBe(2);
expect(result.has(mediaUsers[0].id)).toBe(true);
expect(result.has(mediaUsers[1].id)).toBe(true);
expect(result.get(mediaUsers[0].id)?.username).toBe('mapuser1');
expect(result.get(mediaUsers[1].id)?.isServerAdmin).toBe(true);
});
});
});