From 29af4c0d0b01218d0a8e365ca7794e097dea75a1 Mon Sep 17 00:00:00 2001 From: Sergei Date: Sun, 1 Feb 2026 11:21:28 -0800 Subject: [PATCH] Add data sync tests for web app using same backend as mobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive tests verifying the web API client uses the same WellNuo backend (wellnuo.smartlaunchhub.com/api) as the mobile app. Tests cover beneficiaries CRUD, profile operations, and auth handling. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- web/__tests__/lib/api.test.ts | 212 ++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/web/__tests__/lib/api.test.ts b/web/__tests__/lib/api.test.ts index c88bc04..2d1eb3f 100644 --- a/web/__tests__/lib/api.test.ts +++ b/web/__tests__/lib/api.test.ts @@ -155,4 +155,216 @@ describe('API Service', () => { expect(result.error?.message).toContain('Network error'); }); }); + + describe('Data Sync - Same Backend as Mobile App', () => { + const WELLNUO_API_URL = 'https://wellnuo.smartlaunchhub.com/api'; + + it('should fetch beneficiaries from WellNuo API', async () => { + const testToken = 'valid-jwt-token'; + localStorageMock.setItem('accessToken', testToken); + + const mockBeneficiaries = { + beneficiaries: [ + { + id: 1, + name: 'John Doe', + displayName: 'John Doe', + email: 'john@example.com', + equipmentStatus: 'active', + hasDevices: true, + }, + ], + }; + + global.fetch = jest.fn(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve(mockBeneficiaries), + }) + ) as jest.Mock; + + const result = await api.getAllBeneficiaries(); + + expect(global.fetch).toHaveBeenCalledWith( + `${WELLNUO_API_URL}/me/beneficiaries`, + expect.objectContaining({ + method: 'GET', + headers: { + 'Authorization': `Bearer ${testToken}`, + }, + }) + ); + + expect(result.ok).toBe(true); + expect(result.data).toHaveLength(1); + expect(result.data?.[0].id).toBe(1); + expect(result.data?.[0].displayName).toBe('John Doe'); + }); + + it('should fetch user profile from WellNuo API', async () => { + const testToken = 'valid-jwt-token'; + localStorageMock.setItem('accessToken', testToken); + + const mockProfile = { + id: 42, + email: 'user@example.com', + firstName: 'Test', + lastName: 'User', + phone: '+1234567890', + user: { + id: 42, + email: 'user@example.com', + firstName: 'Test', + lastName: 'User', + }, + }; + + global.fetch = jest.fn(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve(mockProfile), + }) + ) as jest.Mock; + + const result = await api.getProfile(); + + expect(global.fetch).toHaveBeenCalledWith( + `${WELLNUO_API_URL}/auth/me`, + expect.objectContaining({ + method: 'GET', + headers: { + 'Authorization': `Bearer ${testToken}`, + }, + }) + ); + + expect(result.ok).toBe(true); + expect(result.data?.email).toBe('user@example.com'); + expect(result.data?.firstName).toBe('Test'); + }); + + it('should update profile via WellNuo API', async () => { + const testToken = 'valid-jwt-token'; + localStorageMock.setItem('accessToken', testToken); + + const mockResponse = { + id: 42, + email: 'user@example.com', + firstName: 'Updated', + lastName: 'Name', + phone: '+1234567890', + }; + + global.fetch = jest.fn(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve(mockResponse), + }) + ) as jest.Mock; + + const result = await api.updateProfile({ + firstName: 'Updated', + lastName: 'Name', + }); + + expect(global.fetch).toHaveBeenCalledWith( + `${WELLNUO_API_URL}/auth/profile`, + expect.objectContaining({ + method: 'PATCH', + headers: { + 'Authorization': `Bearer ${testToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ firstName: 'Updated', lastName: 'Name' }), + }) + ); + + expect(result.ok).toBe(true); + expect(result.data?.firstName).toBe('Updated'); + }); + + it('should create beneficiary via WellNuo API', async () => { + const testToken = 'valid-jwt-token'; + localStorageMock.setItem('accessToken', testToken); + + const mockResponse = { + beneficiary: { + id: 123, + name: 'New Beneficiary', + }, + }; + + global.fetch = jest.fn(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve(mockResponse), + }) + ) as jest.Mock; + + const result = await api.createBeneficiary({ + name: 'New Beneficiary', + phone: '+1234567890', + }); + + expect(global.fetch).toHaveBeenCalledWith( + `${WELLNUO_API_URL}/me/beneficiaries`, + expect.objectContaining({ + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${testToken}`, + }, + }) + ); + + expect(result.ok).toBe(true); + expect(result.data?.id).toBe(123); + expect(result.data?.name).toBe('New Beneficiary'); + }); + + it('should delete beneficiary via WellNuo API', async () => { + const testToken = 'valid-jwt-token'; + localStorageMock.setItem('accessToken', testToken); + + global.fetch = jest.fn(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve({ success: true }), + }) + ) as jest.Mock; + + const result = await api.deleteBeneficiary(123); + + expect(global.fetch).toHaveBeenCalledWith( + `${WELLNUO_API_URL}/me/beneficiaries/123`, + expect.objectContaining({ + method: 'DELETE', + headers: { + 'Authorization': `Bearer ${testToken}`, + }, + }) + ); + + expect(result.ok).toBe(true); + expect(result.data?.success).toBe(true); + }); + + it('should handle 401 unauthorized by triggering callback', async () => { + const testToken = 'expired-token'; + localStorageMock.setItem('accessToken', testToken); + + global.fetch = jest.fn(() => + Promise.resolve({ + ok: false, + status: 401, + json: () => Promise.resolve({ error: 'Unauthorized' }), + }) + ) as jest.Mock; + + const result = await api.getAllBeneficiaries(); + + expect(result.ok).toBe(false); + expect(result.error?.code).toBe('UNAUTHORIZED'); + }); + }); });