From a89fb5179de040695f13d56f43de50917e1c7f97 Mon Sep 17 00:00:00 2001 From: lauramargar <114984466+lauramargar@users.noreply.github.com> Date: Thu, 9 May 2024 11:18:59 +0200 Subject: [PATCH] feat: migrate `ItemsListInjection` mixin (#1460) --- packages/_vue3-migration-test/src/main.ts | 4 + packages/_vue3-migration-test/src/router.ts | 6 + .../src/x-modules/index.ts | 1 + .../src/x-modules/next-queries/index.ts | 1 + .../src/x-modules/next-queries/x-module.ts | 13 + .../src/x-modules/search/index.ts | 1 + .../src/x-modules/search/x-module.ts | 17 + .../src/x-modules/test-elements-list.vue | 39 ++ .../x-components/src/components/base-grid.vue | 43 ++- packages/x-components/src/components/index.ts | 1 - .../components/items-list-injection.mixin.ts | 45 --- .../src/components/items-list.vue | 99 +++-- .../src/components/location-provider.vue | 2 +- .../__tests__/next-queries-list.spec.ts | 49 ++- .../components/next-queries-list.vue | 353 ++++++++++-------- .../components/__tests__/banners-list.spec.ts | 49 ++- .../__tests__/promoteds-list.spec.ts | 49 ++- .../components/__tests__/results-list.spec.ts | 59 +-- .../search/components/banners-list.vue | 233 +++++++----- .../search/components/promoteds-list.vue | 143 ++++--- .../search/components/results-list.vue | 207 +++++----- .../x-components/tests/unit/base-grid.spec.ts | 3 +- 22 files changed, 824 insertions(+), 593 deletions(-) create mode 100644 packages/_vue3-migration-test/src/x-modules/next-queries/index.ts create mode 100644 packages/_vue3-migration-test/src/x-modules/next-queries/x-module.ts create mode 100644 packages/_vue3-migration-test/src/x-modules/search/x-module.ts create mode 100644 packages/_vue3-migration-test/src/x-modules/test-elements-list.vue delete mode 100644 packages/x-components/src/components/items-list-injection.mixin.ts diff --git a/packages/_vue3-migration-test/src/main.ts b/packages/_vue3-migration-test/src/main.ts index bf9c6ba6cb..52ed2ba47f 100644 --- a/packages/_vue3-migration-test/src/main.ts +++ b/packages/_vue3-migration-test/src/main.ts @@ -4,6 +4,8 @@ import { createStore } from 'vuex'; import { xPlugin } from '../../x-components/src/plugins/x-plugin'; import App from './App.vue'; import router from './router'; +import { searchXModule } from './x-modules/search/x-module'; +import { nextQueriesXModule } from './x-modules/next-queries/x-module'; import { scrollXModule } from './x-modules/scroll/x-module'; // Warnings that cannot be solved in Vue 2 (a.k.a. breaking changes) are suppressed @@ -35,6 +37,8 @@ createApp(App as Component) adapter, store, __PRIVATE__xModules: { + search: searchXModule, + nextQueries: nextQueriesXModule, scroll: scrollXModule } }) diff --git a/packages/_vue3-migration-test/src/router.ts b/packages/_vue3-migration-test/src/router.ts index a19f19f3a4..b2fbc93b16 100644 --- a/packages/_vue3-migration-test/src/router.ts +++ b/packages/_vue3-migration-test/src/router.ts @@ -8,6 +8,7 @@ import { TestSortDropdown, TestSortList, TestSortPickerList, + TestElementsList, TestScroll, TestBaseColumnPickerDropdown } from './'; @@ -62,6 +63,11 @@ const routes = [ path: '/sort-picker-list', name: 'SortPickerList', component: TestSortPickerList + }, + { + path: '/elements-list', + name: 'ElementsList', + component: TestElementsList } ]; diff --git a/packages/_vue3-migration-test/src/x-modules/index.ts b/packages/_vue3-migration-test/src/x-modules/index.ts index 0778e03578..9eb244b491 100644 --- a/packages/_vue3-migration-test/src/x-modules/index.ts +++ b/packages/_vue3-migration-test/src/x-modules/index.ts @@ -1,2 +1,3 @@ export * from './search'; +export { default as TestElementsList } from './test-elements-list.vue'; export * from './scroll'; diff --git a/packages/_vue3-migration-test/src/x-modules/next-queries/index.ts b/packages/_vue3-migration-test/src/x-modules/next-queries/index.ts new file mode 100644 index 0000000000..36ff5e471c --- /dev/null +++ b/packages/_vue3-migration-test/src/x-modules/next-queries/index.ts @@ -0,0 +1 @@ +export * from './x-module'; diff --git a/packages/_vue3-migration-test/src/x-modules/next-queries/x-module.ts b/packages/_vue3-migration-test/src/x-modules/next-queries/x-module.ts new file mode 100644 index 0000000000..95baf4d7e3 --- /dev/null +++ b/packages/_vue3-migration-test/src/x-modules/next-queries/x-module.ts @@ -0,0 +1,13 @@ +import { getNextQueriesStub } from '../../../../x-components/src/__stubs__/next-queries-stubs.factory'; +import { PrivateXModuleOptions } from '../../../../x-components/src/plugins'; +import { NextQueriesXModule } from '../../../../x-components/src/x-modules/next-queries'; + +export const nextQueriesXModule = { + storeModule: { + state: { + query: 'dress', + nextQueries: getNextQueriesStub(), + status: 'success' + } + } +} as PrivateXModuleOptions; diff --git a/packages/_vue3-migration-test/src/x-modules/search/index.ts b/packages/_vue3-migration-test/src/x-modules/search/index.ts index 07635cbbc8..38da673ebb 100644 --- a/packages/_vue3-migration-test/src/x-modules/search/index.ts +++ b/packages/_vue3-migration-test/src/x-modules/search/index.ts @@ -1 +1,2 @@ export * from './components'; +export * from './x-module'; diff --git a/packages/_vue3-migration-test/src/x-modules/search/x-module.ts b/packages/_vue3-migration-test/src/x-modules/search/x-module.ts new file mode 100644 index 0000000000..dae572726c --- /dev/null +++ b/packages/_vue3-migration-test/src/x-modules/search/x-module.ts @@ -0,0 +1,17 @@ +import { getResultsStub } from '../../../../x-components/src/__stubs__/results-stubs.factory'; +import { getBannersStub } from '../../../../x-components/src/__stubs__/banners-stubs.factory'; +import { getPromotedsStub } from '../../../../x-components/src/__stubs__/promoteds-stubs.factory'; +import { PrivateXModuleOptions } from '../../../../x-components/src/plugins'; +import { SearchXModule } from '../../../../x-components/src/x-modules/search'; + +export const searchXModule = { + storeModule: { + state: { + query: 'dress', + results: getResultsStub(10), + promoteds: getPromotedsStub(), + banners: getBannersStub(), + status: 'success' + } + } +} as PrivateXModuleOptions; diff --git a/packages/_vue3-migration-test/src/x-modules/test-elements-list.vue b/packages/_vue3-migration-test/src/x-modules/test-elements-list.vue new file mode 100644 index 0000000000..6312c90e66 --- /dev/null +++ b/packages/_vue3-migration-test/src/x-modules/test-elements-list.vue @@ -0,0 +1,39 @@ + + + diff --git a/packages/x-components/src/components/base-grid.vue b/packages/x-components/src/components/base-grid.vue index ca0e2a30a8..3f58af7c02 100644 --- a/packages/x-components/src/components/base-grid.vue +++ b/packages/x-components/src/components/base-grid.vue @@ -19,7 +19,7 @@ the item using that slot composition to render. @binding {item} item - Item to render --> - + - diff --git a/packages/x-components/src/x-modules/search/components/__tests__/banners-list.spec.ts b/packages/x-components/src/x-modules/search/components/__tests__/banners-list.spec.ts index 858e74acff..d382905966 100644 --- a/packages/x-components/src/x-modules/search/components/__tests__/banners-list.spec.ts +++ b/packages/x-components/src/x-modules/search/components/__tests__/banners-list.spec.ts @@ -1,9 +1,16 @@ import { Banner } from '@empathyco/x-types'; import { DeepPartial, Dictionary } from '@empathyco/x-utils'; import { createLocalVue, mount, Wrapper } from '@vue/test-utils'; -import Vue, { VueConstructor, ComponentOptions } from 'vue'; +import Vue, { + VueConstructor, + ComponentOptions, + computed, + defineComponent, + provide, + inject, + Ref +} from 'vue'; import Vuex, { Store } from 'vuex'; -import { Component } from 'vue-property-decorator'; import BaseGrid from '../../../../components/base-grid.vue'; import { getXComponentXModuleName, isXComponent } from '../../../../components/x-component.utils'; import { XPlugin } from '../../../../plugins/x-plugin'; @@ -14,7 +21,6 @@ import { getBannersStub } from '../../../../__stubs__/banners-stubs.factory'; import BannersList from '../banners-list.vue'; import { LIST_ITEMS_KEY } from '../../../../components/decorators/injection.consts'; import { getResultsStub } from '../../../../__stubs__/results-stubs.factory'; -import { XInject, XProvide } from '../../../../components/decorators/injection.decorators'; import { resetXSearchStateWith } from './utils'; /** @@ -95,7 +101,7 @@ describe('testing BannersList component', () => { ` }); - expect(wrapper.classes('x-items-list')).toBe(true); + expect(wrapper.find(getDataTestSelector('items-list')).classes('x-items-list')).toBe(true); expect(wrapper.find(getDataTestSelector('banners-list-item')).exists()).toBe(true); expect(wrapper.find(getDataTestSelector('banner-slot-overridden')).text()).toBe( `Custom banner: ${getBanners()[0].id}` @@ -127,33 +133,36 @@ describe('testing BannersList component', () => { resetXSearchStateWith(store, { banners: bannersStub, totalResults: resultsStub.length * 2 }); /* It provides an array with some results */ - @Component({ + const Provider = defineComponent({ + name: 'Provider', + setup() { + const providedStub = computed((): ListItem[] => resultsStub); + provide(LIST_ITEMS_KEY as string, providedStub); + }, template: `
` - }) - class Provider extends Vue { - @XProvide(LIST_ITEMS_KEY) - public providedStub: ListItem[] = resultsStub; - } + }); /* * It should inject an array with the result from the Provider and the banner concatenated from * BannersList */ - @Component({ + const Child = defineComponent({ + name: 'Child', + setup() { + const injectedListItems = inject>(LIST_ITEMS_KEY as string); + const injectedListItemsString = computed( + (): string => injectedListItems?.value.map(item => item.id).join(',') ?? '' + ); + return { + injectedListItemsString + }; + }, template: `

{{ injectedListItemsString }}

` - }) - class Child extends Vue { - @XInject(LIST_ITEMS_KEY) - public injectedListItems: ListItem[] | undefined; - - protected get injectedListItemsString(): string { - return this.injectedListItems?.map(item => item.id).join(',') ?? ''; - } - } + }); const wrapper = mount( { diff --git a/packages/x-components/src/x-modules/search/components/__tests__/promoteds-list.spec.ts b/packages/x-components/src/x-modules/search/components/__tests__/promoteds-list.spec.ts index f26d91ccd7..17a265da98 100644 --- a/packages/x-components/src/x-modules/search/components/__tests__/promoteds-list.spec.ts +++ b/packages/x-components/src/x-modules/search/components/__tests__/promoteds-list.spec.ts @@ -1,9 +1,16 @@ import { Promoted } from '@empathyco/x-types'; import { DeepPartial, Dictionary } from '@empathyco/x-utils'; import { createLocalVue, mount, Wrapper } from '@vue/test-utils'; -import Vue, { VueConstructor, ComponentOptions } from 'vue'; +import Vue, { + VueConstructor, + ComponentOptions, + defineComponent, + computed, + provide, + inject, + Ref +} from 'vue'; import Vuex, { Store } from 'vuex'; -import Component from 'vue-class-component'; import BaseGrid from '../../../../components/base-grid.vue'; import { getXComponentXModuleName, isXComponent } from '../../../../components/x-component.utils'; import { XPlugin } from '../../../../plugins/x-plugin'; @@ -13,7 +20,6 @@ import { getDataTestSelector, installNewXPlugin } from '../../../../__tests__/ut import PromotedsList from '../promoteds-list.vue'; import { getPromotedsStub } from '../../../../__stubs__/promoteds-stubs.factory'; import { getResultsStub } from '../../../../__stubs__/results-stubs.factory'; -import { XInject, XProvide } from '../../../../components/decorators/injection.decorators'; import { LIST_ITEMS_KEY } from '../../../../components/decorators/injection.consts'; import { resetXSearchStateWith } from './utils'; @@ -95,7 +101,7 @@ describe('testing PromotedsList component', () => { ` }); - expect(wrapper.classes('x-items-list')).toBe(true); + expect(wrapper.find(getDataTestSelector('items-list')).classes('x-items-list')).toBe(true); expect(wrapper.find(getDataTestSelector('promoteds-list-item')).exists()).toBe(true); expect(wrapper.find(getDataTestSelector('promoted-slot-overridden')).text()).toBe( `Custom promoted: ${getPromoteds()[0].title}` @@ -130,33 +136,36 @@ describe('testing PromotedsList component', () => { }); /* It provides an array with some results */ - @Component({ + const Provider = defineComponent({ + name: 'Provider', + setup() { + const providedStub = computed((): ListItem[] => resultsStub); + provide(LIST_ITEMS_KEY as string, providedStub); + }, template: `
` - }) - class Provider extends Vue { - @XProvide(LIST_ITEMS_KEY) - public providedStub: ListItem[] = resultsStub; - } + }); /* * It should inject an array with the result from the Provider and the banner concatenated from * BannersList */ - @Component({ + const Child = defineComponent({ + name: 'Child', + setup() { + const injectedListItems = inject>(LIST_ITEMS_KEY as string); + const injectedListItemsString = computed( + (): string => injectedListItems?.value!.map(item => item.id).join(',') ?? '' + ); + return { + injectedListItemsString + }; + }, template: `

{{ injectedListItemsString }}

` - }) - class Child extends Vue { - @XInject(LIST_ITEMS_KEY) - public injectedListItems: ListItem[] | undefined; - - protected get injectedListItemsString(): string { - return this.injectedListItems?.map(item => item.id).join(',') ?? ''; - } - } + }); const wrapper = mount( { diff --git a/packages/x-components/src/x-modules/search/components/__tests__/results-list.spec.ts b/packages/x-components/src/x-modules/search/components/__tests__/results-list.spec.ts index f7e9aad95d..38d98e794b 100644 --- a/packages/x-components/src/x-modules/search/components/__tests__/results-list.spec.ts +++ b/packages/x-components/src/x-modules/search/components/__tests__/results-list.spec.ts @@ -1,9 +1,8 @@ import { Result } from '@empathyco/x-types'; import { DeepPartial, Dictionary } from '@empathyco/x-utils'; -import { createLocalVue, mount, Wrapper, VueClass } from '@vue/test-utils'; -import Vue, { VueConstructor, ComponentOptions } from 'vue'; +import { createLocalVue, mount, Wrapper } from '@vue/test-utils'; +import Vue, { VueConstructor, ComponentOptions, defineComponent, inject, Ref } from 'vue'; import Vuex, { Store } from 'vuex'; -import Component from 'vue-class-component'; import { getResultsStub } from '../../../../__stubs__/results-stubs.factory'; import BaseGrid from '../../../../components/base-grid.vue'; import { getXComponentXModuleName, isXComponent } from '../../../../components/x-component.utils'; @@ -12,7 +11,6 @@ import { ListItem } from '../../../../utils/types'; import { getDataTestSelector, installNewXPlugin } from '../../../../__tests__/utils'; import ResultsList from '../results-list.vue'; import { InfiniteScroll } from '../../../../directives/infinite-scroll/infinite-scroll.types'; -import { XInject } from '../../../../components/decorators/injection.decorators'; import { HAS_MORE_ITEMS_KEY, LIST_ITEMS_KEY, @@ -107,7 +105,7 @@ describe('testing Results list component', () => { ` }); - expect(wrapper.classes('x-items-list')).toBe(true); + expect(wrapper.find(getDataTestSelector('items-list')).classes('x-items-list')).toBe(true); expect(wrapper.find(getDataTestSelector('results-list-item')).exists()).toBe(true); expect(wrapper.find(getDataTestSelector('result-slot-overridden')).text()).toBe( `Custom result: ${getResults()[0].name!}` @@ -141,15 +139,17 @@ describe('testing Results list component', () => { }); it('provides the results from state with the key `item`', () => { - @Component({ + const Child = defineComponent({ + name: 'Child', + setup() { + const items = inject>(LIST_ITEMS_KEY as string); + + return { items }; + }, template: `
{{ items[0].id }}
` - }) - class Child extends Vue { - @XInject(LIST_ITEMS_KEY) - public items!: ListItem[]; - } + }); const { wrapper, getResults } = renderResultsList({ template: '', @@ -164,16 +164,17 @@ describe('testing Results list component', () => { // eslint-disable-next-line max-len it('provides the query with the key `query`, only updating it if the status is success', async () => { - @Component({ + const Child = defineComponent({ + name: 'Child', + setup() { + const searchQuery = inject>(QUERY_KEY as string); + + return { searchQuery }; + }, template: `
{{ searchQuery }}
` - }) - class Child extends Vue { - @XInject(QUERY_KEY) - public searchQuery!: string; - } - + }); const { wrapper, commit } = renderResultsList({ template: ``, components: { @@ -215,31 +216,37 @@ describe('testing Results list component', () => { }); it('provides a flag indicating if there are more results with the key `hasMoreItems`', () => { - @Component({ + const Child = defineComponent({ + name: 'Child', + setup() { + const hasMoreItems = inject>(HAS_MORE_ITEMS_KEY as string); + + return { hasMoreItems }; + }, template: `
` - }) - class Child extends Vue { - @XInject(HAS_MORE_ITEMS_KEY) - public hasMoreItems!: boolean; - } + }); const { commit, wrapper } = renderResultsList({ - template: '', + template: ``, components: { Child } }); - const childWrapper = wrapper.findComponent(Child as VueClass); + const childWrapper = wrapper.findComponent(Child); // Initially, the number of `items` and `totalResults` should match. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore expect(childWrapper.vm.hasMoreItems).toBe(false); commit('setTotalResults', 1000); // Now the `totalResults` is higher than the number of `items` + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore expect(childWrapper.vm.hasMoreItems).toBe(true); }); }); diff --git a/packages/x-components/src/x-modules/search/components/banners-list.vue b/packages/x-components/src/x-modules/search/components/banners-list.vue index e7d70a0513..96f4b80d0e 100644 --- a/packages/x-components/src/x-modules/search/components/banners-list.vue +++ b/packages/x-components/src/x-modules/search/components/banners-list.vue @@ -1,5 +1,5 @@