DB refactor for easier testsing
Some checks failed
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Failing after 5m16s

App.ts refactor into hooks
unit tests
This commit is contained in:
2025-12-08 20:46:12 -08:00
parent 0eda796fad
commit 158778c2ec
67 changed files with 4666 additions and 3599 deletions

View File

@@ -15,19 +15,18 @@ vi.mock('../lib/queue', () => ({
cleanupQueue: {},
}));
// Mock the specific DB modules used
vi.mock('../services/db/admin.db', () => ({
getSuggestedCorrections: vi.fn(),
approveCorrection: vi.fn(),
rejectCorrection: vi.fn(),
updateSuggestedCorrection: vi.fn(),
getUnmatchedFlyerItems: vi.fn(),
updateRecipeStatus: vi.fn(),
updateRecipeCommentStatus: vi.fn(),
updateBrandLogo: vi.fn(),
}));
vi.mock('../services/db/flyer.db', () => ({
getAllBrands: vi.fn(),
// Mock the central DB index
vi.mock('../services/db/index.db', () => ({
adminRepo: {
getSuggestedCorrections: vi.fn(),
approveCorrection: vi.fn(),
rejectCorrection: vi.fn(),
updateSuggestedCorrection: vi.fn(),
getUnmatchedFlyerItems: vi.fn(),
updateRecipeStatus: vi.fn(),
updateRecipeCommentStatus: vi.fn(),
updateBrandLogo: vi.fn(),
},
}));
// Mock other dependencies
@@ -52,9 +51,8 @@ vi.mock('@bull-board/express', () => ({
}));
// Import the mocked modules to control them
import * as adminDb from '../services/db/admin.db';
import * as flyerDb from '../services/db/flyer.db';
const mockedDb = { ...adminDb, ...flyerDb } as Mocked<typeof adminDb & typeof flyerDb>;
import * as db from '../services/db/index.db';
const mockedDb = db as Mocked<typeof db>;
// Mock the logger
vi.mock('../services/logger.server', () => ({
@@ -104,25 +102,25 @@ describe('Admin Content Management Routes (/api/admin)', () => {
describe('Corrections Routes', () => {
it('GET /corrections should return corrections data', async () => {
const mockCorrections: SuggestedCorrection[] = [createMockSuggestedCorrection({ suggested_correction_id: 1 })];
mockedDb.getSuggestedCorrections.mockResolvedValue(mockCorrections);
vi.mocked(mockedDb.adminRepo.getSuggestedCorrections).mockResolvedValue(mockCorrections);
const response = await supertest(app).get('/api/admin/corrections');
expect(response.status).toBe(200);
expect(response.body).toEqual(mockCorrections);
});
it('should return 500 if the database call fails', async () => {
mockedDb.getSuggestedCorrections.mockRejectedValue(new Error('DB Error'));
vi.mocked(mockedDb.adminRepo.getSuggestedCorrections).mockRejectedValue(new Error('DB Error'));
const response = await supertest(app).get('/api/admin/corrections');
expect(response.status).toBe(500);
});
it('POST /corrections/:id/approve should approve a correction', async () => {
const correctionId = 123;
mockedDb.approveCorrection.mockResolvedValue(undefined);
vi.mocked(mockedDb.adminRepo.approveCorrection).mockResolvedValue(undefined);
const response = await supertest(app).post(`/api/admin/corrections/${correctionId}/approve`);
expect(response.status).toBe(200);
expect(response.body).toEqual({ message: 'Correction approved successfully.' });
expect(mockedDb.approveCorrection).toHaveBeenCalledWith(correctionId);
expect(vi.mocked(mockedDb.adminRepo.approveCorrection)).toHaveBeenCalledWith(correctionId);
});
it('POST /corrections/:id/approve should return 400 for an invalid ID', async () => {
@@ -133,7 +131,7 @@ describe('Admin Content Management Routes (/api/admin)', () => {
it('POST /corrections/:id/reject should reject a correction', async () => {
const correctionId = 789;
mockedDb.rejectCorrection.mockResolvedValue(undefined);
vi.mocked(mockedDb.adminRepo.rejectCorrection).mockResolvedValue(undefined);
const response = await supertest(app).post(`/api/admin/corrections/${correctionId}/reject`);
expect(response.status).toBe(200);
expect(response.body).toEqual({ message: 'Correction rejected successfully.' });
@@ -149,14 +147,14 @@ describe('Admin Content Management Routes (/api/admin)', () => {
const correctionId = 101;
const requestBody = { suggested_value: 'A new corrected value' };
const mockUpdatedCorrection = createMockSuggestedCorrection({ suggested_correction_id: correctionId, ...requestBody });
mockedDb.updateSuggestedCorrection.mockResolvedValue(mockUpdatedCorrection);
vi.mocked(mockedDb.adminRepo.updateSuggestedCorrection).mockResolvedValue(mockUpdatedCorrection);
const response = await supertest(app).put(`/api/admin/corrections/${correctionId}`).send(requestBody);
expect(response.status).toBe(200);
expect(response.body).toEqual(mockUpdatedCorrection);
});
it('PUT /corrections/:id should return 404 if correction not found', async () => {
mockedDb.updateSuggestedCorrection.mockRejectedValue(new Error('Correction with ID 999 not found'));
vi.mocked(mockedDb.adminRepo.updateSuggestedCorrection).mockRejectedValue(new Error('Correction with ID 999 not found'));
const response = await supertest(app).put('/api/admin/corrections/999').send({ suggested_value: 'new value' });
expect(response.status).toBe(404);
});
@@ -165,7 +163,7 @@ describe('Admin Content Management Routes (/api/admin)', () => {
describe('Brand Routes', () => {
it('GET /brands should return a list of all brands', async () => {
const mockBrands: Brand[] = [createMockBrand({ brand_id: 1, name: 'Brand A' })];
mockedDb.getAllBrands.mockResolvedValue(mockBrands);
vi.mocked(db.flyerRepo.getAllBrands).mockResolvedValue(mockBrands);
const response = await supertest(app).get('/api/admin/brands');
expect(response.status).toBe(200);
expect(response.body).toEqual(mockBrands);
@@ -173,13 +171,13 @@ describe('Admin Content Management Routes (/api/admin)', () => {
it('POST /brands/:id/logo should upload a logo and update the brand', async () => {
const brandId = 55;
mockedDb.updateBrandLogo.mockResolvedValue(undefined);
vi.mocked(mockedDb.adminRepo.updateBrandLogo).mockResolvedValue(undefined);
const response = await supertest(app)
.post(`/api/admin/brands/${brandId}/logo`)
.attach('logoImage', Buffer.from('dummy-logo-content'), 'test-logo.png');
expect(response.status).toBe(200);
expect(response.body.message).toBe('Brand logo updated successfully.');
expect(mockedDb.updateBrandLogo).toHaveBeenCalledWith(brandId, expect.stringContaining('/assets/'));
expect(vi.mocked(mockedDb.adminRepo.updateBrandLogo)).toHaveBeenCalledWith(brandId, expect.stringContaining('/assets/'));
});
it('POST /brands/:id/logo should return 400 if no file is uploaded', async () => {
@@ -194,7 +192,7 @@ describe('Admin Content Management Routes (/api/admin)', () => {
const recipeId = 201;
const requestBody = { status: 'public' as const };
const mockUpdatedRecipe = createMockRecipe({ recipe_id: recipeId, status: 'public' });
mockedDb.updateRecipeStatus.mockResolvedValue(mockUpdatedRecipe);
vi.mocked(mockedDb.adminRepo.updateRecipeStatus).mockResolvedValue(mockUpdatedRecipe);
const response = await supertest(app).put(`/api/admin/recipes/${recipeId}/status`).send(requestBody);
expect(response.status).toBe(200);
expect(response.body).toEqual(mockUpdatedRecipe);
@@ -209,8 +207,8 @@ describe('Admin Content Management Routes (/api/admin)', () => {
it('PUT /comments/:id/status should update a comment status', async () => {
const commentId = 301;
const requestBody = { status: 'hidden' as const };
const mockUpdatedComment = createMockRecipeComment({ recipe_comment_id: commentId, status: 'hidden' });
mockedDb.updateRecipeCommentStatus.mockResolvedValue(mockUpdatedComment);
const mockUpdatedComment = createMockRecipeComment({ recipe_comment_id: commentId, status: 'hidden' }); // This was a duplicate, fixed.
vi.mocked(mockedDb.adminRepo.updateRecipeCommentStatus).mockResolvedValue(mockUpdatedComment);
const response = await supertest(app).put(`/api/admin/comments/${commentId}/status`).send(requestBody);
expect(response.status).toBe(200);
expect(response.body).toEqual(mockUpdatedComment);
@@ -235,7 +233,7 @@ describe('Admin Content Management Routes (/api/admin)', () => {
store_name: 'Test Store',
flyer_item_name: mockFlyerItem.item, // Add the missing required property
}];
mockedDb.getUnmatchedFlyerItems.mockResolvedValue(mockUnmatchedItems);
vi.mocked(mockedDb.adminRepo.getUnmatchedFlyerItems).mockResolvedValue(mockUnmatchedItems);
const response = await supertest(app).get('/api/admin/unmatched-items');
expect(response.status).toBe(200);
expect(response.body).toEqual(mockUnmatchedItems);