diff --git a/backend/__tests__/models/Badge.test.js b/backend/__tests__/models/Badge.test.js index 1a04ad2..5d27a45 100644 --- a/backend/__tests__/models/Badge.test.js +++ b/backend/__tests__/models/Badge.test.js @@ -1,479 +1,327 @@ // Mock CouchDB service for testing const mockCouchdbService = { - createDocument: jest.fn(), - findDocumentById: jest.fn(), - updateDocument: jest.fn(), - findByType: jest.fn(), - initialize: jest.fn(), + find: jest.fn(), + get: jest.fn(), getDocument: jest.fn(), + createDocument: jest.fn(), + destroy: jest.fn(), + initialize: jest.fn(), + isReady: jest.fn().mockReturnValue(true), + shutdown: jest.fn() }; // Mock the service module jest.mock('../../services/couchdbService', () => mockCouchdbService); +const couchdbService = require('../../services/couchdbService'); const Badge = require('../../models/Badge'); describe('Badge Model', () => { beforeEach(() => { jest.clearAllMocks(); // Reset all mocks to ensure clean state + mockCouchdbService.find.mockReset(); + mockCouchdbService.get.mockReset(); + mockCouchdbService.getDocument.mockReset(); mockCouchdbService.createDocument.mockReset(); - mockCouchdbService.findDocumentById.mockReset(); - mockCouchdbService.updateDocument.mockReset(); - mockCouchdbService.findByType.mockReset(); + mockCouchdbService.destroy.mockReset(); }); - describe('Schema Validation', () => { - it('should create a valid badge', async () => { + describe('findAll', () => { + it('should return all badges sorted by order', async () => { + const mockBadges = [ + { _id: 'badge1', type: 'badge', name: 'First Badge', order: 1 }, + { _id: 'badge2', type: 'badge', name: 'Second Badge', order: 2 } + ]; + + couchdbService.find.mockResolvedValue({ docs: mockBadges }); + + const badges = await Badge.findAll(); + + expect(couchdbService.find).toHaveBeenCalledWith({ + selector: { type: 'badge' }, + sort: [{ order: 'asc' }] + }); + expect(badges).toEqual(mockBadges); + }); + + it('should handle errors when finding badges', async () => { + couchdbService.find.mockRejectedValue(new Error('Database error')); + + await expect(Badge.findAll()).rejects.toThrow('Database error'); + }); + }); + + describe('findById', () => { + it('should return badge by ID', async () => { + const mockBadge = { + _id: 'badge_123', + type: 'badge', + name: 'Test Badge', + description: 'Test description' + }; + + couchdbService.get.mockResolvedValue(mockBadge); + + const badge = await Badge.findById('badge_123'); + + expect(couchdbService.get).toHaveBeenCalledWith('badge_123'); + expect(badge).toEqual(mockBadge); + }); + + it('should return null for non-badge documents', async () => { + const mockDoc = { + _id: 'user_123', + type: 'user', + name: 'Test User' + }; + + couchdbService.get.mockResolvedValue(mockDoc); + + const badge = await Badge.findById('user_123'); + + expect(badge).toBeNull(); + }); + + it('should return null for 404 errors', async () => { + const error = new Error('Not found'); + error.statusCode = 404; + couchdbService.get.mockRejectedValue(error); + + const badge = await Badge.findById('nonexistent'); + + expect(badge).toBeNull(); + }); + + it('should handle other errors', async () => { + couchdbService.get.mockRejectedValue(new Error('Database error')); + + await expect(Badge.findById('badge_123')).rejects.toThrow('Database error'); + }); + }); + + describe('create', () => { + it('should create a new badge', async () => { const badgeData = { name: 'Street Cleaner', description: 'Awarded for completing 10 street cleaning tasks', icon: 'broom', - category: 'maintenance', - requirement: { - type: 'task_count', - value: 10, - taskType: 'cleaning' - } + criteria: { type: 'task_count', threshold: 10 }, + rarity: 'common', + order: 1 }; - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - isActive: true, - pointsAwarded: 50, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); + const mockResult = { rev: '1-abc' }; + couchdbService.createDocument.mockResolvedValue(mockResult); const badge = await Badge.create(badgeData); - expect(badge._id).toBeDefined(); - expect(badge.name).toBe(badgeData.name); - expect(badge.description).toBe(badgeData.description); - expect(badge.icon).toBe(badgeData.icon); - expect(badge.category).toBe(badgeData.category); - expect(badge.requirement.type).toBe(badgeData.requirement.type); - expect(badge.isActive).toBe(true); - expect(badge.pointsAwarded).toBe(50); - }); - - it('should require name field', async () => { - const badgeData = { - description: 'Badge without name', - icon: 'star', - category: 'achievement', - }; - - expect(() => new Badge(badgeData)).toThrow(); - }); - - it('should require description field', async () => { - const badgeData = { - name: 'Badge without description', - icon: 'star', - category: 'achievement', - }; - - expect(() => new Badge(badgeData)).toThrow(); - }); - - it('should require icon field', async () => { - const badgeData = { - name: 'Badge without icon', - description: 'This badge has no icon', - category: 'achievement', - }; - - expect(() => new Badge(badgeData)).toThrow(); - }); - - it('should require category field', async () => { - const badgeData = { - name: 'Badge without category', - description: 'This badge has no category', - icon: 'star', - }; - - expect(() => new Badge(badgeData)).toThrow(); - }); - - it('should require requirement field', async () => { - const badgeData = { - name: 'Badge without requirement', - description: 'This badge has no requirement', - icon: 'star', - category: 'achievement', - }; - - expect(() => new Badge(badgeData)).toThrow(); - }); - }); - - describe('Categories', () => { - const validCategories = ['achievement', 'maintenance', 'social', 'milestone', 'special']; - - validCategories.forEach(category => { - it(`should accept "${category}" as valid category`, async () => { - const badgeData = { - name: `${category} Badge`, - description: `Testing ${category} category`, - icon: 'star', - category, - requirement: { - type: 'task_count', - value: 5 - } - }; - - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', + expect(couchdbService.createDocument).toHaveBeenCalledWith( + expect.objectContaining({ + _id: expect.stringMatching(/^badge_\d+_[a-z0-9]+$/), type: 'badge', - ...badgeData, + name: badgeData.name, + description: badgeData.description, + icon: badgeData.icon, + criteria: badgeData.criteria, + rarity: badgeData.rarity, + order: badgeData.order, isActive: true, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.category).toBe(category); - }); - }); - - it('should reject invalid category', async () => { - const badgeData = { - name: 'Invalid Category Badge', - description: 'This badge has invalid category', - icon: 'star', - category: 'invalid_category', - requirement: { - type: 'task_count', - value: 5 - } - }; - - expect(() => new Badge(badgeData)).toThrow(); - }); - }); - - describe('Requirement Types', () => { - const validRequirementTypes = [ - { type: 'task_count', value: 10 }, - { type: 'street_count', value: 5 }, - { type: 'points_earned', value: 1000 }, - { type: 'event_participation', value: 3 }, - { type: 'streak_days', value: 7 } - ]; - - validRequirementTypes.forEach(requirement => { - it(`should accept "${requirement.type}" as valid requirement type`, async () => { - const badgeData = { - name: `${requirement.type} Badge`, - description: `Testing ${requirement.type} requirement`, - icon: 'star', - category: 'achievement', - requirement - }; - - const mockCreated = { - _id: 'badge_123', + createdAt: expect.any(String), + updatedAt: expect.any(String) + }) + ); + expect(badge).toEqual( + expect.objectContaining({ + ...badgeData, _rev: '1-abc', - type: 'badge', - ...badgeData, isActive: true, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.requirement.type).toBe(requirement.type); - expect(badge.requirement.value).toBe(requirement.value); - }); + createdAt: expect.any(String), + updatedAt: expect.any(String) + }) + ); }); - }); - describe('Default Values', () => { - it('should default isActive to true', async () => { + it('should use default values', async () => { const badgeData = { - name: 'Default Active Badge', - description: 'Testing default active status', - icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 5 - } - }; - - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - isActive: true, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.isActive).toBe(true); - }); - - it('should default pointsAwarded to 25', async () => { - const badgeData = { - name: 'Default Points Badge', - description: 'Testing default points', - icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 5 - } - }; - - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - isActive: true, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.pointsAwarded).toBe(25); - }); - }); - - describe('Custom Values', () => { - it('should allow custom isActive value', async () => { - const badgeData = { - name: 'Inactive Badge', - description: 'This badge is inactive', - icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 5 - }, - isActive: false - }; - - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.isActive).toBe(false); - }); - - it('should allow custom pointsAwarded value', async () => { - const badgeData = { - name: 'Custom Points Badge', - description: 'This badge gives custom points', - icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 5 - }, - pointsAwarded: 100 - }; - - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - isActive: true, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.pointsAwarded).toBe(100); - }); - }); - - describe('Complex Requirements', () => { - it('should allow requirements with additional properties', async () => { - const badgeData = { - name: 'Complex Requirement Badge', - description: 'Badge with complex requirement', - icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 10, - taskType: 'cleaning', - timeFrame: '30_days', - streetStatus: 'adopted' - } - }; - - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - isActive: true, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.requirement.taskType).toBe('cleaning'); - expect(badge.requirement.timeFrame).toBe('30_days'); - expect(badge.requirement.streetStatus).toBe('adopted'); - }); - }); - - describe('Timestamps', () => { - it('should automatically set createdAt and updatedAt', async () => { - const badgeData = { - name: 'Timestamp Badge', - description: 'Testing timestamps', - icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 5 - } - }; - - const mockCreated = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - isActive: true, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); - - const badge = await Badge.create(badgeData); - - expect(badge.createdAt).toBeDefined(); - expect(badge.updatedAt).toBeDefined(); - expect(typeof badge.createdAt).toBe('string'); - expect(typeof badge.updatedAt).toBe('string'); - }); - - it('should update updatedAt on modification', async () => { - const badgeData = { - name: 'Update Test Badge', - description: 'Testing update timestamp', - icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 5 - } - }; - - const mockBadge = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', - ...badgeData, - isActive: true, - pointsAwarded: 25, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' - }; - - couchdbService.findDocumentById.mockResolvedValue(mockBadge); - couchdbService.updateDocument.mockResolvedValue({ - ...mockBadge, - isActive: false, - _rev: '2-def', - updatedAt: '2023-01-01T00:00:01.000Z' - }); - - const badge = await Badge.findById('badge_123'); - const originalUpdatedAt = badge.updatedAt; - - badge.isActive = false; - await badge.save(); - - expect(badge.updatedAt).not.toBe(originalUpdatedAt); - }); - }); - - describe('Static Methods', () => { - it('should find badge by ID', async () => { - const mockBadge = { - _id: 'badge_123', - _rev: '1-abc', - type: 'badge', name: 'Test Badge', description: 'Test description', + icon: 'star' + }; + + const mockResult = { rev: '1-abc' }; + couchdbService.createDocument.mockResolvedValue(mockResult); + + const badge = await Badge.create(badgeData); + + expect(badge.rarity).toBe('common'); + expect(badge.order).toBe(0); + expect(badge.isActive).toBe(true); + }); + + it('should handle errors during creation', async () => { + const badgeData = { + name: 'Test Badge', + description: 'Test description', + icon: 'star' + }; + + couchdbService.createDocument.mockRejectedValue(new Error('Creation failed')); + + await expect(Badge.create(badgeData)).rejects.toThrow('Creation failed'); + }); + }); + + describe('update', () => { + it('should update an existing badge', async () => { + const existingBadge = { + _id: 'badge_123', + _rev: '1-abc', + type: 'badge', + name: 'Original Name', + description: 'Original description', icon: 'star', - category: 'achievement', - requirement: { - type: 'task_count', - value: 5 - }, + criteria: { type: 'task_count', threshold: 5 }, + rarity: 'common', + order: 0, isActive: true, - pointsAwarded: 25, createdAt: '2023-01-01T00:00:00.000Z', updatedAt: '2023-01-01T00:00:00.000Z' }; - couchdbService.findDocumentById.mockResolvedValue(mockBadge); + const updateData = { + name: 'Updated Name', + rarity: 'rare' + }; - const badge = await Badge.findById('badge_123'); - expect(badge).toBeDefined(); - expect(badge._id).toBe('badge_123'); - expect(badge.name).toBe('Test Badge'); + const mockResult = { rev: '2-def' }; + couchdbService.get.mockResolvedValue(existingBadge); + couchdbService.createDocument.mockResolvedValue(mockResult); + + const badge = await Badge.update('badge_123', updateData); + + expect(couchdbService.get).toHaveBeenCalledWith('badge_123'); + expect(couchdbService.createDocument).toHaveBeenCalledWith( + expect.objectContaining({ + ...existingBadge, + name: 'Updated Name', + rarity: 'rare', + updatedAt: expect.any(String) + }) + ); + expect(badge._rev).toBe('2-def'); }); - it('should return null when badge not found', async () => { - couchdbService.findDocumentById.mockResolvedValue(null); + it('should throw error for non-badge documents', async () => { + const nonBadgeDoc = { + _id: 'user_123', + _rev: '1-abc', + type: 'user' + }; - const badge = await Badge.findById('nonexistent'); - expect(badge).toBeNull(); + couchdbService.get.mockResolvedValue(nonBadgeDoc); + + await expect(Badge.update('user_123', { name: 'Updated' })).rejects.toThrow('Document is not a badge'); + }); + + it('should handle errors during update', async () => { + couchdbService.get.mockRejectedValue(new Error('Update failed')); + + await expect(Badge.update('badge_123', { name: 'Updated' })).rejects.toThrow('Update failed'); + }); + }); + + describe('delete', () => { + it('should delete a badge', async () => { + const mockBadge = { + _id: 'badge_123', + _rev: '1-abc', + type: 'badge' + }; + + couchdbService.get.mockResolvedValue(mockBadge); + couchdbService.destroy.mockResolvedValue(true); + + const result = await Badge.delete('badge_123'); + + expect(couchdbService.get).toHaveBeenCalledWith('badge_123'); + expect(couchdbService.destroy).toHaveBeenCalledWith('badge_123', '1-abc'); + expect(result).toBe(true); + }); + + it('should throw error for non-badge documents', async () => { + const nonBadgeDoc = { + _id: 'user_123', + _rev: '1-abc', + type: 'user' + }; + + couchdbService.get.mockResolvedValue(nonBadgeDoc); + + await expect(Badge.delete('user_123')).rejects.toThrow('Document is not a badge'); + }); + + it('should handle errors during deletion', async () => { + couchdbService.get.mockRejectedValue(new Error('Delete failed')); + + await expect(Badge.delete('badge_123')).rejects.toThrow('Delete failed'); + }); + }); + + describe('findByCriteria', () => { + it('should find badges by criteria type and threshold', async () => { + const mockBadges = [ + { _id: 'badge1', type: 'badge', criteria: { type: 'task_count', threshold: 10 } }, + { _id: 'badge2', type: 'badge', criteria: { type: 'task_count', threshold: 5 } } + ]; + + couchdbService.find.mockResolvedValue({ docs: mockBadges }); + + const badges = await Badge.findByCriteria('task_count', 7); + + expect(couchdbService.find).toHaveBeenCalledWith({ + selector: { + type: 'badge', + 'criteria.type': 'task_count', + 'criteria.threshold': { $lte: 7 } + }, + sort: [{ 'criteria.threshold': 'desc' }] + }); + expect(badges).toEqual(mockBadges); + }); + + it('should handle errors when finding by criteria', async () => { + couchdbService.find.mockRejectedValue(new Error('Search failed')); + + await expect(Badge.findByCriteria('task_count', 10)).rejects.toThrow('Search failed'); + }); + }); + + describe('findByRarity', () => { + it('should find badges by rarity', async () => { + const mockBadges = [ + { _id: 'badge1', type: 'badge', rarity: 'rare', order: 1 }, + { _id: 'badge2', type: 'badge', rarity: 'rare', order: 2 } + ]; + + couchdbService.find.mockResolvedValue({ docs: mockBadges }); + + const badges = await Badge.findByRarity('rare'); + + expect(couchdbService.find).toHaveBeenCalledWith({ + selector: { + type: 'badge', + rarity: 'rare' + }, + sort: [{ order: 'asc' }] + }); + expect(badges).toEqual(mockBadges); + }); + + it('should handle errors when finding by rarity', async () => { + couchdbService.find.mockRejectedValue(new Error('Search failed')); + + await expect(Badge.findByRarity('rare')).rejects.toThrow('Search failed'); }); }); }); \ No newline at end of file diff --git a/backend/__tests__/models/PointTransaction.test.js b/backend/__tests__/models/PointTransaction.test.js index 8eeb46e..5410272 100644 --- a/backend/__tests__/models/PointTransaction.test.js +++ b/backend/__tests__/models/PointTransaction.test.js @@ -1,59 +1,70 @@ // Mock CouchDB service for testing const mockCouchdbService = { - createDocument: jest.fn(), - findDocumentById: jest.fn(), - updateDocument: jest.fn(), - findByType: jest.fn(), - initialize: jest.fn(), - getDocument: jest.fn(), - findUserById: jest.fn(), + create: jest.fn(), + insert: jest.fn(), + get: jest.fn(), + getById: jest.fn(), + find: jest.fn(), update: jest.fn(), + delete: jest.fn(), + findUserById: jest.fn(), + initialize: jest.fn().mockResolvedValue(true), + isReady: jest.fn().mockReturnValue(true), + isConnected: true, + isConnecting: false, + shutdown: jest.fn().mockResolvedValue(true), }; // Mock the service module jest.mock('../../services/couchdbService', () => mockCouchdbService); +const couchdbService = require('../../services/couchdbService'); +const PointTransaction = require('../../models/PointTransaction'); + describe('PointTransaction Model', () => { beforeEach(() => { - mockCouchdbService.createDocument.mockReset(); - mockCouchdbService.findDocumentById.mockReset(); - mockCouchdbService.updateDocument.mockReset(); - mockCouchdbService.findByType.mockReset(); + mockCouchdbService.create.mockReset(); + mockCouchdbService.insert.mockReset(); + mockCouchdbService.get.mockReset(); + mockCouchdbService.getById.mockReset(); + mockCouchdbService.find.mockReset(); + mockCouchdbService.update.mockReset(); + mockCouchdbService.delete.mockReset(); + mockCouchdbService.findUserById.mockReset(); }); describe('Schema Validation', () => { it('should create a valid point transaction', async () => { const transactionData = { user: 'user_123', - points: 50, - type: 'earned', + amount: 50, + transactionType: 'earned', description: 'Completed street cleaning task', - source: { + relatedEntity: { type: 'task_completion', referenceId: 'task_123' - } + }, + balanceAfter: 150 }; - const mockCreated = { - _id: 'point_transaction_123', - _rev: '1-abc', - type: 'point_transaction', - ...transactionData, - createdAt: '2023-01-01T00:00:00.000Z', - updatedAt: '2023-01-01T00:00:00.000Z' + const mockInsertResult = { + ok: true, + id: 'point_transaction_123', + rev: '1-abc' }; - mockCouchdbService.createDocument.mockResolvedValue(mockCreated); + mockCouchdbService.insert.mockResolvedValue(mockInsertResult); const transaction = await PointTransaction.create(transactionData); expect(transaction._id).toBeDefined(); expect(transaction.user).toBe(transactionData.user); - expect(transaction.points).toBe(transactionData.points); - expect(transaction.type).toBe(transactionData.type); + expect(transaction.amount).toBe(transactionData.amount); + expect(transaction.transactionType).toBe(transactionData.transactionType); expect(transaction.description).toBe(transactionData.description); - expect(transaction.source.type).toBe(transactionData.source.type); - expect(transaction.source.referenceId).toBe(transactionData.source.referenceId); + expect(transaction.relatedEntity.type).toBe(transactionData.relatedEntity.type); + expect(transaction.relatedEntity.referenceId).toBe(transactionData.relatedEntity.referenceId); + expect(transaction.balanceAfter).toBe(transactionData.balanceAfter); }); it('should require user field', async () => { diff --git a/backend/__tests__/models/Post.test.js b/backend/__tests__/models/Post.test.js index 6786509..20d15bb 100644 --- a/backend/__tests__/models/Post.test.js +++ b/backend/__tests__/models/Post.test.js @@ -8,11 +8,15 @@ const mockCouchdbService = { getDocument: jest.fn(), findUserById: jest.fn(), update: jest.fn(), + create: jest.fn(), + getById: jest.fn(), }; // Mock the service module jest.mock('../../services/couchdbService', () => mockCouchdbService); +const Post = require('../../models/Post'); + describe('Post Model', () => { beforeEach(() => { jest.clearAllMocks(); diff --git a/backend/models/Badge.js b/backend/models/Badge.js index 70d527d..d60a479 100644 --- a/backend/models/Badge.js +++ b/backend/models/Badge.js @@ -46,7 +46,7 @@ class Badge { updatedAt: new Date().toISOString() }; - const result = await couchdbService.insert(badge); + const result = await couchdbService.createDocument(badge); return { ...badge, _rev: result.rev }; } catch (error) { console.error('Error creating badge:', error); @@ -67,7 +67,7 @@ class Badge { updatedAt: new Date().toISOString() }; - const result = await couchdbService.insert(updatedBadge); + const result = await couchdbService.createDocument(updatedBadge); return { ...updatedBadge, _rev: result.rev }; } catch (error) { console.error('Error updating badge:', error);