test(deploy): contract test — ConfigTabs disabled gates all inputs
This commit is contained in:
@@ -0,0 +1,269 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
import { ThemeProvider } from '@cameleer/design-system';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import { MonitoringTab } from './MonitoringTab';
|
||||||
|
import { ResourcesTab } from './ResourcesTab';
|
||||||
|
import { VariablesTab } from './VariablesTab';
|
||||||
|
import { SensitiveKeysTab } from './SensitiveKeysTab';
|
||||||
|
import type {
|
||||||
|
MonitoringFormState,
|
||||||
|
ResourcesFormState,
|
||||||
|
VariablesFormState,
|
||||||
|
SensitiveKeysFormState,
|
||||||
|
} from '../hooks/useDeploymentPageState';
|
||||||
|
|
||||||
|
function wrap(ui: ReactNode) {
|
||||||
|
const queryClient = new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: { retry: false },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return render(
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<ThemeProvider>{ui}</ThemeProvider>
|
||||||
|
</QueryClientProvider>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultMonitoring: MonitoringFormState = {
|
||||||
|
engineLevel: 'REGULAR',
|
||||||
|
payloadCaptureMode: 'BOTH',
|
||||||
|
payloadSize: '4',
|
||||||
|
payloadUnit: 'KB',
|
||||||
|
applicationLogLevel: 'INFO',
|
||||||
|
agentLogLevel: 'INFO',
|
||||||
|
metricsEnabled: true,
|
||||||
|
metricsInterval: '60',
|
||||||
|
samplingRate: '1.0',
|
||||||
|
compressSuccess: false,
|
||||||
|
replayEnabled: true,
|
||||||
|
routeControlEnabled: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultResources: ResourcesFormState = {
|
||||||
|
memoryLimit: '512',
|
||||||
|
memoryReserve: '',
|
||||||
|
cpuRequest: '500',
|
||||||
|
cpuLimit: '',
|
||||||
|
ports: [],
|
||||||
|
appPort: '8080',
|
||||||
|
replicas: '1',
|
||||||
|
deployStrategy: 'blue-green',
|
||||||
|
stripPrefix: true,
|
||||||
|
sslOffloading: true,
|
||||||
|
runtimeType: 'auto',
|
||||||
|
customArgs: '',
|
||||||
|
extraNetworks: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultVariables: VariablesFormState = {
|
||||||
|
envVars: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultSensitiveKeys: SensitiveKeysFormState = {
|
||||||
|
sensitiveKeys: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('ConfigTabs disabled contract', () => {
|
||||||
|
describe('MonitoringTab', () => {
|
||||||
|
it('disables all inputs and selects when disabled=true', () => {
|
||||||
|
wrap(
|
||||||
|
<MonitoringTab
|
||||||
|
value={defaultMonitoring}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const textboxes = screen.queryAllByRole('textbox');
|
||||||
|
const comboboxes = screen.queryAllByRole('combobox');
|
||||||
|
|
||||||
|
expect(textboxes.length).toBeGreaterThan(0);
|
||||||
|
expect(comboboxes.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
textboxes.forEach((box) => {
|
||||||
|
expect(box).toBeDisabled();
|
||||||
|
});
|
||||||
|
comboboxes.forEach((cb) => {
|
||||||
|
expect(cb).toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enables inputs when disabled=false', () => {
|
||||||
|
wrap(
|
||||||
|
<MonitoringTab
|
||||||
|
value={defaultMonitoring}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={false}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const textboxes = screen.queryAllByRole('textbox');
|
||||||
|
expect(textboxes.length).toBeGreaterThan(0);
|
||||||
|
textboxes.forEach((box) => {
|
||||||
|
expect(box).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ResourcesTab', () => {
|
||||||
|
it('disables all inputs and selects when disabled=true', () => {
|
||||||
|
wrap(
|
||||||
|
<ResourcesTab
|
||||||
|
value={defaultResources}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={true}
|
||||||
|
isProd={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const textboxes = screen.queryAllByRole('textbox');
|
||||||
|
const comboboxes = screen.queryAllByRole('combobox');
|
||||||
|
|
||||||
|
expect(textboxes.length).toBeGreaterThan(0);
|
||||||
|
expect(comboboxes.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
textboxes.forEach((box) => {
|
||||||
|
expect(box).toBeDisabled();
|
||||||
|
});
|
||||||
|
comboboxes.forEach((cb) => {
|
||||||
|
expect(cb).toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enables inputs when disabled=false', () => {
|
||||||
|
wrap(
|
||||||
|
<ResourcesTab
|
||||||
|
value={defaultResources}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={false}
|
||||||
|
isProd={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const textboxes = screen.queryAllByRole('textbox');
|
||||||
|
expect(textboxes.length).toBeGreaterThan(0);
|
||||||
|
textboxes.forEach((box) => {
|
||||||
|
expect(box).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('VariablesTab', () => {
|
||||||
|
it('disables add and import buttons when disabled=true', () => {
|
||||||
|
wrap(
|
||||||
|
<VariablesTab
|
||||||
|
value={defaultVariables}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttons = screen.queryAllByRole('button');
|
||||||
|
// When disabled, import and clear/add buttons should be disabled
|
||||||
|
// Copy button is always enabled by design
|
||||||
|
const importBtn = buttons.find((btn) => btn.title?.includes('Import'));
|
||||||
|
const clearBtn = buttons.find((btn) => btn.title?.includes('Clear'));
|
||||||
|
expect(importBtn).toBeDisabled();
|
||||||
|
expect(clearBtn).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enables inputs when disabled=false', () => {
|
||||||
|
wrap(
|
||||||
|
<VariablesTab
|
||||||
|
value={defaultVariables}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={false}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const buttons = screen.queryAllByRole('button');
|
||||||
|
const importBtn = buttons.find((btn) => btn.title?.includes('Import'));
|
||||||
|
const clearBtn = buttons.find((btn) => btn.title?.includes('Clear'));
|
||||||
|
expect(importBtn).not.toBeDisabled();
|
||||||
|
expect(clearBtn).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with envVars populated, disables textboxes when disabled=true', () => {
|
||||||
|
const varState: VariablesFormState = {
|
||||||
|
envVars: [
|
||||||
|
{ key: 'TEST_VAR', value: 'test-value' },
|
||||||
|
{ key: 'ANOTHER', value: 'value' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
wrap(
|
||||||
|
<VariablesTab
|
||||||
|
value={varState}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const textboxes = screen.queryAllByRole('textbox');
|
||||||
|
expect(textboxes.length).toBeGreaterThan(0);
|
||||||
|
textboxes.forEach((box) => {
|
||||||
|
expect(box).toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('SensitiveKeysTab', () => {
|
||||||
|
it('disables input and add button when disabled=true', () => {
|
||||||
|
wrap(
|
||||||
|
<SensitiveKeysTab
|
||||||
|
value={defaultSensitiveKeys}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const textboxes = screen.queryAllByRole('textbox');
|
||||||
|
expect(textboxes.length).toBeGreaterThan(0);
|
||||||
|
textboxes.forEach((box) => {
|
||||||
|
expect(box).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
const buttons = screen.queryAllByRole('button');
|
||||||
|
const addButton = buttons.find((btn) => btn.textContent?.includes('Add'));
|
||||||
|
expect(addButton).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enables input when disabled=false', () => {
|
||||||
|
wrap(
|
||||||
|
<SensitiveKeysTab
|
||||||
|
value={defaultSensitiveKeys}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={false}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const textboxes = screen.queryAllByRole('textbox');
|
||||||
|
expect(textboxes.length).toBeGreaterThan(0);
|
||||||
|
textboxes.forEach((box) => {
|
||||||
|
expect(box).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with sensitive keys, disables remove tag buttons when disabled=true', () => {
|
||||||
|
const skState: SensitiveKeysFormState = {
|
||||||
|
sensitiveKeys: ['Authorization', 'X-API-Key', '*password*'],
|
||||||
|
};
|
||||||
|
|
||||||
|
wrap(
|
||||||
|
<SensitiveKeysTab
|
||||||
|
value={skState}
|
||||||
|
onChange={vi.fn()}
|
||||||
|
disabled={true}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Tags have remove buttons that should be disabled
|
||||||
|
const buttons = screen.queryAllByRole('button');
|
||||||
|
// Check that at least some buttons exist (the tag removers)
|
||||||
|
expect(buttons.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user