144 lines
5.0 KiB
TypeScript
144 lines
5.0 KiB
TypeScript
// src/tests/integration/user.routes.integration.test.ts
|
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
import supertest from 'supertest';
|
|
import app from '../../../server';
|
|
import { getPool } from '../../services/db/connection.db';
|
|
import type { UserProfile } from '../../types';
|
|
import { createAndLoginUser } from '../utils/testHelpers';
|
|
|
|
/**
|
|
* @vitest-environment node
|
|
*/
|
|
|
|
const request = supertest(app);
|
|
|
|
let authToken = '';
|
|
let createdListId: number;
|
|
let testUser: UserProfile;
|
|
|
|
describe('User Routes Integration Tests (/api/users)', () => {
|
|
// Authenticate once before all tests in this suite to get a JWT.
|
|
beforeAll(async () => {
|
|
// Use the helper to create and log in a user in one step.
|
|
const { user, token } = await createAndLoginUser({
|
|
fullName: 'User Routes Test User',
|
|
});
|
|
testUser = user;
|
|
authToken = token;
|
|
});
|
|
|
|
afterAll(async () => {
|
|
if (testUser) {
|
|
// Clean up the created user from the database
|
|
await getPool().query('DELETE FROM public.users WHERE user_id = $1', [testUser.user.user_id]);
|
|
}
|
|
});
|
|
|
|
describe('GET /api/users/profile', () => {
|
|
it('should return the profile for the authenticated user', async () => {
|
|
const response = await request
|
|
.get('/api/users/profile')
|
|
.set('Authorization', `Bearer ${authToken}`);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body).toBeDefined();
|
|
expect(response.body.user.email).toBe(testUser.user.email);
|
|
expect(response.body.role).toBe('user');
|
|
});
|
|
|
|
it('should return 401 Unauthorized if no token is provided', async () => {
|
|
const response = await request.get('/api/users/profile');
|
|
expect(response.status).toBe(401);
|
|
});
|
|
});
|
|
|
|
describe('PUT /api/users/profile', () => {
|
|
it('should update the user profile', async () => {
|
|
const newName = `Test User ${Date.now()}`;
|
|
const response = await request
|
|
.put('/api/users/profile')
|
|
.set('Authorization', `Bearer ${authToken}`)
|
|
.send({ full_name: newName });
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.full_name).toBe(newName);
|
|
|
|
// Verify the change by fetching the profile again
|
|
const verifyResponse = await request
|
|
.get('/api/users/profile')
|
|
.set('Authorization', `Bearer ${authToken}`);
|
|
|
|
expect(verifyResponse.body.full_name).toBe(newName);
|
|
});
|
|
});
|
|
|
|
describe('Shopping List CRUD', () => {
|
|
it('POST /api/users/shopping-lists should create a new shopping list', async () => {
|
|
const listName = `My Integration Test List ${Date.now()}`;
|
|
const response = await request
|
|
.post('/api/users/shopping-lists')
|
|
.set('Authorization', `Bearer ${authToken}`)
|
|
.send({ name: listName });
|
|
|
|
expect(response.status).toBe(201);
|
|
expect(response.body.name).toBe(listName);
|
|
expect(response.body.shopping_list_id).toBeDefined();
|
|
createdListId = response.body.shopping_list_id; // Save for the next test
|
|
});
|
|
|
|
it('GET /api/users/shopping-lists should retrieve the created shopping list', async () => {
|
|
const response = await request
|
|
.get('/api/users/shopping-lists')
|
|
.set('Authorization', `Bearer ${authToken}`);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(Array.isArray(response.body)).toBe(true);
|
|
const foundList = response.body.find(
|
|
(list: { shopping_list_id: number }) => list.shopping_list_id === createdListId,
|
|
);
|
|
expect(foundList).toBeDefined();
|
|
});
|
|
|
|
it('DELETE /api/users/shopping-lists/:listId should delete the shopping list', async () => {
|
|
expect(createdListId).toBeDefined(); // Ensure the previous test ran and set the ID
|
|
|
|
const response = await request
|
|
.delete(`/api/users/shopping-lists/${createdListId}`)
|
|
.set('Authorization', `Bearer ${authToken}`);
|
|
|
|
expect(response.status).toBe(204);
|
|
|
|
// Verify deletion
|
|
const verifyResponse = await request
|
|
.get('/api/users/shopping-lists')
|
|
.set('Authorization', `Bearer ${authToken}`);
|
|
|
|
const foundList = verifyResponse.body.find(
|
|
(list: { shopping_list_id: number }) => list.shopping_list_id === createdListId,
|
|
);
|
|
expect(foundList).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('PUT /api/users/profile/preferences', () => {
|
|
it('should update user preferences', async () => {
|
|
const preferences = { darkMode: true, unitSystem: 'metric' };
|
|
const response = await request
|
|
.put('/api/users/profile/preferences')
|
|
.set('Authorization', `Bearer ${authToken}`)
|
|
.send(preferences);
|
|
|
|
expect(response.status).toBe(200);
|
|
expect(response.body.preferences).toEqual(preferences);
|
|
|
|
// Verify the change by fetching the profile again
|
|
const verifyResponse = await request
|
|
.get('/api/users/profile')
|
|
.set('Authorization', `Bearer ${authToken}`);
|
|
|
|
expect(verifyResponse.body.preferences?.darkMode).toBe(true);
|
|
expect(verifyResponse.body.preferences?.unitSystem).toBe('metric');
|
|
});
|
|
});
|
|
});
|