Fix for 3152
- Updated yupExtended.ts: Updated schema for minInSyncReplicas and replicationFactor to be mutually exculsive and conditionally maintain replicationFactor >= minInSyncReplicas. - Added unit tests for validation updated logic in yupExtended.ts. - Fixed failing test cases in Edit.spec.ts - Problem : This test case just checks if submit is possible after changes, the test case was changing value for minInSyncReplicas. Due to this the new validation logic was being triggered, the logic failed since it looks like replicationFactor is included in DangerZone which is mocked out as part of this test. - Fix : Removed stubbing/mocking for DangerZone, making sure it renders. Mocked dependencies for DangerZone. Triggering change to a different field than minInSyncReplicas.
This commit is contained in:
parent
727f38401b
commit
81935d99f1
3 changed files with 116 additions and 37 deletions
|
@ -8,6 +8,8 @@ import {
|
|||
useTopicConfig,
|
||||
useTopicDetails,
|
||||
useUpdateTopic,
|
||||
useIncreaseTopicPartitionsCount,
|
||||
useUpdateTopicReplicationFactor,
|
||||
} from 'lib/hooks/api/topics';
|
||||
import { internalTopicPayload, topicConfigPayload } from 'lib/fixtures/topics';
|
||||
|
||||
|
@ -25,14 +27,12 @@ jest.mock('react-router-dom', () => ({
|
|||
useNavigate: () => mockNavigate,
|
||||
}));
|
||||
|
||||
jest.mock('components/Topics/Topic/Edit/DangerZone/DangerZone', () => () => (
|
||||
<>DangerZone</>
|
||||
));
|
||||
|
||||
jest.mock('lib/hooks/api/topics', () => ({
|
||||
useTopicDetails: jest.fn(),
|
||||
useTopicConfig: jest.fn(),
|
||||
useUpdateTopic: jest.fn(),
|
||||
useIncreaseTopicPartitionsCount: jest.fn(),
|
||||
useUpdateTopicReplicationFactor: jest.fn(),
|
||||
}));
|
||||
|
||||
const updateTopicMock = jest.fn();
|
||||
|
@ -59,20 +59,27 @@ describe('Edit Component', () => {
|
|||
isLoading: false,
|
||||
mutateAsync: updateTopicMock,
|
||||
}));
|
||||
(useIncreaseTopicPartitionsCount as jest.Mock).mockImplementation(() => ({
|
||||
isLoading: false,
|
||||
mutateAsync: {},
|
||||
}));
|
||||
(useUpdateTopicReplicationFactor as jest.Mock).mockImplementation(() => ({
|
||||
isLoading: false,
|
||||
mutateAsync: {},
|
||||
}));
|
||||
renderComponent();
|
||||
});
|
||||
|
||||
it('renders DangerZone component', () => {
|
||||
expect(screen.getByText(`DangerZone`)).toBeInTheDocument();
|
||||
expect(screen.getByText(`Danger Zone`)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('submits form correctly', async () => {
|
||||
renderComponent();
|
||||
const btn = screen.getAllByText(/Update topic/i)[0];
|
||||
const field = screen.getByRole('spinbutton', {
|
||||
name: 'Min In Sync Replicas Min In Sync Replicas',
|
||||
const field = screen.getByRole('button', {
|
||||
name: '1 day',
|
||||
});
|
||||
await userEvent.type(field, '1');
|
||||
await userEvent.click(field);
|
||||
await userEvent.click(btn);
|
||||
expect(updateTopicMock).toHaveBeenCalledTimes(1);
|
||||
expect(mockNavigate).toHaveBeenCalledWith('../');
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import { isValidEnum, isValidJsonObject } from 'lib/yupExtended';
|
||||
import {
|
||||
isValidEnum,
|
||||
isValidJsonObject,
|
||||
topicFormValidationSchema,
|
||||
} from 'lib/yupExtended';
|
||||
|
||||
const invalidEnum = `
|
||||
ennum SchemType {
|
||||
|
@ -53,3 +57,36 @@ describe('yup extended', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('topicFormValidationSchema', () => {
|
||||
describe('minInSyncReplicas', () => {
|
||||
it('should fail if minInSyncReplicas > replicationFactor', async () => {
|
||||
const formData = {
|
||||
name: 'my-topic',
|
||||
partitions: 3,
|
||||
replicationFactor: 2,
|
||||
minInSyncReplicas: 3,
|
||||
cleanupPolicy: 'compact',
|
||||
};
|
||||
|
||||
await expect(
|
||||
topicFormValidationSchema.validate(formData)
|
||||
).rejects.toThrow(
|
||||
/Min In Sync Replicas must be less than or equal to Replication Factor/
|
||||
);
|
||||
});
|
||||
it('should pass if minInSyncReplicas <= replicationFactor', async () => {
|
||||
const formData = {
|
||||
name: 'my-topic',
|
||||
partitions: 3,
|
||||
replicationFactor: 3,
|
||||
minInSyncReplicas: 2,
|
||||
cleanupPolicy: 'delete',
|
||||
};
|
||||
|
||||
await expect(topicFormValidationSchema.validate(formData)).resolves.toBe(
|
||||
formData
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -90,33 +90,68 @@ export function cacheTest(
|
|||
yup.addMethod(yup.StringSchema, 'isJsonObject', isJsonObject);
|
||||
yup.addMethod(yup.StringSchema, 'isEnum', isEnum);
|
||||
|
||||
export const topicFormValidationSchema = yup.object().shape({
|
||||
name: yup
|
||||
.string()
|
||||
.max(249)
|
||||
.required()
|
||||
.matches(
|
||||
TOPIC_NAME_VALIDATION_PATTERN,
|
||||
'Only alphanumeric, _, -, and . allowed'
|
||||
export const topicFormValidationSchema = yup.object().shape(
|
||||
{
|
||||
name: yup
|
||||
.string()
|
||||
.max(249)
|
||||
.required()
|
||||
.matches(
|
||||
TOPIC_NAME_VALIDATION_PATTERN,
|
||||
'Only alphanumeric, _, -, and . allowed'
|
||||
),
|
||||
partitions: yup
|
||||
.number()
|
||||
.min(1)
|
||||
.max(2147483647)
|
||||
.required()
|
||||
.typeError('Number of partitions is required and must be a number'),
|
||||
replicationFactor: yup.lazy((value) => {
|
||||
if (value && value !== '') {
|
||||
return yup.number().when('minInSyncReplicas', {
|
||||
is: (val) => val && val !== '',
|
||||
then: () =>
|
||||
yup
|
||||
.number()
|
||||
.min(
|
||||
yup.ref('minInSyncReplicas'),
|
||||
'Replication Factor must be greater than Min In Sync Replicas'
|
||||
)
|
||||
.required(),
|
||||
otherwise: () => yup.number().min(0),
|
||||
});
|
||||
}
|
||||
return yup.string();
|
||||
}),
|
||||
minInSyncReplicas: yup.lazy((value) => {
|
||||
if (value && value !== '') {
|
||||
return yup.number().when('replicationFactor', {
|
||||
is: (val) => val && val !== '',
|
||||
then: () =>
|
||||
yup
|
||||
.number()
|
||||
.max(
|
||||
yup.ref('replicationFactor'),
|
||||
'Min In Sync Replicas must be less than or equal to Replication Factor'
|
||||
)
|
||||
.required(),
|
||||
otherwise: () => yup.number().max(0),
|
||||
});
|
||||
}
|
||||
return yup.string();
|
||||
}),
|
||||
cleanupPolicy: yup.string().required(),
|
||||
retentionMs: yup.string(),
|
||||
retentionBytes: yup.number(),
|
||||
maxMessageBytes: yup.string(),
|
||||
customParams: yup.array().of(
|
||||
yup.object().shape({
|
||||
name: yup.string().required('Custom parameter is required'),
|
||||
value: yup.string().required('Value is required'),
|
||||
})
|
||||
),
|
||||
partitions: yup
|
||||
.number()
|
||||
.min(1)
|
||||
.max(2147483647)
|
||||
.required()
|
||||
.typeError('Number of partitions is required and must be a number'),
|
||||
replicationFactor: yup.string(),
|
||||
minInSyncReplicas: yup.string(),
|
||||
cleanupPolicy: yup.string().required(),
|
||||
retentionMs: yup.string(),
|
||||
retentionBytes: yup.number(),
|
||||
maxMessageBytes: yup.string(),
|
||||
customParams: yup.array().of(
|
||||
yup.object().shape({
|
||||
name: yup.string().required('Custom parameter is required'),
|
||||
value: yup.string().required('Value is required'),
|
||||
})
|
||||
),
|
||||
});
|
||||
},
|
||||
['minInSyncReplicas', 'replicationFactor']
|
||||
);
|
||||
|
||||
export default yup;
|
||||
|
|
Loading…
Add table
Reference in a new issue