diff --git a/src/services/flyerDataTransformer.test.ts b/src/services/flyerDataTransformer.test.ts index 39821106..00fc5c00 100644 --- a/src/services/flyerDataTransformer.test.ts +++ b/src/services/flyerDataTransformer.test.ts @@ -21,6 +21,11 @@ describe('FlyerDataTransformer', () => { beforeEach(() => { vi.clearAllMocks(); transformer = new FlyerDataTransformer(); + // Stub environment variables to ensure consistency and predictability. + // Prioritize FRONTEND_URL to match the updated service logic. + vi.stubEnv('FRONTEND_URL', 'http://localhost:3000'); + vi.stubEnv('BASE_URL', ''); // Ensure this is not used to confirm priority logic + vi.stubEnv('PORT', ''); // Ensure this is not used // Provide a default mock implementation for generateFlyerIcon vi.mocked(generateFlyerIcon).mockResolvedValue('icon-flyer-page-1.webp'); @@ -70,6 +75,9 @@ describe('FlyerDataTransformer', () => { mockLogger, ); + // Dynamically construct the expected base URL, mirroring the logic in the transformer. + const expectedBaseUrl = `http://localhost:3000`; + // Assert // 0. Check logging expect(mockLogger.info).toHaveBeenCalledWith( @@ -83,8 +91,8 @@ describe('FlyerDataTransformer', () => { // 1. Check flyer data expect(flyerData).toEqual({ file_name: originalFileName, - image_url: `http://localhost:3000/flyer-images/flyer-page-1.jpg`, - icon_url: `http://localhost:3000/flyer-images/icons/icon-flyer-page-1.webp`, + image_url: `${expectedBaseUrl}/flyer-images/flyer-page-1.jpg`, + icon_url: `${expectedBaseUrl}/flyer-images/icons/icon-flyer-page-1.webp`, checksum, store_name: 'Test Store', valid_from: '2024-01-01', @@ -151,6 +159,9 @@ describe('FlyerDataTransformer', () => { mockLogger, ); + // Dynamically construct the expected base URL, mirroring the logic in the transformer. + const expectedBaseUrl = `http://localhost:3000`; + // Assert // 0. Check logging expect(mockLogger.info).toHaveBeenCalledWith( @@ -167,8 +178,8 @@ describe('FlyerDataTransformer', () => { expect(itemsForDb).toHaveLength(0); expect(flyerData).toEqual({ file_name: originalFileName, - image_url: `http://localhost:3000/flyer-images/another.png`, - icon_url: `http://localhost:3000/flyer-images/icons/icon-another.webp`, + image_url: `${expectedBaseUrl}/flyer-images/another.png`, + icon_url: `${expectedBaseUrl}/flyer-images/icons/icon-another.webp`, checksum, store_name: 'Unknown Store (auto)', // Should use fallback valid_from: null, diff --git a/src/services/flyerDataTransformer.ts b/src/services/flyerDataTransformer.ts index cfa0a3a1..f3feec59 100644 --- a/src/services/flyerDataTransformer.ts +++ b/src/services/flyerDataTransformer.ts @@ -76,7 +76,7 @@ export class FlyerDataTransformer { } // Construct proper URLs including protocol and host to satisfy DB constraints - const rawBaseUrl = process.env.BASE_URL || `http://localhost:${process.env.PORT || 3000}`; + const rawBaseUrl = process.env.FRONTEND_URL || process.env.BASE_URL || `http://localhost:${process.env.PORT || 3000}`; // Normalize base URL by removing any trailing slash to prevent double slashes in the final URL, // and replace the strict `new URL()` constructor to prevent exceptions in test environments. const baseUrl = rawBaseUrl.endsWith('/') ? rawBaseUrl.slice(0, -1) : rawBaseUrl; @@ -91,7 +91,10 @@ export class FlyerDataTransformer { valid_to: extractedData.valid_to, store_address: extractedData.store_address, // The number of items is now calculated directly from the transformed data. item_count: itemsForDb.length, - uploaded_by: userId, + // Defensively handle the userId. An empty string ('') is not a valid UUID, + // but `null` is. This ensures that any falsy value for userId (undefined, null, '') + // is converted to `null` for the database, preventing a 22P02 error. + uploaded_by: userId || null, status: needsReview ? 'needs_review' : 'processed', }; diff --git a/src/tests/integration/gamification.integration.test.ts b/src/tests/integration/gamification.integration.test.ts index 1af3c4e7..b01bf27f 100644 --- a/src/tests/integration/gamification.integration.test.ts +++ b/src/tests/integration/gamification.integration.test.ts @@ -162,6 +162,6 @@ describe('Gamification Flow Integration Test', () => { firstUploadAchievement!.points_value, ); }, - 120000, // Increase timeout to 120 seconds for this long-running test + 240000, // Increase timeout to 240s to match other long-running processing tests ); }); \ No newline at end of file