Skip to content

Commit

Permalink
Implement deleting schemas (#366)
Browse files Browse the repository at this point in the history
  • Loading branch information
GneyHabub committed Apr 13, 2021
1 parent d471759 commit 3945845
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 6 deletions.
11 changes: 10 additions & 1 deletion kafka-ui-react-app/src/components/Schemas/Details/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SchemaSubject } from 'generated-sources';
import { ClusterName, SchemaName } from 'redux/interfaces';
import { clusterSchemasPath } from 'lib/paths';
import ClusterContext from 'components/contexts/ClusterContext';
import { useHistory } from 'react-router';
import Breadcrumb from '../../common/Breadcrumb/Breadcrumb';
import SchemaVersion from './SchemaVersion';
import LatestVersionItem from './LatestVersionItem';
Expand All @@ -18,13 +19,15 @@ export interface DetailsProps {
clusterName: ClusterName,
schemaName: SchemaName
) => void;
deleteSchema: (clusterName: ClusterName, subject: string) => Promise<void>;
}

const Details: React.FC<DetailsProps> = ({
subject,
schema,
clusterName,
fetchSchemaVersions,
deleteSchema,
versions,
isFetched,
}) => {
Expand All @@ -33,6 +36,12 @@ const Details: React.FC<DetailsProps> = ({
fetchSchemaVersions(clusterName, subject);
}, [fetchSchemaVersions, clusterName]);

const history = useHistory();
const onDelete = async () => {
await deleteSchema(clusterName, subject);
history.push(clusterSchemasPath(clusterName));
};

return (
<div className="section">
<div className="level">
Expand Down Expand Up @@ -75,7 +84,7 @@ const Details: React.FC<DetailsProps> = ({
className="button is-danger is-small level-item"
type="button"
title="in development"
disabled
onClick={onDelete}
>
Delete
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
getSchema,
getSortedSchemaVersions,
} from 'redux/reducers/schemas/selectors';
import { fetchSchemaVersions } from 'redux/actions';
import { fetchSchemaVersions, deleteSchema } from 'redux/actions';
import Details from './Details';

interface RouteProps {
Expand All @@ -33,6 +33,7 @@ const mapStateToProps = (

const mapDispatchToProps = {
fetchSchemaVersions,
deleteSchema,
};

export default withRouter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe('Details', () => {
schema={schema}
clusterName="Test cluster"
fetchSchemaVersions={jest.fn()}
deleteSchema={jest.fn()}
isFetched
versions={[]}
{...props}
Expand Down Expand Up @@ -100,6 +101,17 @@ describe('Details', () => {
expect(wrapper.find('SchemaVersion').length).toEqual(2);
});

it('calls deleteSchema on button click', () => {
const mockDelete = jest.fn();
const component = mount(
<StaticRouter>
{setupWrapper({ versions, deleteSchema: mockDelete })}
</StaticRouter>
);
component.find('button').at(1).simulate('click');
expect(mockDelete).toHaveBeenCalledTimes(1);
});

it('matches snapshot', () => {
expect(shallow(setupWrapper({ versions }))).toMatchSnapshot();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ exports[`Details View Initial state matches snapshot 1`] = `
</button>
<button
className="button is-danger is-small level-item"
disabled={true}
onClick={[Function]}
title="in development"
type="button"
>
Expand Down Expand Up @@ -196,7 +196,7 @@ exports[`Details View when page with schema versions loaded when schema has vers
</button>
<button
className="button is-danger is-small level-item"
disabled={true}
onClick={[Function]}
title="in development"
type="button"
>
Expand Down Expand Up @@ -334,7 +334,7 @@ exports[`Details View when page with schema versions loaded when versions are em
</button>
<button
className="button is-danger is-small level-item"
disabled={true}
onClick={[Function]}
title="in development"
type="button"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,37 @@ describe('Thunks', () => {
}
});
});

describe('deleteSchema', () => {
it('fires DELETE_SCHEMA__SUCCESS on success', async () => {
fetchMock.deleteOnce(
`/api/clusters/${clusterName}/schemas/${subject}`,
200
);

await store.dispatch(thunks.deleteSchema(clusterName, subject));

expect(store.getActions()).toEqual([
actions.deleteSchemaAction.request(),
actions.deleteSchemaAction.success(subject),
]);
});

it('fires DELETE_SCHEMA__FAILURE on failure', async () => {
fetchMock.deleteOnce(
`/api/clusters/${clusterName}/schemas/${subject}`,
404
);

try {
await store.dispatch(thunks.deleteSchema(clusterName, subject));
} catch (error) {
expect(error.status).toEqual(404);
expect(store.getActions()).toEqual([
actions.deleteSchemaAction.request(),
actions.deleteSchemaAction.failure({}),
]);
}
});
});
});
6 changes: 6 additions & 0 deletions kafka-ui-react-app/src/redux/actions/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ export const createSchemaAction = createAsyncAction(
'POST_SCHEMA__FAILURE'
)<undefined, SchemaSubject, { alert?: FailurePayload }>();

export const deleteSchemaAction = createAsyncAction(
'DELETE_SCHEMA__REQUEST',
'DELETE_SCHEMA__SUCCESS',
'DELETE_SCHEMA__FAILURE'
)<undefined, string, { alert?: FailurePayload }>();

export const dismissAlert = createAction('DISMISS_ALERT')<string>();

export const fetchConnectsAction = createAsyncAction(
Expand Down
22 changes: 22 additions & 0 deletions kafka-ui-react-app/src/redux/actions/thunks/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,25 @@ export const createSchema = (
dispatch(actions.createSchemaAction.failure({ alert }));
}
};

export const deleteSchema = (
clusterName: ClusterName,
subject: string
): PromiseThunkResult => async (dispatch) => {
dispatch(actions.deleteSchemaAction.request());
try {
await schemasApiClient.deleteSchema({
clusterName,
subject,
});
dispatch(actions.deleteSchemaAction.success(subject));
} catch (error) {
const response = await getResponse(error);
const alert: FailurePayload = {
subject: ['schema', subject].join('-'),
title: `Schema ${subject}`,
response,
};
dispatch(actions.deleteSchemaAction.failure({ alert }));
}
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { SchemaSubject, SchemaType } from 'generated-sources';
import {
createSchemaAction,
deleteSchemaAction,
fetchSchemasByClusterNameAction,
fetchSchemaVersionsAction,
} from 'redux/actions';
Expand Down Expand Up @@ -46,4 +48,31 @@ describe('Schemas reducer', () => {
reducer(undefined, createSchemaAction.success(schemaVersionsPayload[0]))
).toMatchSnapshot();
});

it('deletes the schema from the list on DELETE_SCHEMA__SUCCESS', () => {
const schema: SchemaSubject = {
subject: 'name',
version: '1',
id: 1,
schema: '{}',
compatibilityLevel: 'BACKWARD',
schemaType: SchemaType.AVRO,
};
expect(
reducer(
{
byName: {
[schema.subject]: schema,
},
allNames: [schema.subject],
currentSchemaVersions: [],
},
deleteSchemaAction.success(schema.subject)
)
).toEqual({
byName: {},
allNames: [],
currentSchemaVersions: [],
});
});
});
16 changes: 16 additions & 0 deletions kafka-ui-react-app/src/redux/reducers/schemas/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { SchemaSubject } from 'generated-sources';
import { Action, SchemasState } from 'redux/interfaces';
import * as actions from 'redux/actions';
import { getType } from 'typesafe-actions';

export const initialState: SchemasState = {
byName: {},
Expand Down Expand Up @@ -44,6 +46,18 @@ const addToSchemaList = (
return newState;
};

const deleteFromSchemaList = (
state: SchemasState,
payload: string
): SchemasState => {
const newState: SchemasState = {
...state,
};
delete newState.byName[payload];
newState.allNames = newState.allNames.filter((name) => name !== payload);
return newState;
};

const reducer = (state = initialState, action: Action): SchemasState => {
switch (action.type) {
case 'GET_CLUSTER_SCHEMAS__SUCCESS':
Expand All @@ -52,6 +66,8 @@ const reducer = (state = initialState, action: Action): SchemasState => {
return { ...state, currentSchemaVersions: action.payload };
case 'POST_SCHEMA__SUCCESS':
return addToSchemaList(state, action.payload);
case getType(actions.deleteSchemaAction.success):
return deleteFromSchemaList(state, action.payload);
default:
return state;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('topics reducer', () => {
reducer(
{
byName: {
topic,
[topic.name]: topic,
},
allNames: [topic.name],
messages: [],
Expand Down

0 comments on commit 3945845

Please sign in to comment.