Skip to content

Commit

Permalink
DMATF-14 | Allow modification of search form inputs with URL query pa…
Browse files Browse the repository at this point in the history
…rameters (#1898)

* DMATF-14 | Allow modification of search form inputs with URL query parameters

* DMATF-14 | Fix formatting

* DMATF-14 | Fix styling thrown by linter

* DMATF-14 | Run linter fix

* DMATF-14 | Added tests

---------

Co-authored-by: Mateusz <76775507+szczygiel-m@users.noreply.github.com>
  • Loading branch information
mnajborowski and szczygiel-m authored Oct 9, 2024
1 parent 9611ede commit bda2607
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 10 deletions.
5 changes: 5 additions & 0 deletions hermes-console/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ const router = createRouter({
path: '/ui/search',
name: 'search',
component: () => import('@/views/search/SearchView.vue'),
props: (route) => ({
collection: route.query.collection,
filter: route.query.filter,
pattern: route.query.pattern,
}),
},
],
});
Expand Down
43 changes: 43 additions & 0 deletions hermes-console/src/views/search/SearchView.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { computed, ref } from 'vue';
import { createPinia, setActivePinia } from 'pinia';
import { createTestingPiniaWithState } from '@/dummy/store';
import { dummySubscription } from '@/dummy/subscription';
import { dummyTopic } from '@/dummy/topic';
import { expect } from 'vitest';
import { fireEvent, waitFor } from '@testing-library/vue';
import { render } from '@/utils/test-utils';
import { useSearch } from '@/composables/search/useSearch';
import router from '@/router';
import SearchView from '@/views/search/SearchView.vue';
import type { UseSearch } from '@/composables/search/useSearch';

Expand All @@ -21,6 +25,11 @@ const useSearchStub: UseSearch = {
};

describe('SearchView', () => {
beforeEach(() => {
vi.mocked(useSearch).mockReturnValue(useSearchStub);
setActivePinia(createPinia());
});

it('should render subscriptions table when subscriptions are present', () => {
// given
vi.mocked(useSearch).mockReturnValueOnce({
Expand Down Expand Up @@ -110,4 +119,38 @@ describe('SearchView', () => {
expect(queryByText('search.connectionError.title')).not.toBeInTheDocument();
expect(queryByText('search.connectionError.text')).not.toBeInTheDocument();
});

it('should modify form inputs based on passed query parameters', async () => {
await router.push({
path: '/ui/search',
query: { collection: 'topics', filter: 'name', pattern: 'test' },
});

const { getByLabelText } = render(SearchView, {
testPinia: createTestingPiniaWithState(),
global: { plugins: [router] },
});

expect(getByLabelText('collection').value).toBe('topics');
expect(getByLabelText('filter').value).toBe('name');
expect(getByLabelText('regex pattern').value).toBe('test');
});

it('should update query parameters in URL when form inputs are modified', async () => {
const { getByLabelText, getByRole } = render(SearchView, {
testPinia: createTestingPiniaWithState(),
global: { plugins: [router] },
});

await fireEvent.update(getByLabelText('regex pattern'), 'newPattern');
await fireEvent.click(getByRole('button'));

await waitFor(() => {
expect(router.currentRoute.value.query).toEqual({
collection: 'subscriptions',
filter: 'endpoint',
pattern: 'newPattern',
});
});
});
});
76 changes: 66 additions & 10 deletions hermes-console/src/views/search/SearchView.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { ref } from 'vue';
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
import { onMounted, ref } from 'vue';
import { SearchFilter, useSearch } from '@/composables/search/useSearch';
import { useI18n } from 'vue-i18n';
import ConsoleAlert from '@/components/console-alert/ConsoleAlert.vue';
Expand All @@ -8,21 +9,40 @@
import TopicSearchResults from '@/views/search/topic-search-results/TopicSearchResults.vue';
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const searchCollectionValues = ['subscriptions', 'topics'];
const searchCollections = [
{ title: t('search.collection.subscriptions'), value: 'subscriptions' },
{ title: t('search.collection.topics'), value: 'topics' },
{
title: t('search.collection.subscriptions'),
value: searchCollectionValues[0],
},
{ title: t('search.collection.topics'), value: searchCollectionValues[1] },
];
const selectedSearchCollection = ref(searchCollections[0].value);
const selectedSearchCollection = ref(
searchCollectionValues.includes(route.query.collection)
? route.query.collection
: searchCollectionValues[0],
);
const searchFilterValues = [
SearchFilter.ENDPOINT,
SearchFilter.NAME,
SearchFilter.OWNER,
];
const searchFilters = [
{ title: t('search.filter.endpoint'), value: SearchFilter.ENDPOINT },
{ title: t('search.filter.name'), value: SearchFilter.NAME },
{ title: t('search.filter.owner'), value: SearchFilter.OWNER },
{ title: t('search.filter.endpoint'), value: searchFilterValues[0] },
{ title: t('search.filter.name'), value: searchFilterValues[1] },
{ title: t('search.filter.owner'), value: searchFilterValues[2] },
];
const selectedSearchFilter = ref(searchFilters[0].value);
const selectedSearchFilter = ref(
searchFilterValues.includes(route.query.filter)
? route.query.filter
: searchFilterValues[0],
);
const searchPattern = ref('');
const searchPattern = ref(route.query.pattern || '');
const {
topics,
Expand All @@ -33,6 +53,16 @@
error,
} = useSearch();
function updateQueryParams() {
router.push({
query: {
collection: selectedSearchCollection.value,
filter: selectedSearchFilter.value,
pattern: searchPattern.value,
},
});
}
function search() {
if (selectedSearchCollection.value === 'topics') {
subscriptions.value = undefined;
Expand All @@ -44,6 +74,30 @@
throw Error(`Unknown search filter: ${selectedSearchCollection.value}`);
}
}
function searchAndUpdateQueryParams() {
updateQueryParams();
search();
}
onBeforeRouteUpdate((to) => {
selectedSearchCollection.value = searchCollectionValues.includes(
to.query.collection,
)
? to.query.collection
: searchCollectionValues[0];
selectedSearchFilter.value = searchFilterValues.includes(to.query.filter)
? to.query.filter
: searchFilterValues[0];
searchPattern.value = to.query.pattern || '';
search();
});
onMounted(() => {
if (route.query.collection || route.query.filter || route.query.pattern) {
search();
}
});
</script>

<template>
Expand All @@ -57,18 +111,20 @@
<v-row>
<p class="text-h3 mt-16">Search</p>
</v-row>
<v-form @submit.prevent="search">
<v-form @submit.prevent="searchAndUpdateQueryParams">
<v-row class="mt-8">
<v-col md="2" cols="12">
<v-select
v-model="selectedSearchCollection"
label="collection"
:items="searchCollections"
variant="outlined"
></v-select>
</v-col>
<v-col md="2" cols="12">
<v-select
v-model="selectedSearchFilter"
label="filter"
:items="searchFilters"
variant="outlined"
></v-select>
Expand Down

0 comments on commit bda2607

Please sign in to comment.