Skip to content

Commit

Permalink
Hermes console vue move offsets (#1708)
Browse files Browse the repository at this point in the history
  • Loading branch information
moscicky authored Aug 28, 2023
1 parent 5c6c9ae commit 0d705a1
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 14 deletions.
4 changes: 4 additions & 0 deletions hermes-console-vue/json-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ server.post('/query/subscriptions', (req, res) => {
res.jsonp(subscriptions);
});

server.post('/topics/*/subscriptions/*/moveOffsetsToTheEnd', (req, res) => {
res.sendStatus(200);
});

const router = jsonServer.router('json-server/db.json');
server.use(router);

Expand Down
9 changes: 9 additions & 0 deletions hermes-console-vue/src/api/hermes-client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,12 @@ export function querySubscriptions(
export function fetchRoles(path: string): ResponsePromise<Role[]> {
return axios.get<Role[]>(path);
}

export function moveSubscriptionOffsets(
topicName: string,
subscription: string,
): ResponsePromise<null> {
return axios.post<null>(
`/topics/${topicName}/subscriptions/${subscription}/moveOffsetsToTheEnd`,
);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { afterEach } from 'vitest';
import { afterEach, expect } from 'vitest';
import { createTestingPinia } from '@pinia/testing';
import { dummyConsumerGroups } from '@/dummy/consumerGroups';
import { dummySubscription } from '@/dummy/subscription';
import { dummyTopic } from '@/dummy/topic';
import {
fetchConsumerGroupsErrorHandler,
fetchConsumerGroupsHandler,
moveSubscriptionOffsetsHandler,
} from '@/mocks/handlers';
import { setActivePinia } from 'pinia';
import { setupServer } from 'msw/node';
import { useConsumerGroups } from '@/composables/consumer-groups/use-consumer-groups/useConsumerGroups';
import { useNotificationsStore } from '@/store/app-notifications/useAppNotifications';
import { waitFor } from '@testing-library/vue';

describe('useConsumerGroups', () => {
Expand All @@ -22,6 +26,14 @@ describe('useConsumerGroups', () => {
}),
);

const pinia = createTestingPinia({
fakeApp: true,
});

beforeEach(() => {
setActivePinia(pinia);
});

afterEach(() => {
server.resetHandlers();
});
Expand Down Expand Up @@ -66,4 +78,68 @@ describe('useConsumerGroups', () => {
expect(error.value.fetchConsumerGroups).not.toBeNull();
});
});

it('should show message that moving offsets was successful', async () => {
// given
server.use(
moveSubscriptionOffsetsHandler({
topicName,
subscriptionName,
statusCode: 200,
}),
);
server.listen();
const notificationsStore = useNotificationsStore();
const dispatchNotification = vi.spyOn(
notificationsStore,
'dispatchNotification',
);

const { moveOffsets } = useConsumerGroups(topicName, subscriptionName);

// when
moveOffsets();

// then
await waitFor(() => {
expect(dispatchNotification).toHaveBeenLastCalledWith(
expect.objectContaining({
type: 'success',
title: 'notifications.subscriptionOffsets.move.success',
}),
);
});
});

it('should show message that moving offsets was unsuccessful', async () => {
// given
server.use(
moveSubscriptionOffsetsHandler({
topicName,
subscriptionName,
statusCode: 500,
}),
);
server.listen();

const notificationsStore = useNotificationsStore();
const dispatchNotification = vi.spyOn(
notificationsStore,
'dispatchNotification',
);
const { moveOffsets } = useConsumerGroups(topicName, subscriptionName);

// when
moveOffsets();

// then
await waitFor(() => {
expect(dispatchNotification).toHaveBeenLastCalledWith(
expect.objectContaining({
type: 'error',
title: 'notifications.subscriptionOffsets.move.failure',
}),
);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { fetchConsumerGroups as getConsumerGroups } from '@/api/hermes-client';
import {
fetchConsumerGroups as getConsumerGroups,
moveSubscriptionOffsets,
} from '@/api/hermes-client';
import { ref } from 'vue';
import { useGlobalI18n } from '@/i18n';
import { useNotificationsStore } from '@/store/app-notifications/useAppNotifications';
import type { ConsumerGroup } from '@/api/consumer-group';
import type { Ref } from 'vue';

export interface UseConsumerGroups {
consumerGroups: Ref<ConsumerGroup[] | undefined>;
moveOffsets: () => void;
loading: Ref<boolean>;
error: Ref<UseConsumerGroupsErrors>;
}
Expand Down Expand Up @@ -36,10 +42,39 @@ export function useConsumerGroups(
}
};

const moveOffsets = async () => {
const notificationsStore = useNotificationsStore();
try {
await moveSubscriptionOffsets(topicName, subscriptionName);
await notificationsStore.dispatchNotification({
title: useGlobalI18n().t(
'notifications.subscriptionOffsets.move.success',
{
subscriptionName,
},
),
text: '',
type: 'success',
});
} catch (e) {
await notificationsStore.dispatchNotification({
title: useGlobalI18n().t(
'notifications.subscriptionOffsets.move.failure',
{
subscriptionName,
},
),
text: (e as Error).message,
type: 'error',
});
}
};

fetchConsumerGroups();

return {
consumerGroups,
moveOffsets,
loading,
error,
};
Expand Down
13 changes: 13 additions & 0 deletions hermes-console-vue/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createI18n } from 'vue-i18n';
import messages from '@/i18n/messages';

export const i18n = createI18n({
legacy: false,
locale: 'en-US',
fallbackLocale: 'en-US',
messages: messages,
});

export function useGlobalI18n() {
return i18n.global;
}
12 changes: 12 additions & 0 deletions hermes-console-vue/src/i18n/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,10 @@ const en_US = {
reason: 'Reason',
timestamp: 'Timestamp',
},
moveOffsets: {
tooltip: 'Move subscription offsets to the end',
button: 'MOVE OFFSETS',
},
},
search: {
collection: {
Expand Down Expand Up @@ -511,6 +515,14 @@ const en_US = {
},
},
},
notifications: {
subscriptionOffsets: {
move: {
success: 'Moved offsets for subscription {subscriptionName}',
failure: 'Failed to move offsets for subscription {subscriptionName}',
},
},
},
};

export default en_US;
12 changes: 1 addition & 11 deletions hermes-console-vue/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import '@mdi/font/css/materialdesignicons.css';
import 'vuetify/styles';
import { aliases, mdi } from 'vuetify/iconsets/mdi';
import { createApp } from 'vue';
import { createI18n } from 'vue-i18n';
import { createPinia } from 'pinia';
import { createVuetify } from 'vuetify';
import { i18n } from '@/i18n';
import App from './App.vue';
import axios from 'axios';
import messages from '@/i18n/messages';
import piniaPluginPersistedState from 'pinia-plugin-persistedstate';
import router from './router';

Expand Down Expand Up @@ -48,13 +47,6 @@ const vuetify = createVuetify({
},
});

const i18n = createI18n({
legacy: false,
locale: 'en-US',
fallbackLocale: 'en-US',
messages: messages,
});

const store = createPinia();

store.use(piniaPluginPersistedState);
Expand All @@ -67,5 +59,3 @@ app.use(router);
app.use(store);

app.mount('#app');

export default i18n;
16 changes: 16 additions & 0 deletions hermes-console-vue/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,19 @@ export const fetchGroupInconsistenciesErrorHandler = ({
rest.get(`${url}/consistency/inconsistencies/groups`, (req, res, ctx) => {
return res(ctx.status(errorCode), ctx.json(undefined));
});

export const moveSubscriptionOffsetsHandler = ({
topicName,
subscriptionName,
statusCode,
}: {
topicName: string;
subscriptionName: string;
statusCode: number;
}) =>
rest.post(
`${url}/topics/${topicName}/subscriptions/${subscriptionName}/moveOffsetsToTheEnd`,
(req, res, ctx) => {
return res(ctx.status(statusCode), ctx.json(undefined));
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ vi.mock('@/composables/consumer-groups/use-consumer-groups/useConsumerGroups');

const useConsumerGroupsStub: UseConsumerGroups = {
consumerGroups: ref(dummyConsumerGroups),
moveOffsets: () => {},
loading: ref(false),
error: ref({
fetchConsumerGroups: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
const params = route.params as Record<string, string>;
const { subscriptionId, topicId, groupId } = params;
const { consumerGroups, loading, error } = useConsumerGroups(
const { consumerGroups, moveOffsets, loading, error } = useConsumerGroups(
topicId,
subscriptionId,
);
Expand Down Expand Up @@ -64,6 +64,14 @@
{{ $t('consumerGroups.title') }}
</p>
</v-col>
<v-col md="2" class="text-right">
<v-btn color="red" @click="moveOffsets">
{{ $t('subscription.moveOffsets.button') }}
<v-tooltip activator="parent" location="left">{{
$t('subscription.moveOffsets.tooltip')
}}</v-tooltip>
</v-btn>
</v-col>
</v-row>
<v-row dense v-if="consumerGroups">
<v-col>
Expand Down
10 changes: 10 additions & 0 deletions hermes-console-vue/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import '@testing-library/jest-dom';
import { useGlobalI18n } from './src/i18n';
import { useI18n } from 'vue-i18n';
import { vi } from 'vitest';

/*
* Mock browser-specific elements.
*/
vi.mock('./src/i18n');
global.ResizeObserver = vi.fn(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
Expand All @@ -26,3 +28,11 @@ vi.mocked(useI18n, {
}).mockReturnValue({
t: (key) => key,
});

vi.mocked(useGlobalI18n, {
partial: true,
deep: true,
}).mockReturnValue({
// @ts-ignore
t: (key) => key,
});

0 comments on commit 0d705a1

Please sign in to comment.