112 lines
2.9 KiB
TypeScript
112 lines
2.9 KiB
TypeScript
|
|
import { describe, it, expect, vi } from 'vitest';
|
||
|
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||
|
|
import { ThemeProvider } from '@cameleer/design-system';
|
||
|
|
import type { ReactNode } from 'react';
|
||
|
|
import { EnvironmentSwitcherModal } from './EnvironmentSwitcherModal';
|
||
|
|
import type { Environment } from '../api/queries/admin/environments';
|
||
|
|
|
||
|
|
function wrap(ui: ReactNode) {
|
||
|
|
return render(<ThemeProvider>{ui}</ThemeProvider>);
|
||
|
|
}
|
||
|
|
|
||
|
|
const envs: Environment[] = [
|
||
|
|
{
|
||
|
|
id: '11111111-1111-1111-1111-111111111111',
|
||
|
|
slug: 'dev',
|
||
|
|
displayName: 'Development',
|
||
|
|
production: false,
|
||
|
|
enabled: true,
|
||
|
|
defaultContainerConfig: {},
|
||
|
|
jarRetentionCount: 5,
|
||
|
|
color: 'amber',
|
||
|
|
createdAt: '2026-04-22T00:00:00Z',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
id: '22222222-2222-2222-2222-222222222222',
|
||
|
|
slug: 'prod',
|
||
|
|
displayName: 'Production',
|
||
|
|
production: true,
|
||
|
|
enabled: true,
|
||
|
|
defaultContainerConfig: {},
|
||
|
|
jarRetentionCount: 10,
|
||
|
|
color: 'red',
|
||
|
|
createdAt: '2026-04-22T00:00:00Z',
|
||
|
|
},
|
||
|
|
];
|
||
|
|
|
||
|
|
describe('EnvironmentSwitcherModal', () => {
|
||
|
|
it('renders one row per env when open', () => {
|
||
|
|
wrap(
|
||
|
|
<EnvironmentSwitcherModal
|
||
|
|
open
|
||
|
|
onClose={() => {}}
|
||
|
|
envs={envs}
|
||
|
|
value="dev"
|
||
|
|
onPick={() => {}}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(screen.getByText('Development')).toBeInTheDocument();
|
||
|
|
expect(screen.getByText('Production')).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('calls onPick with slug when a row is clicked', () => {
|
||
|
|
const onPick = vi.fn();
|
||
|
|
wrap(
|
||
|
|
<EnvironmentSwitcherModal
|
||
|
|
open
|
||
|
|
onClose={() => {}}
|
||
|
|
envs={envs}
|
||
|
|
value="dev"
|
||
|
|
onPick={onPick}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
fireEvent.click(screen.getByRole('option', { name: /production/i }));
|
||
|
|
expect(onPick).toHaveBeenCalledWith('prod');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('marks the current env with aria-selected', () => {
|
||
|
|
wrap(
|
||
|
|
<EnvironmentSwitcherModal
|
||
|
|
open
|
||
|
|
onClose={() => {}}
|
||
|
|
envs={envs}
|
||
|
|
value="dev"
|
||
|
|
onPick={() => {}}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
const selected = screen.getByRole('option', { name: /development/i });
|
||
|
|
expect(selected).toHaveAttribute('aria-selected', 'true');
|
||
|
|
});
|
||
|
|
|
||
|
|
it('renders empty state when no envs exist', () => {
|
||
|
|
wrap(
|
||
|
|
<EnvironmentSwitcherModal
|
||
|
|
open
|
||
|
|
onClose={() => {}}
|
||
|
|
envs={[]}
|
||
|
|
value={undefined}
|
||
|
|
onPick={() => {}}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(screen.getByText(/no environments/i)).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('forced mode swaps the title and ignores onClose', () => {
|
||
|
|
const onClose = vi.fn();
|
||
|
|
wrap(
|
||
|
|
<EnvironmentSwitcherModal
|
||
|
|
open
|
||
|
|
onClose={onClose}
|
||
|
|
envs={envs}
|
||
|
|
value={undefined}
|
||
|
|
onPick={() => {}}
|
||
|
|
forced
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(screen.getByText(/select an environment/i)).toBeInTheDocument();
|
||
|
|
// Simulate ESC — DS Modal forwards this to onClose, which we wrapped in a no-op.
|
||
|
|
fireEvent.keyDown(document, { key: 'Escape' });
|
||
|
|
expect(onClose).not.toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|