Compare commits

...

6 Commits

Author SHA1 Message Date
Gitea Actions
ba67ace190 ci: Bump version to 0.2.18 [skip ci] 2025-12-29 04:33:54 +05:00
Gitea Actions
50782c30e5 ci: Bump version to 0.2.16 [skip ci] 2025-12-29 04:33:54 +05:00
4a2ff8afc5 fix unit tests
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 8m39s
2025-12-28 15:33:22 -08:00
Gitea Actions
7a1c14ce89 ci: Bump version to 0.2.15 [skip ci] 2025-12-29 04:12:16 +05:00
6fafc3d089 test secrets better
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 8m47s
2025-12-28 15:11:46 -08:00
Gitea Actions
4316866bce ci: Bump version to 0.2.14 [skip ci] 2025-12-29 03:54:44 +05:00
6 changed files with 44 additions and 9 deletions

View File

@@ -390,8 +390,15 @@ jobs:
run: |
# Fail-fast check to ensure secrets are configured in Gitea.
if [ -z "$DB_HOST" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ] || [ -z "$DB_NAME" ] || [ -z "$JWT_SECRET" ]; then
echo "ERROR: One or more test secrets (DB_*, JWT_SECRET) are not set in Gitea repository settings."
MISSING_SECRETS=""
if [ -z "$DB_HOST" ]; then MISSING_SECRETS="${MISSING_SECRETS} DB_HOST"; fi
if [ -z "$DB_USER" ]; then MISSING_SECRETS="${MISSING_SECRETS} DB_USER"; fi
if [ -z "$DB_PASSWORD" ]; then MISSING_SECRETS="${MISSING_SECRETS} DB_PASSWORD"; fi
if [ -z "$DB_NAME" ]; then MISSING_SECRETS="${MISSING_SECRETS} DB_NAME"; fi
if [ -z "$JWT_SECRET" ]; then MISSING_SECRETS="${MISSING_SECRETS} JWT_SECRET"; fi
if [ ! -z "$MISSING_SECRETS" ]; then
echo "ERROR: The following required secrets are missing in Gitea:${MISSING_SECRETS}"
exit 1
fi

View File

@@ -11,6 +11,7 @@ if (missingSecrets.length > 0) {
console.warn('\n[ecosystem.config.cjs] ⚠️ WARNING: The following environment variables are MISSING in the shell:');
missingSecrets.forEach(key => console.warn(` - ${key}`));
console.warn('[ecosystem.config.cjs] The application may crash if these are required for startup.\n');
process.exit(1); // Fail fast so PM2 doesn't attempt to start a broken app
} else {
console.log('[ecosystem.config.cjs] ✅ Critical environment variables are present.');
}

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "flyer-crawler",
"version": "0.2.13",
"version": "0.2.18",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "flyer-crawler",
"version": "0.2.13",
"version": "0.2.18",
"dependencies": {
"@bull-board/api": "^6.14.2",
"@bull-board/express": "^6.14.2",

View File

@@ -1,7 +1,7 @@
{
"name": "flyer-crawler",
"private": true,
"version": "0.2.13",
"version": "0.2.18",
"type": "module",
"scripts": {
"dev": "concurrently \"npm:start:dev\" \"vite\"",

View File

@@ -25,8 +25,9 @@ vi.mock('./logger.client', () => ({
// 2. Mock ./apiClient to simply pass calls through to the global fetch.
vi.mock('./apiClient', async (importOriginal) => {
return {
apiFetch: (
// This is the core logic we want to preserve: it calls the global fetch
// which is then intercepted by MSW.
const apiFetch = (
url: string,
options: RequestInit = {},
apiOptions: import('./apiClient').ApiOptions = {},
@@ -60,6 +61,26 @@ vi.mock('./apiClient', async (importOriginal) => {
const request = new Request(fullUrl, options);
console.log(`[apiFetch MOCK] Executing fetch for URL: ${request.url}.`);
return fetch(request);
};
return {
// The original mock only had apiFetch. We need to add the helpers.
apiFetch,
// These helpers are what aiApiClient.ts actually calls.
// Their mock implementation should just call our mocked apiFetch.
authedGet: (endpoint: string, options: import('./apiClient').ApiOptions = {}) => {
return apiFetch(endpoint, { method: 'GET' }, options);
},
authedPost: <T>(endpoint: string, body: T, options: import('./apiClient').ApiOptions = {}) => {
return apiFetch(
endpoint,
{ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) },
options,
);
},
authedPostForm: (endpoint: string, formData: FormData, options: import('./apiClient').ApiOptions = {}) => {
return apiFetch(endpoint, { method: 'POST', body: formData }, options);
},
// Add a mock for ApiOptions to satisfy the compiler
ApiOptions: vi.fn(),

View File

@@ -284,10 +284,12 @@ describe('FlyerProcessingService', () => {
await expect(service.processJob(job)).rejects.toThrow(conversionError);
expect(job.updateProgress).toHaveBeenCalledWith({
// Use `toHaveBeenLastCalledWith` to check only the final error payload, ignoring earlier progress updates.
expect(job.updateProgress).toHaveBeenLastCalledWith({
errorCode: 'PDF_CONVERSION_FAILED',
message:
'The uploaded PDF could not be processed. It might be blank, corrupt, or password-protected.', // This was a duplicate, fixed.
stderr: 'pdftocairo error',
});
expect(mockCleanupQueue.add).not.toHaveBeenCalled();
expect(logger.warn).toHaveBeenCalledWith(
@@ -308,10 +310,14 @@ describe('FlyerProcessingService', () => {
{ err: validationError, validationErrors: {}, rawData: {} },
'AI Data Validation failed.',
);
expect(job.updateProgress).toHaveBeenCalledWith({
// Use `toHaveBeenLastCalledWith` to check only the final error payload.
// The payload from AiDataValidationError includes validationErrors and rawData.
expect(job.updateProgress).toHaveBeenLastCalledWith({
errorCode: 'AI_VALIDATION_FAILED',
message:
"The AI couldn't read the flyer's format. Please try a clearer image or a different flyer.", // This was a duplicate, fixed.
validationErrors: {},
rawData: {},
});
expect(mockCleanupQueue.add).not.toHaveBeenCalled();
expect(logger.warn).toHaveBeenCalledWith(