From e7ea64dc36aa7d52bee0e9d0ea0035452ef4f62b Mon Sep 17 00:00:00 2001 From: Dmitry Date: Wed, 3 Dec 2025 04:40:47 +0300 Subject: [PATCH] web --- .gitignore | 2 + mnemo_cards_admin/web/src/api/auth.test.ts | 40 +++++++++++--------- mnemo_cards_admin/web/src/api/client.test.ts | 24 ++++++------ 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 24476c5..7e3530e 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +.isar \ No newline at end of file diff --git a/mnemo_cards_admin/web/src/api/auth.test.ts b/mnemo_cards_admin/web/src/api/auth.test.ts index 1b3f997..c30e1b4 100644 --- a/mnemo_cards_admin/web/src/api/auth.test.ts +++ b/mnemo_cards_admin/web/src/api/auth.test.ts @@ -1,8 +1,8 @@ import { describe, it, expect, vi, beforeEach } from 'vitest' +import type { MockedFunction } from 'vitest' import { authApi } from './auth' -import { adminApiClient } from './client' -// Mock the adminApiClient +// Mock the adminApiClient module vi.mock('./client', () => ({ adminApiClient: { post: vi.fn(), @@ -10,7 +10,13 @@ vi.mock('./client', () => ({ }, })) -const mockedAdminApiClient = vi.mocked(adminApiClient) +// Import the mocked module +import { adminApiClient } from './client' +import type { AxiosResponse } from 'axios' + +// Type the mocked functions +const mockPost = adminApiClient.post as MockedFunction +const mockGet = adminApiClient.get as MockedFunction describe('authApi', () => { beforeEach(() => { @@ -21,18 +27,18 @@ describe('authApi', () => { it('should call adminApiClient.post with correct endpoint', async () => { const mockResponse = { data: { success: true, message: 'Code sent' }, - } - mockedAdminApiClient.post.mockResolvedValue(mockResponse) + } as AxiosResponse + mockPost.mockResolvedValue(mockResponse) const result = await authApi.requestCode() - expect(mockedAdminApiClient.post).toHaveBeenCalledWith('/api/v2/admin/auth/request-code') + expect(mockPost).toHaveBeenCalledWith('/api/v2/admin/auth/request-code') expect(result).toEqual({ success: true, message: 'Code sent' }) }) it('should handle API errors', async () => { const error = new Error('Network error') - mockedAdminApiClient.post.mockRejectedValue(error) + mockPost.mockRejectedValue(error) await expect(authApi.requestCode()).rejects.toThrow('Network error') }) @@ -46,12 +52,12 @@ describe('authApi', () => { token: 'jwt-token', user: { id: 1, name: 'Admin', admin: true }, }, - } - mockedAdminApiClient.post.mockResolvedValue(mockResponse) + } as AxiosResponse + mockPost.mockResolvedValue(mockResponse) const result = await authApi.verifyCode('123456') - expect(mockedAdminApiClient.post).toHaveBeenCalledWith('/api/v2/admin/auth/verify-code', { + expect(mockPost).toHaveBeenCalledWith('/api/v2/admin/auth/verify-code', { code: '123456', }) expect(result).toEqual(mockResponse.data) @@ -60,8 +66,8 @@ describe('authApi', () => { it('should handle invalid code response', async () => { const mockResponse = { data: { success: false, message: 'Invalid code' }, - } - mockedAdminApiClient.post.mockResolvedValue(mockResponse) + } as AxiosResponse + mockPost.mockResolvedValue(mockResponse) const result = await authApi.verifyCode('invalid') @@ -76,20 +82,20 @@ describe('authApi', () => { success: true, user: { id: 1, name: 'Admin', admin: true }, }, - } - mockedAdminApiClient.get.mockResolvedValue(mockResponse) + } as AxiosResponse + mockGet.mockResolvedValue(mockResponse) const result = await authApi.getCurrentUser() - expect(mockedAdminApiClient.get).toHaveBeenCalledWith('/api/v2/admin/auth/me') + expect(mockGet).toHaveBeenCalledWith('/api/v2/admin/auth/me') expect(result).toEqual(mockResponse.data) }) it('should handle unauthorized access', async () => { const mockResponse = { data: { success: false, message: 'Not authenticated' }, - } - mockedAdminApiClient.get.mockResolvedValue(mockResponse) + } as AxiosResponse + mockGet.mockResolvedValue(mockResponse) const result = await authApi.getCurrentUser() diff --git a/mnemo_cards_admin/web/src/api/client.test.ts b/mnemo_cards_admin/web/src/api/client.test.ts index 4d4270c..eca6ad6 100644 --- a/mnemo_cards_admin/web/src/api/client.test.ts +++ b/mnemo_cards_admin/web/src/api/client.test.ts @@ -74,9 +74,12 @@ describe('API Clients', () => { describe('Error handling', () => { it('should handle 401 errors by clearing token and redirecting', async () => { - const originalLocation = window.location - delete (window as any).location - window.location = { href: '' } as any + // Mock window.location + const mockLocation = { href: '' } + Object.defineProperty(window, 'location', { + value: mockLocation, + writable: true, + }) const handleAuthError = (error: any) => { if (error.response?.status === 401) { @@ -95,15 +98,15 @@ describe('API Clients', () => { expect(localStorage.getItem('admin_token')).toBeNull() expect(window.location.href).toBe('/login') - - // Restore original location - window.location = originalLocation }) it('should not redirect for non-401 errors', async () => { - const originalLocation = window.location - delete (window as any).location - window.location = { href: '' } as any + // Mock window.location + const mockLocation = { href: '' } + Object.defineProperty(window, 'location', { + value: mockLocation, + writable: true, + }) const handleAuthError = (error: any) => { if (error.response?.status === 401) { @@ -119,9 +122,6 @@ describe('API Clients', () => { expect(localStorage.getItem('admin_token')).toBeNull() // Should be cleared from beforeEach expect(window.location.href).toBe('') - - // Restore original location - window.location = originalLocation }) }) })