fix: remove any types, dead code, unused exports; add comprehensive tests
- Fix handleRotate bug ignoring Result from rotateSealedSecret() - Fix dead code branch in useControllerHealth - Replace all `any` types with `unknown` + type guards - Delete unused functions/exports (452 lines removed) - Add 18 new test files covering all hooks, libs, and components - 233 tests passing, zero tsc errors, zero lint issues Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* Unit tests for usePermissions hooks
|
||||
*/
|
||||
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
// Mock rbac module
|
||||
vi.mock('../lib/rbac', () => ({
|
||||
checkSealedSecretPermissions: vi.fn(),
|
||||
}));
|
||||
|
||||
import { checkSealedSecretPermissions } from '../lib/rbac';
|
||||
import { usePermission, usePermissions } from './usePermissions';
|
||||
|
||||
const mockCheckPerms = vi.mocked(checkSealedSecretPermissions);
|
||||
|
||||
describe('usePermissions', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('usePermissions', () => {
|
||||
it('should start in loading state', () => {
|
||||
mockCheckPerms.mockReturnValue(new Promise(() => {})); // never resolves
|
||||
|
||||
const { result } = renderHook(() => usePermissions('default'));
|
||||
|
||||
expect(result.current.loading).toBe(true);
|
||||
expect(result.current.permissions).toBe(null);
|
||||
expect(result.current.error).toBe(null);
|
||||
});
|
||||
|
||||
it('should transition to loaded with permissions', async () => {
|
||||
mockCheckPerms.mockResolvedValue({
|
||||
ok: true,
|
||||
value: {
|
||||
canCreate: true,
|
||||
canRead: true,
|
||||
canUpdate: false,
|
||||
canDelete: false,
|
||||
canList: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => usePermissions('default'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(result.current.permissions).toEqual({
|
||||
canCreate: true,
|
||||
canRead: true,
|
||||
canUpdate: false,
|
||||
canDelete: false,
|
||||
canList: true,
|
||||
});
|
||||
expect(result.current.error).toBe(null);
|
||||
});
|
||||
|
||||
it('should set error state on failure', async () => {
|
||||
mockCheckPerms.mockResolvedValue({
|
||||
ok: false,
|
||||
error: 'Permission check failed',
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => usePermissions('default'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(result.current.permissions).toBe(null);
|
||||
expect(result.current.error).toBe('Permission check failed');
|
||||
});
|
||||
|
||||
it('should re-fetch when namespace changes', async () => {
|
||||
mockCheckPerms.mockResolvedValue({
|
||||
ok: true,
|
||||
value: {
|
||||
canCreate: true,
|
||||
canRead: true,
|
||||
canUpdate: true,
|
||||
canDelete: true,
|
||||
canList: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { result, rerender } = renderHook(({ ns }: { ns: string }) => usePermissions(ns), {
|
||||
initialProps: { ns: 'default' },
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(mockCheckPerms).toHaveBeenCalledWith('default');
|
||||
|
||||
rerender({ ns: 'production' });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(mockCheckPerms).toHaveBeenCalledWith('production');
|
||||
expect(mockCheckPerms).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should handle unmount cancellation', async () => {
|
||||
let resolvePromise: (value: unknown) => void;
|
||||
mockCheckPerms.mockReturnValue(
|
||||
new Promise(resolve => {
|
||||
resolvePromise = resolve;
|
||||
})
|
||||
);
|
||||
|
||||
const { result, unmount } = renderHook(() => usePermissions('default'));
|
||||
|
||||
expect(result.current.loading).toBe(true);
|
||||
|
||||
// Unmount before promise resolves
|
||||
unmount();
|
||||
|
||||
// Resolve after unmount - should not cause errors
|
||||
resolvePromise!({
|
||||
ok: true,
|
||||
value: {
|
||||
canCreate: true,
|
||||
canRead: true,
|
||||
canUpdate: true,
|
||||
canDelete: true,
|
||||
canList: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should work without namespace (cluster-wide)', async () => {
|
||||
mockCheckPerms.mockResolvedValue({
|
||||
ok: true,
|
||||
value: {
|
||||
canCreate: false,
|
||||
canRead: true,
|
||||
canUpdate: false,
|
||||
canDelete: false,
|
||||
canList: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => usePermissions());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(mockCheckPerms).toHaveBeenCalledWith(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('usePermission', () => {
|
||||
it('should return specific permission', async () => {
|
||||
mockCheckPerms.mockResolvedValue({
|
||||
ok: true,
|
||||
value: {
|
||||
canCreate: true,
|
||||
canRead: true,
|
||||
canUpdate: false,
|
||||
canDelete: false,
|
||||
canList: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => usePermission('default', 'canCreate'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(result.current.allowed).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when permission is denied', async () => {
|
||||
mockCheckPerms.mockResolvedValue({
|
||||
ok: true,
|
||||
value: {
|
||||
canCreate: false,
|
||||
canRead: true,
|
||||
canUpdate: false,
|
||||
canDelete: false,
|
||||
canList: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { result } = renderHook(() => usePermission('default', 'canCreate'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.loading).toBe(false);
|
||||
});
|
||||
|
||||
expect(result.current.allowed).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when permissions are null (loading/error)', () => {
|
||||
mockCheckPerms.mockReturnValue(new Promise(() => {}));
|
||||
|
||||
const { result } = renderHook(() => usePermission('default', 'canCreate'));
|
||||
|
||||
expect(result.current.loading).toBe(true);
|
||||
expect(result.current.allowed).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user