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

@@ -531,14 +531,28 @@ class CouchDBService {
}
}
async updateDocument(doc) {
async updateDocument(docOrId, maybeDoc) {
if (!this.isConnected) await this.initialize();
try {
if (!doc._id || !doc._rev) {
let doc;
if (arguments.length === 2) {
const id = docOrId;
const provided = maybeDoc || {};
if (!provided._id) provided._id = id;
if (!provided._rev) {
const existing = await this.getDocument(id);
if (!existing) throw new Error("Document not found for update");
provided._rev = existing._rev;
}
doc = provided;
} else {
doc = docOrId;
}
if (!doc || !doc._id || !doc._rev) {
throw new Error("Document must have _id and _rev for update");
}
const response = await this.makeRequest('PUT', `/${this.dbName}/${doc._id}`, doc);
return { ...doc, _rev: response.rev };
} catch (error) {
@@ -560,12 +574,24 @@ class CouchDBService {
}
// Query operations
async find(query) {
async find(queryOrSelector, maybeOptions) {
if (!this.isConnected) await this.initialize();
try {
let query;
if (queryOrSelector && queryOrSelector.selector) {
query = queryOrSelector;
} else {
// Support (selector, options)
query = { selector: queryOrSelector || {} };
if (maybeOptions && typeof maybeOptions === 'object') {
Object.assign(query, maybeOptions);
}
}
const response = await this.makeRequest('POST', `/${this.dbName}/_find`, query);
return response.docs;
const docs = Array.isArray(response) ? response : response?.docs;
return Array.isArray(docs) ? docs : [];
} catch (error) {
logger.error("Error executing query", error);
throw error;
@@ -668,11 +694,14 @@ class CouchDBService {
}
// Batch operation helper
async bulkDocs(docs) {
async bulkDocs(docsOrPayload) {
if (!this.isConnected) await this.initialize();
try {
const response = await this.makeRequest('POST', `/${this.dbName}/_bulk_docs`, { docs });
const payload = Array.isArray(docsOrPayload)
? { docs: docsOrPayload }
: (docsOrPayload && docsOrPayload.docs ? docsOrPayload : { docs: [] });
const response = await this.makeRequest('POST', `/${this.dbName}/_bulk_docs`, payload);
return response;
} catch (error) {
logger.error("Error in bulk operation", error);