From dc505b2789af9d2b48df33f096289517373da6e4 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 9 Feb 2026 07:28:16 +0000 Subject: [PATCH] fix: mock system api in layout tests to prevent network crashes - Mocked `getNotifications` and `checkUpdates` in `Layout.test.tsx` - Prevents `UND_ERR_INVALID_ARG` errors caused by unmocked `undici` network requests in JSDOM - Ensures clean test execution for `Layout` and child components --- .../internal/services/access_list_service.go | 24 +++++++++++-------- codecov.yml | 2 +- .../src/components/__tests__/Layout.test.tsx | 8 +++++++ .../src/pages/__tests__/UsersPage.test.tsx | 14 ++++++++--- frontend/vitest.config.ts | 5 ++++ scripts/frontend-test-coverage.sh | 2 +- 6 files changed, 40 insertions(+), 15 deletions(-) diff --git a/backend/internal/services/access_list_service.go b/backend/internal/services/access_list_service.go index 36f70e6f..46c05be6 100644 --- a/backend/internal/services/access_list_service.go +++ b/backend/internal/services/access_list_service.go @@ -102,11 +102,13 @@ func (s *AccessListService) Create(acl *models.AccessList) error { // GetByID retrieves an access list by ID func (s *AccessListService) GetByID(id uint) (*models.AccessList, error) { var acl models.AccessList - if err := s.db.Where("id = ?", id).First(&acl).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, ErrAccessListNotFound - } - return nil, err + // Use Find to avoid GORM 'record not found' log noise + result := s.db.Where("id = ?", id).Limit(1).Find(&acl) + if result.Error != nil { + return nil, result.Error + } + if result.RowsAffected == 0 { + return nil, ErrAccessListNotFound } return &acl, nil } @@ -114,11 +116,13 @@ func (s *AccessListService) GetByID(id uint) (*models.AccessList, error) { // GetByUUID retrieves an access list by UUID func (s *AccessListService) GetByUUID(uuidStr string) (*models.AccessList, error) { var acl models.AccessList - if err := s.db.Where("uuid = ?", uuidStr).First(&acl).Error; err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return nil, ErrAccessListNotFound - } - return nil, err + // Use Find to avoid GORM 'record not found' log noise + result := s.db.Where("uuid = ?", uuidStr).Limit(1).Find(&acl) + if result.Error != nil { + return nil, result.Error + } + if result.RowsAffected == 0 { + return nil, ErrAccessListNotFound } return &acl, nil } diff --git a/codecov.yml b/codecov.yml index 77bb7558..09d6b20b 100644 --- a/codecov.yml +++ b/codecov.yml @@ -5,7 +5,7 @@ coverage: status: project: default: - target: auto + target: 85% threshold: 1% patch: default: diff --git a/frontend/src/components/__tests__/Layout.test.tsx b/frontend/src/components/__tests__/Layout.test.tsx index a4f67bca..11bf9221 100644 --- a/frontend/src/components/__tests__/Layout.test.tsx +++ b/frontend/src/components/__tests__/Layout.test.tsx @@ -32,6 +32,14 @@ vi.mock('../../api/featureFlags', () => ({ }), })) +// Mock System API to prevent unhandled network requests +vi.mock('../../api/system', () => ({ + getNotifications: vi.fn().mockResolvedValue([]), + markNotificationRead: vi.fn(), + markAllNotificationsRead: vi.fn(), + checkUpdates: vi.fn().mockResolvedValue({ available: false }), +})) + const renderWithProviders = (children: ReactNode) => { const queryClient = new QueryClient({ defaultOptions: { diff --git a/frontend/src/pages/__tests__/UsersPage.test.tsx b/frontend/src/pages/__tests__/UsersPage.test.tsx index f65d4f13..a136d1b6 100644 --- a/frontend/src/pages/__tests__/UsersPage.test.tsx +++ b/frontend/src/pages/__tests__/UsersPage.test.tsx @@ -362,6 +362,10 @@ describe('UsersPage', () => { }) describe('URL Preview in InviteModal', () => { + afterEach(() => { + vi.useRealTimers() + }) + it('shows URL preview when valid email is entered', async () => { vi.mocked(usersApi.listUsers).mockResolvedValue(mockUsers) vi.mocked(client.post).mockResolvedValue({ @@ -406,19 +410,23 @@ describe('UsersPage', () => { }) renderWithQueryClient() + const user = userEvent.setup() await waitFor(() => expect(screen.getByText('Invite User')).toBeInTheDocument()) + await user.click(screen.getByRole('button', { name: /Invite User/i })) + await waitFor(() => expect(screen.getByPlaceholderText('user@example.com')).toBeInTheDocument()) vi.useFakeTimers() - const openUser = userEvent.setup({ advanceTimers: vi.advanceTimersByTime }) - await openUser.click(screen.getByRole('button', { name: /Invite User/i })) try { const emailInput = screen.getByPlaceholderText('user@example.com') fireEvent.change(emailInput, { target: { value: 'test@example.com' } }) + // Verify not called immediately + expect(client.post).not.toHaveBeenCalled() + await act(async () => { - await vi.advanceTimersByTimeAsync(500) + await vi.advanceTimersByTimeAsync(550) }) expect(client.post).toHaveBeenCalledTimes(1) diff --git a/frontend/vitest.config.ts b/frontend/vitest.config.ts index b94fa081..42d4043d 100644 --- a/frontend/vitest.config.ts +++ b/frontend/vitest.config.ts @@ -13,6 +13,11 @@ export default defineConfig({ pool: 'threads', globals: true, environment: 'jsdom', + environmentOptions: { + jsdom: { + url: 'http://localhost', + }, + }, setupFiles: './src/test/setup.ts', // TypeScript types for test globals - these are automatically available in test files typecheck: { diff --git a/scripts/frontend-test-coverage.sh b/scripts/frontend-test-coverage.sh index 2645e7f3..3444605d 100755 --- a/scripts/frontend-test-coverage.sh +++ b/scripts/frontend-test-coverage.sh @@ -12,7 +12,7 @@ sleep 1 ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" FRONTEND_DIR="$ROOT_DIR/frontend" -MIN_COVERAGE="${CHARON_MIN_COVERAGE:-${CPM_MIN_COVERAGE:-87.5}}" +MIN_COVERAGE="${CHARON_MIN_COVERAGE:-${CPM_MIN_COVERAGE:-88}}" cd "$FRONTEND_DIR"