Skip to content

Commit

Permalink
feat: migrate query suggestions module to composition api (#1497)
Browse files Browse the repository at this point in the history
Co-authored-by: Jose A. Cabaneros <[email protected]>
Co-authored-by: Diego Pascual <[email protected]>
  • Loading branch information
3 people authored Jun 12, 2024
1 parent 34fb857 commit 4a9c742
Show file tree
Hide file tree
Showing 14 changed files with 3,057 additions and 8,517 deletions.
2 changes: 1 addition & 1 deletion packages/_vue3-migration-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@vueuse/core": "~10.7.1",
"vue": "^3.4.22",
"vue-router": "^4.3.0",
"vuex": "^4.1.0"
"vuex": "4.0.2"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
Expand Down
10 changes: 8 additions & 2 deletions packages/_vue3-migration-test/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { XComponentsAdapter } from '@empathyco/x-types';
import { QuerySuggestionsRequest, XComponentsAdapter } from '@empathyco/x-types';
import { Component, configureCompat, createApp } from 'vue';
import { createStore } from 'vuex';
import { xPlugin } from '../../x-components/src/plugins/x-plugin';
import { getQuerySuggestionsStub } from '../../x-components/src/__stubs__/query-suggestions-stubs.factory';
import App from './App.vue';
import router from './router';
import { facetsXModule, nextQueriesXModule, scrollXModule, searchXModule } from './';
Expand All @@ -26,7 +27,12 @@ if (VUE_COMPAT_MODE === 2) {
});
}

const adapter = {} as XComponentsAdapter;
const adapter = {
querySuggestions: (request: QuerySuggestionsRequest) =>
new Promise(resolve => {
resolve({ suggestions: getQuerySuggestionsStub(request.query, 5) });
})
} as XComponentsAdapter;

const store = createStore({});

Expand Down
8 changes: 7 additions & 1 deletion packages/_vue3-migration-test/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import {
TestBaseKeyboardNavigation,
TestPartialResultsList,
TestBaseEventsModal,
TestBaseIdModal
TestBaseIdModal,
TestQuerySuggestions
} from './';

const routes = [
Expand Down Expand Up @@ -194,6 +195,11 @@ const routes = [
path: '/test-base-id-modal',
name: 'TestBaseIdModal',
component: TestBaseIdModal
},
{
path: '/query-suggestions',
name: 'QuerySuggestions',
component: TestQuerySuggestions
}
];

Expand Down
4 changes: 4 additions & 0 deletions packages/_vue3-migration-test/src/x-modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ export * from './search';
export * from './search-box';
export { default as TestElementsList } from './test-elements-list.vue';
export * from './scroll';
<<<<<<< feat/EMP-4163-migrate-query-suggestions-module-to-composition-api
export * from './query-suggestions';
=======
export * from './history-queries';
>>>>>>> main
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as TestQuerySuggestions } from './test-query-suggestions.vue';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<SearchInput />
<QuerySuggestions />
</template>

<script setup>
import SearchInput from '../../../../../x-components/src/x-modules/search-box/components/search-input.vue';
import QuerySuggestions from '../../../../../x-components/src/x-modules/query-suggestions/components/query-suggestions.vue';
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components';
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('testing plugin alias', () => {
identifierResults: undefined,
nextQueries: undefined,
popularSearches: undefined,
querySuggestions: undefined,
querySuggestions: 'initial', // It is already registered by the `querySuggestionsXModule` import itself
recommendations: undefined,
relatedTags: undefined,
search: undefined
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Suggestion } from '@empathyco/x-types';
import { DeepPartial } from '@empathyco/x-utils';
import { createLocalVue, mount, Wrapper } from '@vue/test-utils';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex, { Store } from 'vuex';
import { createQuerySuggestion } from '../../../../__stubs__/query-suggestions-stubs.factory';
import { getDataTestSelector, installNewXPlugin } from '../../../../__tests__/utils';
Expand All @@ -15,50 +14,49 @@ import { resetXQuerySuggestionsStateWith } from './utils';
function renderQuerySuggestion({
suggestion = createQuerySuggestion('baileys'),
query = '',
template = '<QuerySuggestion v-bind="$attrs"/>'
}: RenderQuerySuggestionOptions = {}): RenderQuerySuggestionApi {
template = '<QuerySuggestion :suggestion="suggestion"/>'
} = {}) {
const localVue = createLocalVue();
localVue.use(Vuex);
const store = new Store<DeepPartial<RootXStoreState>>({});

installNewXPlugin({ store, initialXModules: [querySuggestionsXModule] }, localVue);
resetXQuerySuggestionsStateWith(store, { query });

const wrapper = mount(
{
template,
inheritAttrs: false,
components: {
QuerySuggestion
}
components: { QuerySuggestion },
props: ['suggestion']
},
{
localVue,
propsData: { suggestion },
store
store,
propsData: { suggestion }
}
);

return {
wrapper: wrapper.findComponent(QuerySuggestion),
suggestion,
emitSpy: jest.spyOn(XPlugin.bus, 'emit'),
getMatchingPart() {
return wrapper.get(getDataTestSelector('matching-part'));
}
};
getMatchingPart: () => wrapper.get(getDataTestSelector('matching-part'))
} as const;
}

describe('testing query-suggestion component', () => {
it('is an XComponent that belongs to the query suggestions', () => {
const { wrapper } = renderQuerySuggestion();
expect(isXComponent(wrapper.vm)).toEqual(true);

expect(isXComponent(wrapper.vm)).toBeTruthy();
expect(getXComponentXModuleName(wrapper.vm)).toEqual('querySuggestions');
});

it('renders the suggestion received as prop', () => {
const { wrapper } = renderQuerySuggestion({
suggestion: createQuerySuggestion('milk')
});

expect(wrapper.text()).toEqual('milk');
});

Expand Down Expand Up @@ -97,33 +95,12 @@ describe('testing query-suggestion component', () => {
const { wrapper } = renderQuerySuggestion({
suggestion: createQuerySuggestion('baileys'),
template: `
<QuerySuggestion v-bind="$attrs" #default="{ suggestion }">
<QuerySuggestion :suggestion="suggestion" #default="{ suggestion }">
<span>🔍</span>
<span>{{ suggestion.query }}</span>
</QuerySuggestion>
`
</QuerySuggestion>`
});

expect(wrapper.text()).toEqual('🔍 baileys');
});
});

interface RenderQuerySuggestionOptions {
/** The suggestion data to render. */
suggestion?: Suggestion;
/** The query that the suggestions belong to. */
query?: string;
/** The template to render. */
template?: string;
}

interface RenderQuerySuggestionApi {
/** Testing wrapper of the {@link QuerySuggestion} component. */
wrapper: Wrapper<Vue>;
/** Retrieves the wrapper that matches the query in the {@link QuerySuggestion} component. */
getMatchingPart: () => Wrapper<Vue>;
/** The {@link XBus.emit} spy. */
emitSpy: jest.SpyInstance;
/** Rendered {@link Suggestion} model data. */
suggestion: Suggestion;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Suggestion } from '@empathyco/x-types';
import { DeepPartial } from '@empathyco/x-utils';
import { createLocalVue, mount, Wrapper, WrapperArray } from '@vue/test-utils';
import { createLocalVue, mount } from '@vue/test-utils';
import Vuex, { Store } from 'vuex';
import { createQuerySuggestion } from '../../../../__stubs__/query-suggestions-stubs.factory';
import { getDataTestSelector, installNewXPlugin } from '../../../../__tests__/utils';
Expand All @@ -16,54 +15,48 @@ function renderQuerySuggestions({
createQuerySuggestion('milk chocolate'),
createQuerySuggestion('chocolate milk')
],
maxItemsToRender,
maxItemsToRender = 5,
template = '<QuerySuggestions v-bind="$attrs" />'
}: RenderQuerySuggestionsOptions = {}): RenderQuerySuggestionsApi {
} = {}) {
const localVue = createLocalVue();
localVue.use(Vuex);
const store = new Store<DeepPartial<RootXStoreState>>({});

installNewXPlugin({ store, initialXModules: [querySuggestionsXModule] }, localVue);
resetXQuerySuggestionsStateWith(store, { suggestions });

const wrapper = mount(
{
template,
inheritAttrs: false,
components: {
QuerySuggestions
}
components: { QuerySuggestions }
},
{
localVue,
store,
propsData: {
maxItemsToRender
}
propsData: { maxItemsToRender }
}
);

return {
wrapper: wrapper.findComponent(QuerySuggestions),
suggestions,
async setMaxItemsToRender(max) {
return await wrapper.setProps({ maxItemsToRender: max });
},
getSuggestionItemWrappers() {
return wrapper.findAll(getDataTestSelector('suggestion-item'));
}
getSuggestionItemWrappers: () => wrapper.findAll(getDataTestSelector('suggestion-item'))
};
}

describe('testing Query Suggestions component', () => {
it('is an XComponent that belongs to the query suggestions module', () => {
const { wrapper } = renderQuerySuggestions();
expect(isXComponent(wrapper.vm)).toEqual(true);

expect(isXComponent(wrapper.vm)).toBeTruthy();
expect(getXComponentXModuleName(wrapper.vm)).toEqual('querySuggestions');
});

it('does not render anything when suggestions are empty', () => {
const { wrapper } = renderQuerySuggestions({ suggestions: [] });
expect(wrapper.html()).toBe('');

expect(wrapper.html()).toEqual('');
});

it('renders the state list of suggestions', () => {
Expand All @@ -87,8 +80,7 @@ describe('testing Query Suggestions component', () => {
<span>🔍</span>
<span>{{ suggestion.query }}</span>
</button>
</QuerySuggestions>
`
</QuerySuggestions>`
});

const suggestionItemWrappers = getSuggestionItemWrappers();
Expand All @@ -108,8 +100,7 @@ describe('testing Query Suggestions component', () => {
<QuerySuggestions #suggestion-content="{ suggestion }">
<span>🔍</span>
<span>{{ suggestion.query }}</span>
</QuerySuggestions>
`
</QuerySuggestions>`
});

const suggestionItemWrappers = getSuggestionItemWrappers();
Expand All @@ -120,9 +111,8 @@ describe('testing Query Suggestions component', () => {
});
});

// eslint-disable-next-line max-len
it('renders at most the number of QuerySuggestion defined by `maxItemsToRender` prop', async () => {
const { getSuggestionItemWrappers, setMaxItemsToRender, suggestions } = renderQuerySuggestions({
const { wrapper, getSuggestionItemWrappers, suggestions } = renderQuerySuggestions({
suggestions: [
createQuerySuggestion('shirt'),
createQuerySuggestion('jeans'),
Expand All @@ -131,33 +121,13 @@ describe('testing Query Suggestions component', () => {
]
});

await setMaxItemsToRender(suggestions.length - 1);
await wrapper.setProps({ maxItemsToRender: suggestions.length - 1 });
expect(getSuggestionItemWrappers().wrappers).toHaveLength(suggestions.length - 1);

await setMaxItemsToRender(suggestions.length);
await wrapper.setProps({ maxItemsToRender: suggestions.length });
expect(getSuggestionItemWrappers().wrappers).toHaveLength(suggestions.length);

await setMaxItemsToRender(suggestions.length + 1);
await wrapper.setProps({ maxItemsToRender: suggestions.length });
expect(getSuggestionItemWrappers().wrappers).toHaveLength(suggestions.length);
});
});

interface RenderQuerySuggestionsOptions {
/** The suggestions list to render. */
suggestions?: Suggestion[];
/** The maximum number of items to render. */
maxItemsToRender?: string;
/** The template to render. */
template?: string;
}

interface RenderQuerySuggestionsApi {
/** QuerySuggestions component testing wrapper. */
wrapper: Wrapper<Vue>;
/** Retrieves the list item of each suggestion. */
getSuggestionItemWrappers: () => WrapperArray<Vue>;
/** Updates the maximum number of items to render. */
setMaxItemsToRender: (max: number) => Promise<void>;
/** Rendered suggestions data. */
suggestions: Suggestion[];
}
Loading

0 comments on commit 4a9c742

Please sign in to comment.