Added test for consumer group offset hooks

This commit is contained in:
Nir Gazit
2021-01-18 16:13:40 +02:00
parent 4a438d589c
commit a81bc52801
8 changed files with 189 additions and 33 deletions
@@ -17,26 +17,17 @@
import React from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { ConsumerGroupOffsets } from './ConsumerGroupOffsets';
import * as data from './__fixtures__/consumer-group-offsets.json';
import { ConsumerGroupOffsetsResponse } from '../../api/types';
const consumerGroupOffsets = data as ConsumerGroupOffsetsResponse;
describe('ConsumerGroupOffsets', () => {
it('should render consumer group table', async () => {
const rendered = await renderInTestApp(
<ConsumerGroupOffsets
consumerGroup="consumer"
topics={[
{
topic: 'topic1',
partitionId: 1,
topicOffset: '100',
groupOffset: '50',
},
{
topic: 'topic2',
partitionId: 1,
topicOffset: '2340',
groupOffset: '1234',
},
]}
consumerGroup={consumerGroupOffsets.consumerId}
topics={consumerGroupOffsets.offsets}
loading={false}
retry={() => {}}
/>,
@@ -18,8 +18,7 @@ import { Table, TableColumn } from '@backstage/core';
import { Box, Typography } from '@material-ui/core';
import RetryIcon from '@material-ui/icons/Replay';
import React from 'react';
import { useConsumerGroupFromEntity } from './useConsumerGroupsFromEntity';
import { useConsumerGroupOffsets } from './useConsumerGroupOffsets';
import { useConsumerGroupsOffsetsForEntity } from './useConsumerGroupsOffsetsForEntity';
export type TopicPartitionInfo = {
topic: string;
@@ -98,14 +97,7 @@ export const ConsumerGroupOffsets = ({
};
export const KafkaTopicsForConsumer = () => {
const consumerGroup = useConsumerGroupFromEntity();
const [tableProps, { retry }] = useConsumerGroupOffsets(consumerGroup);
const [tableProps, { retry }] = useConsumerGroupsOffsetsForEntity();
return (
<ConsumerGroupOffsets
{...tableProps}
consumerGroup={consumerGroup}
retry={retry}
/>
);
return <ConsumerGroupOffsets {...tableProps} retry={retry} />;
};
@@ -0,0 +1,17 @@
{
"consumerId": "consumer",
"offsets": [
{
"topic": "topic1",
"partitionId": 1,
"topicOffset": "100",
"groupOffset": "50"
},
{
"topic": "topic2",
"partitionId": 1,
"topicOffset": "2340",
"groupOffset": "1234"
}
]
}
@@ -0,0 +1,53 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { useConsumerGroupsForEntity } from './useConsumerGroupsForEntity';
import { EntityContext } from '@backstage/plugin-catalog';
import { Entity } from '@backstage/catalog-model';
describe('useConsumerGroupOffsets', () => {
const entity: Entity = {
apiVersion: 'v1',
kind: 'Component',
metadata: {
name: 'test',
annotations: {
'kafka.apache.org/consumer-groups': 'consumer',
},
},
spec: {
owner: 'guest',
type: 'Website',
lifecycle: 'development',
},
};
const wrapper = ({ children }: PropsWithChildren<{}>) => {
return (
<EntityContext.Provider value={{ entity: entity, loading: false }}>
{children}
</EntityContext.Provider>
);
};
const subject = () => renderHook(useConsumerGroupsForEntity, { wrapper });
it('returns correct consumer group for annotation', async () => {
const { result } = subject();
expect(result.current).toBe('consumer');
});
});
@@ -17,7 +17,7 @@
import { useEntity } from '@backstage/plugin-catalog';
import { KAFKA_CONSUMER_GROUP_ANNOTATION } from '../../constants';
export const useConsumerGroupFromEntity = () => {
export const useConsumerGroupsForEntity = () => {
const { entity } = useEntity();
return entity.metadata.annotations?.[KAFKA_CONSUMER_GROUP_ANNOTATION] ?? '';
@@ -0,0 +1,98 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import { renderHook } from '@testing-library/react-hooks';
import { EntityContext } from '@backstage/plugin-catalog';
import { Entity } from '@backstage/catalog-model';
import * as data from './__fixtures__/consumer-group-offsets.json';
import {
ConsumerGroupOffsetsResponse,
KafkaApi,
kafkaApiRef,
} from '../../api/types';
import { ApiProvider, ApiRegistry, errorApiRef } from '@backstage/core';
import { useConsumerGroupsOffsetsForEntity } from './useConsumerGroupsOffsetsForEntity';
import { when } from 'jest-when';
const consumerGroupOffsets = data as ConsumerGroupOffsetsResponse;
const mockErrorApi: jest.Mocked<typeof errorApiRef.T> = {
post: jest.fn(),
error$: jest.fn(),
};
const mockKafkaApi: jest.Mocked<KafkaApi> = {
getConsumerGroupOffsets: jest.fn(),
};
describe('useConsumerGroupOffsets', () => {
const entity: Entity = {
apiVersion: 'v1',
kind: 'Component',
metadata: {
name: 'test',
annotations: {
'kafka.apache.org/consumer-groups': consumerGroupOffsets.consumerId,
},
},
spec: {
owner: 'guest',
type: 'Website',
lifecycle: 'development',
},
};
const wrapper = ({ children }: PropsWithChildren<{}>) => {
return (
<ApiProvider
apis={ApiRegistry.with(errorApiRef, mockErrorApi).with(
kafkaApiRef,
mockKafkaApi,
)}
>
<EntityContext.Provider value={{ entity: entity, loading: false }}>
{children}
</EntityContext.Provider>
</ApiProvider>
);
};
const subject = () =>
renderHook(useConsumerGroupsOffsetsForEntity, { wrapper });
it('returns correct consumer group for annotation', async () => {
when(mockKafkaApi.getConsumerGroupOffsets)
.calledWith(consumerGroupOffsets.consumerId)
.mockResolvedValue(consumerGroupOffsets);
const { result, waitForNextUpdate } = subject();
await waitForNextUpdate();
const [tableProps] = result.current;
expect(tableProps.consumerGroup).toBe(consumerGroupOffsets.consumerId);
expect(tableProps.topics).toBe(consumerGroupOffsets.offsets);
});
it('posts an error to the error api', async () => {
const error = new Error('error!');
mockKafkaApi.getConsumerGroupOffsets.mockRejectedValueOnce(error);
const { waitForNextUpdate } = subject();
await waitForNextUpdate();
expect(mockErrorApi.post).toHaveBeenCalledWith(error);
});
});
@@ -17,28 +17,31 @@
import { errorApiRef, useApi } from '@backstage/core';
import { useAsyncRetry } from 'react-use';
import { kafkaApiRef } from '../../api/types';
import { useConsumerGroupsForEntity } from './useConsumerGroupsForEntity';
export function useConsumerGroupOffsets(groupId: string) {
export const useConsumerGroupsOffsetsForEntity = () => {
const consumerGroup = useConsumerGroupsForEntity();
const api = useApi(kafkaApiRef);
const errorApi = useApi(errorApiRef);
const { loading, value: topics, retry } = useAsyncRetry(async () => {
try {
const response = await api.getConsumerGroupOffsets(groupId);
const response = await api.getConsumerGroupOffsets(consumerGroup);
return response.offsets;
} catch (e) {
errorApi.post(e);
throw e;
}
}, [api, errorApi, groupId]);
}, [api, errorApi, consumerGroup]);
return [
{
loading,
consumerGroup,
topics,
},
{
retry,
},
] as const;
}
};