Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73484d3eb4 | ||
| b3253d5bbc | |||
|
|
54f3769e90 | ||
| bad6f74ee6 |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "flyer-crawler",
|
||||
"version": "0.9.9",
|
||||
"version": "0.9.11",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "flyer-crawler",
|
||||
"version": "0.9.9",
|
||||
"version": "0.9.11",
|
||||
"dependencies": {
|
||||
"@bull-board/api": "^6.14.2",
|
||||
"@bull-board/express": "^6.14.2",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "flyer-crawler",
|
||||
"private": true,
|
||||
"version": "0.9.9",
|
||||
"version": "0.9.11",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "concurrently \"npm:start:dev\" \"vite\"",
|
||||
|
||||
@@ -208,6 +208,34 @@ router.post(
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /api/ai/upload-legacy - Process a flyer upload from a legacy client.
|
||||
* This is an authenticated route that processes the flyer synchronously.
|
||||
* This is used for integration testing the legacy upload flow.
|
||||
*/
|
||||
router.post(
|
||||
'/upload-legacy',
|
||||
passport.authenticate('jwt', { session: false }),
|
||||
uploadToDisk.single('flyerFile'),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
if (!req.file) {
|
||||
return res.status(400).json({ message: 'No flyer file uploaded.' });
|
||||
}
|
||||
const userProfile = req.user as UserProfile;
|
||||
const newFlyer = await aiService.processLegacyFlyerUpload(req.file, req.body, userProfile, req.log);
|
||||
res.status(200).json(newFlyer);
|
||||
} catch (error) {
|
||||
await cleanupUploadedFile(req.file);
|
||||
if (error instanceof DuplicateFlyerError) {
|
||||
logger.warn(`Duplicate legacy flyer upload attempt blocked.`);
|
||||
return res.status(409).json({ message: error.message, flyerId: error.flyerId });
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* NEW ENDPOINT: Checks the status of a background job.
|
||||
*/
|
||||
|
||||
@@ -1136,7 +1136,7 @@ describe('AI Service (Server)', () => {
|
||||
expect(dbModule.adminRepo.logActivity).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
action: 'flyer_processed',
|
||||
userId: 'u1',
|
||||
userId: mockProfile.user.user_id,
|
||||
}),
|
||||
mockLoggerInstance,
|
||||
);
|
||||
|
||||
@@ -7,6 +7,10 @@ import { ValidationError, NotFoundError } from './db/errors.db';
|
||||
import type { Job } from 'bullmq';
|
||||
import type { TokenCleanupJobData } from '../types/job-data';
|
||||
|
||||
// Un-mock the service under test to ensure we are testing the real implementation,
|
||||
// not the global mock from `tests/setup/tests-setup-unit.ts`.
|
||||
vi.unmock('./userService');
|
||||
|
||||
// --- Hoisted Mocks ---
|
||||
const mocks = vi.hoisted(() => {
|
||||
// Create mock implementations for the repository methods we'll be using.
|
||||
@@ -212,9 +216,12 @@ describe('UserService', () => {
|
||||
describe('updateUserAvatar', () => {
|
||||
it('should construct avatar URL and update profile', async () => {
|
||||
const { logger } = await import('./logger.server');
|
||||
const testBaseUrl = 'http://localhost:3001';
|
||||
vi.stubEnv('FRONTEND_URL', testBaseUrl);
|
||||
|
||||
const userId = 'user-123';
|
||||
const file = { filename: 'avatar.jpg' } as Express.Multer.File;
|
||||
const expectedUrl = '/uploads/avatars/avatar.jpg';
|
||||
const expectedUrl = `${testBaseUrl}/uploads/avatars/avatar.jpg`;
|
||||
|
||||
mocks.mockUpdateUserProfile.mockResolvedValue({} as any);
|
||||
|
||||
@@ -225,6 +232,8 @@ describe('UserService', () => {
|
||||
{ avatar_url: expectedUrl },
|
||||
logger,
|
||||
);
|
||||
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -88,6 +88,10 @@ describe('Gamification Flow Integration Test', () => {
|
||||
it(
|
||||
'should award the "First Upload" achievement after a user successfully uploads and processes their first flyer',
|
||||
async () => {
|
||||
// --- Arrange: Stub environment variables for URL generation in the background worker ---
|
||||
const testBaseUrl = 'http://localhost:3001'; // Use a fixed port for predictability
|
||||
vi.stubEnv('FRONTEND_URL', testBaseUrl);
|
||||
|
||||
// --- Arrange: Prepare a unique flyer file for upload ---
|
||||
const imagePath = path.resolve(__dirname, '../assets/test-flyer-image.jpg');
|
||||
const imageBuffer = await fs.readFile(imagePath);
|
||||
@@ -174,6 +178,9 @@ describe('Gamification Flow Integration Test', () => {
|
||||
expect(Number(userOnLeaderboard?.points)).toBeGreaterThanOrEqual(
|
||||
firstUploadAchievement!.points_value,
|
||||
);
|
||||
|
||||
// --- Cleanup ---
|
||||
vi.unstubAllEnvs();
|
||||
},
|
||||
240000, // Increase timeout to 240s to match other long-running processing tests
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user