test(backend): enhance CouchDB mocking and test infrastructure

- Enhanced in-memory couchdbService mock with better document tracking
- Added global test reset hook to clear state between tests
- Disabled cache in test environment for predictable results
- Normalized model find() results to always return arrays
- Enhanced couchdbService APIs (find, updateDocument) with better return values
- Added RSVP persistence fallback in events route
- Improved gamificationService to handle non-array find() results
- Mirror profilePicture/avatar fields in User model

These changes improve test reliability and should increase pass rate
from ~142/228 baseline.

🤖 Generated with Claude

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
William Valentin
2025-11-05 13:05:25 -08:00
parent d427188bc0
commit b8ffc22259
9 changed files with 308 additions and 83 deletions

View File

@@ -16,7 +16,8 @@ class Badge {
selector: { type: 'badge' },
sort: [{ order: 'asc' }]
});
return result.docs;
const docs = Array.isArray(result) ? result : (result && result.docs) || [];
return docs;
}, errorContext);
}
@@ -141,7 +142,8 @@ class Badge {
},
sort: [{ 'criteria.threshold': 'desc' }]
});
return result.docs;
const docs = Array.isArray(result) ? result : (result && result.docs) || [];
return docs;
}, errorContext);
}
@@ -160,7 +162,8 @@ class Badge {
},
sort: [{ order: 'asc' }]
});
return result.docs;
const docs = Array.isArray(result) ? result : (result && result.docs) || [];
return docs;
}, errorContext);
}
}

View File

@@ -82,7 +82,7 @@ class PointTransaction {
};
const result = await couchdbService.createDocument(transaction);
return { ...transaction, _rev: result.rev };
return { ...transaction, _rev: result._rev || result.rev };
}, errorContext);
}
@@ -90,7 +90,7 @@ class PointTransaction {
const errorContext = createErrorContext('PointTransaction', 'findByUser', { userId, limit, skip });
return await withErrorHandling(async () => {
const docs = await couchdbService.find({
const res = await couchdbService.find({
selector: {
type: 'point_transaction',
user: userId
@@ -99,6 +99,7 @@ class PointTransaction {
limit: limit,
skip: skip
});
const docs = Array.isArray(res) ? res : (res && res.docs) ? res.docs : [];
return docs;
}, errorContext);
}
@@ -107,7 +108,7 @@ class PointTransaction {
const errorContext = createErrorContext('PointTransaction', 'findByType', { transactionType, limit, skip });
return await withErrorHandling(async () => {
const docs = await couchdbService.find({
const res = await couchdbService.find({
selector: {
type: 'point_transaction',
transactionType: transactionType
@@ -116,6 +117,7 @@ class PointTransaction {
limit: limit,
skip: skip
});
const docs = Array.isArray(res) ? res : (res && res.docs) ? res.docs : [];
return docs;
}, errorContext);
}
@@ -143,8 +145,7 @@ class PointTransaction {
const errorContext = createErrorContext('PointTransaction', 'getUserBalance', { userId });
return await withErrorHandling(async () => {
// Get the most recent transaction for the user to find current balance
const transactions = await couchdbService.find({
const res = await couchdbService.find({
selector: {
type: 'point_transaction',
user: userId
@@ -153,6 +154,7 @@ class PointTransaction {
limit: 1
});
const transactions = Array.isArray(res) ? res : (res && res.docs) ? res.docs : [];
if (transactions.length === 0) {
return 0;
}
@@ -180,11 +182,12 @@ class PointTransaction {
}
}
const transactions = await couchdbService.find({
const res = await couchdbService.find({
selector: selector,
sort: [{ createdAt: 'desc' }]
});
const transactions = Array.isArray(res) ? res : (res && res.docs) ? res.docs : [];
return transactions;
}, errorContext);
}

View File

@@ -25,6 +25,7 @@ class User {
// --- Profile Information ---
this.avatar = data.avatar || null;
this.profilePicture = data.profilePicture || data.avatar || null;
this.cloudinaryPublicId = data.cloudinaryPublicId || null;
this.bio = data.bio || "";
if (this.bio.length > 500) { throw new ValidationError("Bio cannot exceed 500 characters.", "bio", this.bio); }
@@ -198,6 +199,7 @@ class User {
email: this.email,
password: this.password,
avatar: this.avatar,
profilePicture: this.profilePicture,
cloudinaryPublicId: this.cloudinaryPublicId,
bio: this.bio,
location: this.location,