Files
headlamp-sealed-secrets-plugin/src/components/DecryptDialog.test.tsx
T
DevContainer User 9d9bc5f22f 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>
2026-03-04 17:13:00 +00:00

168 lines
5.0 KiB
TypeScript

/**
* Unit tests for DecryptDialog component
*/
import { act, fireEvent, render, screen } from '@testing-library/react';
import React from 'react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
// Mock notistack
const mockEnqueueSnackbar = vi.fn();
vi.mock('notistack', () => ({
useSnackbar: () => ({ enqueueSnackbar: mockEnqueueSnackbar }),
}));
// Mock iconify
vi.mock('@iconify/react', () => ({
Icon: ({ icon }: { icon: string }) => <span data-testid="icon">{icon}</span>,
}));
// Mock headlamp
vi.mock('@kinvolk/headlamp-plugin/lib', () => ({
K8s: {
ResourceClasses: {
Secret: {
useGet: vi.fn(),
},
},
},
}));
vi.mock('../lib/SealedSecretCRD', () => ({
SealedSecret: {},
}));
import { K8s } from '@kinvolk/headlamp-plugin/lib';
import { DecryptDialog } from './DecryptDialog';
const mockUseGetSecret = vi.mocked(K8s.ResourceClasses.Secret.useGet);
describe('DecryptDialog', () => {
const mockSealedSecret = {
metadata: {
name: 'my-secret',
namespace: 'default',
},
} as never;
beforeEach(() => {
vi.clearAllMocks();
vi.useFakeTimers();
// Mock clipboard
Object.assign(navigator, {
clipboard: { writeText: vi.fn().mockResolvedValue(undefined) },
});
});
afterEach(() => {
vi.useRealTimers();
});
it('should show "Secret Not Found" when secret does not exist', () => {
mockUseGetSecret.mockReturnValue([null, null] as never);
render(
<DecryptDialog sealedSecret={mockSealedSecret} secretKey="password" onClose={vi.fn()} />
);
expect(screen.getByText('Secret Not Found')).toBeDefined();
});
it('should show "Key Not Found" when key does not exist in secret', () => {
mockUseGetSecret.mockReturnValue([{ data: { other: 'value' } }, null] as never);
render(
<DecryptDialog sealedSecret={mockSealedSecret} secretKey="missing-key" onClose={vi.fn()} />
);
expect(screen.getByText('Key Not Found')).toBeDefined();
expect(screen.getByText('missing-key')).toBeDefined();
});
it('should decode and display base64 value', () => {
const encoded = btoa('my-secret-value');
mockUseGetSecret.mockReturnValue([{ data: { password: encoded } }, null] as never);
render(
<DecryptDialog sealedSecret={mockSealedSecret} secretKey="password" onClose={vi.fn()} />
);
expect(screen.getByText(/Decrypted Value: password/)).toBeDefined();
// The value should be in a text field (hidden by default as password type)
expect(screen.getByDisplayValue('my-secret-value')).toBeDefined();
});
it('should show countdown timer', () => {
const encoded = btoa('value');
mockUseGetSecret.mockReturnValue([{ data: { key: encoded } }, null] as never);
render(<DecryptDialog sealedSecret={mockSealedSecret} secretKey="key" onClose={vi.fn()} />);
expect(screen.getByText(/30 seconds/)).toBeDefined();
});
it('should auto-close after countdown', () => {
const encoded = btoa('value');
mockUseGetSecret.mockReturnValue([{ data: { key: encoded } }, null] as never);
const onClose = vi.fn();
render(<DecryptDialog sealedSecret={mockSealedSecret} secretKey="key" onClose={onClose} />);
// Advance 30 seconds
act(() => {
vi.advanceTimersByTime(30000);
});
expect(onClose).toHaveBeenCalled();
});
it('should copy to clipboard', () => {
const encoded = btoa('copy-me');
mockUseGetSecret.mockReturnValue([{ data: { key: encoded } }, null] as never);
render(<DecryptDialog sealedSecret={mockSealedSecret} secretKey="key" onClose={vi.fn()} />);
// Click copy button
const copyButton = screen.getByLabelText('Copy value to clipboard');
fireEvent.click(copyButton);
expect(navigator.clipboard.writeText).toHaveBeenCalledWith('copy-me');
expect(mockEnqueueSnackbar).toHaveBeenCalledWith('Copied to clipboard', {
variant: 'success',
});
});
it('should toggle show/hide value', () => {
const encoded = btoa('toggle-me');
mockUseGetSecret.mockReturnValue([{ data: { key: encoded } }, null] as never);
render(<DecryptDialog sealedSecret={mockSealedSecret} secretKey="key" onClose={vi.fn()} />);
// Initially hidden (password type)
const showButton = screen.getByLabelText('Show secret value');
fireEvent.click(showButton);
// Now should show hide button
expect(screen.getByLabelText('Hide secret value')).toBeDefined();
});
it('should close on Close button click', () => {
mockUseGetSecret.mockReturnValue([null, null] as never);
const onClose = vi.fn();
render(<DecryptDialog sealedSecret={mockSealedSecret} secretKey="key" onClose={onClose} />);
fireEvent.click(screen.getByLabelText('Close dialog'));
expect(onClose).toHaveBeenCalled();
});
it('should show security warning', () => {
const encoded = btoa('value');
mockUseGetSecret.mockReturnValue([{ data: { key: encoded } }, null] as never);
render(<DecryptDialog sealedSecret={mockSealedSecret} secretKey="key" onClose={vi.fn()} />);
expect(screen.getByText(/Security Warning/)).toBeDefined();
});
});