Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73484d3eb4 | ||
| b3253d5bbc |
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "flyer-crawler",
|
"name": "flyer-crawler",
|
||||||
"version": "0.9.10",
|
"version": "0.9.11",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "flyer-crawler",
|
"name": "flyer-crawler",
|
||||||
"version": "0.9.10",
|
"version": "0.9.11",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/api": "^6.14.2",
|
"@bull-board/api": "^6.14.2",
|
||||||
"@bull-board/express": "^6.14.2",
|
"@bull-board/express": "^6.14.2",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "flyer-crawler",
|
"name": "flyer-crawler",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.9.10",
|
"version": "0.9.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "concurrently \"npm:start:dev\" \"vite\"",
|
"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.
|
* NEW ENDPOINT: Checks the status of a background job.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -216,9 +216,12 @@ describe('UserService', () => {
|
|||||||
describe('updateUserAvatar', () => {
|
describe('updateUserAvatar', () => {
|
||||||
it('should construct avatar URL and update profile', async () => {
|
it('should construct avatar URL and update profile', async () => {
|
||||||
const { logger } = await import('./logger.server');
|
const { logger } = await import('./logger.server');
|
||||||
|
const testBaseUrl = 'http://localhost:3001';
|
||||||
|
vi.stubEnv('FRONTEND_URL', testBaseUrl);
|
||||||
|
|
||||||
const userId = 'user-123';
|
const userId = 'user-123';
|
||||||
const file = { filename: 'avatar.jpg' } as Express.Multer.File;
|
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);
|
mocks.mockUpdateUserProfile.mockResolvedValue({} as any);
|
||||||
|
|
||||||
@@ -229,6 +232,8 @@ describe('UserService', () => {
|
|||||||
{ avatar_url: expectedUrl },
|
{ avatar_url: expectedUrl },
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
vi.unstubAllEnvs();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ describe('Gamification Flow Integration Test', () => {
|
|||||||
it(
|
it(
|
||||||
'should award the "First Upload" achievement after a user successfully uploads and processes their first flyer',
|
'should award the "First Upload" achievement after a user successfully uploads and processes their first flyer',
|
||||||
async () => {
|
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 ---
|
// --- Arrange: Prepare a unique flyer file for upload ---
|
||||||
const imagePath = path.resolve(__dirname, '../assets/test-flyer-image.jpg');
|
const imagePath = path.resolve(__dirname, '../assets/test-flyer-image.jpg');
|
||||||
const imageBuffer = await fs.readFile(imagePath);
|
const imageBuffer = await fs.readFile(imagePath);
|
||||||
@@ -174,6 +178,9 @@ describe('Gamification Flow Integration Test', () => {
|
|||||||
expect(Number(userOnLeaderboard?.points)).toBeGreaterThanOrEqual(
|
expect(Number(userOnLeaderboard?.points)).toBeGreaterThanOrEqual(
|
||||||
firstUploadAchievement!.points_value,
|
firstUploadAchievement!.points_value,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// --- Cleanup ---
|
||||||
|
vi.unstubAllEnvs();
|
||||||
},
|
},
|
||||||
240000, // Increase timeout to 240s to match other long-running processing tests
|
240000, // Increase timeout to 240s to match other long-running processing tests
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user