From c6b28e5e9a07832e992f27a40d7513dbec90d2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20CG?= Date: Tue, 23 Jul 2024 17:05:44 +0200 Subject: [PATCH 01/43] feat(x-installer): update to vue3 and adapt x-installer (#1572) * feat(x-installer): update to vue3 and adapt x-installer * feat(x-installer): simplify internal createApp fn * feat(scroll): fix import path * feat(component): keep injector const export * feat(mixins): removing deprecated mixins --- packages/x-components/package.json | 26 +- packages/x-components/src/App.vue | 4 - .../column-picker/base-column-picker-list.vue | 6 +- .../__tests__/bus.decorators.spec.ts | 390 - .../__tests__/debounce.decorators.spec.ts | 102 - .../__tests__/injection.decorators.spec.ts | 174 - .../__tests__/store.decorators.spec.ts | 66 - .../components/decorators/bus.decorators.ts | 173 - .../decorators/debounce.decorators.ts | 44 - .../components/decorators/injection.consts.ts | 14 +- .../decorators/injection.decorators.ts | 254 - .../components/decorators/store.decorators.ts | 62 - .../src/components/dynamic-props.mixin.ts | 33 - packages/x-components/src/components/index.ts | 5 - .../src/components/x-component.mixin.ts | 22 - .../x-components/src/composables/use-store.ts | 6 +- packages/x-components/src/main.ts | 19 +- .../src/plugins/devtools/devtools.plugin.ts | 7 +- packages/x-components/src/plugins/index.ts | 2 - .../src/plugins/x-plugin.alias.ts | 141 - .../src/plugins/x-plugin.mixin.ts | 113 - packages/x-components/src/plugins/x-plugin.ts | 43 +- packages/x-components/src/router.ts | 16 +- .../src/store/utils/config-store.utils.ts | 4 +- .../x-components/src/vue-global-events.d.ts | 4 - .../src/x-installer/x-installer/types.ts | 54 +- .../x-installer/x-installer/x-installer.ts | 80 +- .../device/components/device-detector.vue | 2 +- .../experience-controls/store/module.ts | 5 +- .../src/x-modules/facets/store/module.ts | 18 +- .../components/query-preview-list.vue | 3 +- .../x-modules/queries-preview/store/module.ts | 6 +- .../scroll/components/main-scroll-item.vue | 9 +- .../scroll/components/scroll.const.ts | 2 +- .../src/x-modules/scroll/store/module.ts | 4 +- .../x-modules/url/components/url-handler.vue | 2 +- .../store/mutations/set-params.mutation.ts | 2 +- packages/x-components/vite.config.ts | 13 +- pnpm-lock.yaml | 13647 ++++++---------- 39 files changed, 4794 insertions(+), 10783 deletions(-) delete mode 100644 packages/x-components/src/components/decorators/__tests__/bus.decorators.spec.ts delete mode 100644 packages/x-components/src/components/decorators/__tests__/debounce.decorators.spec.ts delete mode 100644 packages/x-components/src/components/decorators/__tests__/injection.decorators.spec.ts delete mode 100644 packages/x-components/src/components/decorators/__tests__/store.decorators.spec.ts delete mode 100644 packages/x-components/src/components/decorators/bus.decorators.ts delete mode 100644 packages/x-components/src/components/decorators/debounce.decorators.ts delete mode 100644 packages/x-components/src/components/decorators/injection.decorators.ts delete mode 100644 packages/x-components/src/components/decorators/store.decorators.ts delete mode 100644 packages/x-components/src/components/dynamic-props.mixin.ts delete mode 100644 packages/x-components/src/components/x-component.mixin.ts delete mode 100644 packages/x-components/src/plugins/x-plugin.alias.ts delete mode 100644 packages/x-components/src/plugins/x-plugin.mixin.ts delete mode 100644 packages/x-components/src/vue-global-events.d.ts diff --git a/packages/x-components/package.json b/packages/x-components/package.json index 5cebc86eb3..8f241c897b 100644 --- a/packages/x-components/package.json +++ b/packages/x-components/package.json @@ -82,19 +82,15 @@ "js-md5": "^0.8.3", "rxjs": "~7.8.0", "tslib": "~2.6.0", - "vue-class-component": "~7.2.6", - "vue-global-events": "~1.2.1", - "vue-property-decorator": "~8.5.0", - "vue-runtime-helpers": "~1.1.2" + "vue-global-events": "~3.0.1" }, "peerDependencies": { - "vue": "~2.7.0", - "vuex": "^3.0.0" + "vue": "~3.4.31", + "vuex": "4.0.2" }, "devDependencies": { "@badeball/cypress-cucumber-preprocessor": "~20.0.0", "@bahmutov/cypress-esbuild-preprocessor": "~2.2.0", - "@cypress/vue2": "~2.0.1", "@empathyco/x-tailwindcss": "^1.2.0-alpha.3", "@microsoft/api-documenter": "~7.23.0", "@microsoft/api-extractor": "~7.39.0", @@ -105,9 +101,8 @@ "@types/jest": "~27.5.0", "@types/node": "~18.19.0", "@types/testing-library__jest-dom": "~5.14.5", - "@vitejs/plugin-vue2": "^2.2.0", - "@vue/test-utils": "~1.0.3", - "@vue/vue2-jest": "~27.0.0-alpha.3", + "@vitejs/plugin-vue": "~5.0.5", + "@vue/test-utils": "~2.4.6", "autoprefixer": "~10.4.4", "convert-source-map": "~2.0.0", "cypress": "~13.6.0", @@ -132,12 +127,11 @@ "ts-node": "~10.9.1", "typescript": "~4.9.4", "vite": "^4.5.0", - "vite-plugin-vue-inspector": "^4.0.0", - "vue": "~2.7.14", - "vue-docgen-cli": "~4.67.0", - "vue-router": "~3.6.5", - "vue-template-compiler": "~2.7.14", - "vuex": "~3.6.2" + "vite-plugin-vue-inspector": "~5.1.2", + "vue": "~3.4.31", + "vue-docgen-cli": "~4.79.0", + "vue-router": "~4.4.0", + "vuex": "4.0.2" }, "publishConfig": { "access": "public", diff --git a/packages/x-components/src/App.vue b/packages/x-components/src/App.vue index ac2acc6692..429535e60b 100644 --- a/packages/x-components/src/App.vue +++ b/packages/x-components/src/App.vue @@ -10,10 +10,6 @@ - - diff --git a/packages/_vue3-migration-test/src/router.ts b/packages/_vue3-migration-test/src/router.ts index c040f9f98c..c188737156 100644 --- a/packages/_vue3-migration-test/src/router.ts +++ b/packages/_vue3-migration-test/src/router.ts @@ -22,7 +22,6 @@ import { TestSearchBox, TestBaseVariableColumnGrid, TestEmpathize, - TestUseLayouts, TestSlidingPanel, TestBaseSuggestions, TestHighlight, @@ -174,11 +173,6 @@ const routes = [ name: 'BaseVariableColumnGrid', component: TestBaseVariableColumnGrid }, - { - path: '/test-use-layouts', - name: 'UseLayouts', - component: TestUseLayouts - }, { path: '/base-suggestions', name: 'BaseSuggestions', diff --git a/packages/x-components/src/components/items-list.vue b/packages/x-components/src/components/items-list.vue index 4634c4cdd3..206beb7fa2 100644 --- a/packages/x-components/src/components/items-list.vue +++ b/packages/x-components/src/components/items-list.vue @@ -37,58 +37,35 @@ export default defineComponent({ name: 'ItemsList', props: { - /** - * Animation component that will be used to animate the list. - * - * @public - */ + /** Animation component that will be used to animate the list. */ animation: { type: animationProp, default: 'ul' }, - - /** - * List of items. - * - * @public - */ + /** List of items. */ items: { type: Array as PropType, required: true }, - - /** - * Item's classes. - * - * @public - */ - itemClass: { - type: String - } + /** Item's classes. */ + itemClass: String }, setup(props) { /** * The list of the items with additional properties. * * @returns A list of items with `dataTest`, `class` and the `slotName` for each item. - * - * @internal */ - const computedItems = computed( - (): { - dataTest: string; - class: Array; - }[] => { - return props.items.map(item => { - const modelName = toKebabCase(item.modelName); - return { - ...item, - dataTest: `${modelName}s-list-item`, - class: [`x-${modelName}s-list-item`, props.itemClass], - slotName: modelName - }; - }); - } + const computedItems = computed(() => + props.items.map(item => { + const modelName = toKebabCase(item.modelName); + return { + ...item, + dataTest: `${modelName}s-list-item`, + class: [`x-${modelName}s-list-item`, props.itemClass], + slotName: modelName + }; + }) ); return { computedItems }; diff --git a/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue b/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue index 18737d8819..dcec318d3a 100644 --- a/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue +++ b/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue @@ -13,7 +13,7 @@ />
@@ -23,7 +23,7 @@
-
+
@@ -32,14 +32,18 @@
-
+
TOOLBAR
-
+
MAIN @@ -47,7 +51,7 @@
EXTRA ASIDE -
+
SCROLL TO TOP @@ -86,13 +94,11 @@ diff --git a/packages/x-components/src/components/layouts/single-column-layout.vue b/packages/x-components/src/components/layouts/single-column-layout.vue index b974f7dbf6..4fdf4d5b7a 100644 --- a/packages/x-components/src/components/layouts/single-column-layout.vue +++ b/packages/x-components/src/components/layouts/single-column-layout.vue @@ -1,27 +1,33 @@ + + + +
@@ -449,8 +458,8 @@ - diff --git a/packages/x-components/src/components/animations/staggering-transition-group.vue b/packages/x-components/src/components/animations/staggering-transition-group.vue deleted file mode 100644 index 5e84c1b6bd..0000000000 --- a/packages/x-components/src/components/animations/staggering-transition-group.vue +++ /dev/null @@ -1,472 +0,0 @@ - - - - - -## Examples - -### Basic example - -Apart from all the props and events that the classic transition group has, the staggering transition -group also exposes a new `staggering` property, which allows to configure the delay for each one of -the nodes when animating. - -```vue - - - - -``` - diff --git a/packages/x-components/src/components/base-grid.vue b/packages/x-components/src/components/base-grid.vue index 86ed995de2..4306a12f05 100644 --- a/packages/x-components/src/components/base-grid.vue +++ b/packages/x-components/src/components/base-grid.vue @@ -9,7 +9,7 @@ data-test="grid" >
  • @@ -114,41 +104,28 @@ }; const xBus = useXBus(); - /** - * It injects {@link ListItem} provided by an ancestor. - * - * @internal - */ - const injectedListItems = inject | undefined>( - LIST_ITEMS_KEY as string, - undefined - ); - - const gridEl = ref(null); + /** It injects {@link ListItem} provided by an ancestor. */ + const injectedListItems = inject>(LIST_ITEMS_KEY as string); + const gridEl = ref(); let renderedColumnsNumber = ref(0); + /** * Emits the {@link XEventsTypes.RenderedColumnsNumberChanged} * event whenever the number of columns rendered inside the grid changes. - * - * @internal */ watch( renderedColumnsNumber, () => xBus.emit('RenderedColumnsNumberChanged', renderedColumnsNumber.value), - { - immediate: false - } + { immediate: false } ); /** * It returns the items passed as props or the injected ones. * * @returns List of grid items. - * - * @public */ - const computedItems = computed((): ListItem[] | void => { + const computedItems = computed(() => { return ( props.items ?? injectedListItems?.value ?? @@ -163,38 +140,27 @@ * amount of columns or rows based on how many columns the grid is divided into. * * @returns CSS class with the column property value. - * - * @internal */ - const cssClasses = computed( - (): VueCSSClasses => - props.columns ? `x-base-grid--cols-${props.columns}` : 'x-base-grid--cols-auto' - ); + const cssClasses = computed(() => `x-base-grid--cols-${props.columns || 'auto'}`); /** * CSSStyleDeclaration object specifying the number of columns the grid is divided into based on * the column property value. * * @returns A CSSStyleDeclaration to use as the style attribute. - * - * @internal */ - const style = computed((): Partial => { - return { - gridTemplateColumns: props.columns - ? `repeat(${props.columns}, minmax(0, 1fr))` - : 'repeat(auto-fill, minmax(var(--x-size-min-width-grid-item, 150px), 1fr))' - }; - }); + const style = computed>(() => ({ + gridTemplateColumns: props.columns + ? `repeat(${props.columns}, minmax(0, 1fr))` + : 'repeat(auto-fill, minmax(var(--x-size-min-width-grid-item, 150px), 1fr))' + })); /** * Maps the item to an object containing: the `item`, its `CSS class` and its slot name. * * @returns An array of objects containing the item and its CSS class. - * - * @internal */ - const gridItems = computed((): GridItem[] => + const gridItems = computed(() => (computedItems.value as ListItem[]).map(item => { const slotName = toKebabCase(item.modelName); return { @@ -210,30 +176,20 @@ * * @param value - The value to check. * @returns `true` if the value is an `ElementRef` object, `false` otherwise. - * - * @internal */ const isElementRef = (value: any): value is ElementRef => { return value && value.$el instanceof HTMLElement; }; - /** - * Updates the number of columns rendered inside the grid. - * - * @internal - */ - const updateRenderedColumnsNumber = (): void => { + /** Updates the number of columns rendered inside the grid. */ + function updateRenderedColumnsNumber() { const { gridTemplateColumns } = getComputedStyle( isElementRef(gridEl.value) ? gridEl.value.$el : (gridEl.value as Element) ); renderedColumnsNumber.value = gridTemplateColumns.split(' ').length; - }; + } - /** - * Initialises the rendered columns number and sets a ResizeObserver to keep it updated. - * - * @internal - */ + /** Initialises the rendered columns number and sets a ResizeObserver to keep it updated. */ let resizeObserver: UseResizeObserverReturn; onMounted(() => { resizeObserver = useResizeObserver( diff --git a/packages/x-components/src/views/home/Home.vue b/packages/x-components/src/views/home/Home.vue index d6cdb4af04..d7cdf47c11 100644 --- a/packages/x-components/src/views/home/Home.vue +++ b/packages/x-components/src/views/home/Home.vue @@ -136,7 +136,11 @@ - + @@ -463,7 +467,7 @@ /* eslint-disable max-len */ import { computed, ComputedRef, defineComponent, provide } from 'vue'; import { animateClipPath } from '../../components/animations/animate-clip-path/animate-clip-path.factory'; - // import StaggeredFadeAndSlide from '../../components/animations/staggered-fade-and-slide.vue'; + import StaggeredFadeAndSlide from '../../components/animations/staggered-fade-and-slide.vue'; import AutoProgressBar from '../../components/auto-progress-bar.vue'; import BaseDropdown from '../../components/base-dropdown.vue'; import BaseGrid from '../../components/base-grid.vue'; @@ -604,7 +608,7 @@ 'Find sunglasses' ]; const columnPickerValues = [0, 2, 4]; - // const resultsAnimation = StaggeredFadeAndSlide; + const resultsAnimation = StaggeredFadeAndSlide; const modalAnimation = animateClipPath(); const selectedColumns = 4; const sortValues = ['', 'price asc', 'price desc']; @@ -666,7 +670,7 @@ adapterConfig.e2e = !adapterConfig.e2e; }; return { - resultsAnimation: undefined, + resultsAnimation, modalAnimation, queriesPreviewInfo, stores, From ed587b16a56b32734e9cf3ff05311954627f3820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Antonio=20Caba=C3=B1eros?= Date: Tue, 27 Aug 2024 15:18:16 +0200 Subject: [PATCH 19/43] build: adjust rollup production build for Vue3 (#1603) Co-authored-by: Diego Pascual --- packages/x-components/build/build.ts | 37 +-- packages/x-components/build/build.utils.ts | 26 +- .../build/postcss-dir-pseudo-class.d.ts | 6 - .../x-components/build/postcss-logical.d.ts | 6 - .../build/postcss-types/options.ts | 4 - .../design-system.rollup-plugin.ts | 18 +- .../x-components.rollup-plugin.ts | 10 +- packages/x-components/build/rollup.config.ts | 129 ++++----- .../x-components/build/tools/inject-css.js | 13 + packages/x-components/package.json | 13 +- packages/x-components/src/App.vue | 4 +- .../components/animations/animate-width.vue | 20 +- .../components/animations/collapse-height.vue | 12 +- .../components/animations/collapse-width.vue | 12 +- .../src/components/animations/cross-fade.vue | 26 +- .../components/animations/fade-and-slide.vue | 32 +-- .../src/components/animations/fade.vue | 18 +- .../animations/staggered-fade-and-slide.vue | 8 +- .../src/components/auto-progress-bar.vue | 20 +- .../src/components/base-dropdown.vue | 18 +- .../x-components/src/components/base-grid.vue | 33 ++- .../src/components/base-rating.vue | 48 ++-- .../src/components/base-switch.vue | 40 +-- .../components/decorators/injection.consts.ts | 2 +- .../fixed-header-and-asides-layout.vue | 34 +-- .../layouts/multi-column-max-width-layout.vue | 70 ++--- .../layouts/single-column-layout.vue | 2 +- .../src/components/modals/base-modal.vue | 26 +- .../panels/base-header-toggle-panel.vue | 2 +- .../src/components/panels/base-tabs-panel.vue | 2 +- .../components/result/base-result-image.vue | 10 +- .../components/result/base-result-link.vue | 2 +- .../components/result/base-result-rating.vue | 2 +- .../result/result-variant-selector.vue | 2 +- .../src/components/scroll/base-scroll.vue | 2 +- .../src/components/sliding-panel.vue | 83 +++--- .../suggestions/base-suggestions.vue | 12 +- packages/x-components/src/shims-tsx.d.ts | 8 - packages/x-components/src/shims-vue.d.ts | 2 +- .../accessibility/wai-base-event-button.vue | 2 +- packages/x-components/src/views/home/Home.vue | 2 +- .../x-components/src/views/home/aside.vue | 2 - .../x-components/src/views/home/result.vue | 2 - packages/x-components/src/views/pdp.vue | 2 - .../components/facets/facets-provider.vue | 2 +- .../facets/components/facets/facets.vue | 7 +- .../filters/editable-number-range-filter.vue | 10 +- .../facets/components/lists/filters-list.vue | 2 +- .../components/lists/filters-search.vue | 36 ++- .../lists/selected-filters-list.vue | 5 +- .../history-queries/components/my-history.vue | 2 +- .../components/identifier-results.vue | 2 +- .../components/query-preview.vue | 10 +- .../store/getters/query-suggestions.getter.ts | 5 +- .../components/recommendations.vue | 2 +- .../related-tags/components/related-tags.vue | 2 +- .../scroll/components/main-scroll.vue | 2 +- .../components/search-input-placeholder.vue | 12 +- .../search-box/components/search-input.vue | 2 +- .../x-modules/search/components/banner.vue | 10 +- .../components/partial-results-list.vue | 2 +- .../x-modules/search/components/promoted.vue | 10 +- .../search/components/redirection.vue | 2 - .../x-modules/search/components/sort-list.vue | 2 +- pnpm-lock.yaml | 255 +++++++++++++++--- 65 files changed, 640 insertions(+), 566 deletions(-) delete mode 100644 packages/x-components/build/postcss-dir-pseudo-class.d.ts delete mode 100644 packages/x-components/build/postcss-logical.d.ts delete mode 100644 packages/x-components/build/postcss-types/options.ts create mode 100644 packages/x-components/build/tools/inject-css.js delete mode 100644 packages/x-components/src/shims-tsx.d.ts diff --git a/packages/x-components/build/build.ts b/packages/x-components/build/build.ts index 42b28542fe..5bf2451666 100644 --- a/packages/x-components/build/build.ts +++ b/packages/x-components/build/build.ts @@ -1,35 +1,16 @@ -import * as path from 'path'; -import fs from 'fs'; -import { rollup } from 'rollup'; -import { cssDeprecatedComponentsRollupConfig, rollupConfig } from './rollup.config'; - -const rootDir = path.resolve(__dirname, '../'); - -// eslint-disable-next-line no-console -build().catch(console.error); +import { OutputOptions, rollup } from 'rollup'; +import { cssDeprecatedRollupConfig, rollupConfig } from './rollup.config'; /** * Entry point for building the project. */ -async function build(): Promise { - try { - const bundle = await rollup(rollupConfig); - await bundle.write(rollupConfig.output); - - const bundleCssDeprecatedComponents = await rollup(cssDeprecatedComponentsRollupConfig); - await bundleCssDeprecatedComponents.write(cssDeprecatedComponentsRollupConfig.output); +async function build() { + const bundle = await rollup(rollupConfig); + await bundle.write(rollupConfig.output as OutputOptions); - return removeTempFiles(); - } catch (error) { - // eslint-disable-next-line no-console - console.error('Build failed: ', (error as Error).message); - process.exit(1); - } + const bundleCssDeprecatedComponents = await rollup(cssDeprecatedRollupConfig); + await bundleCssDeprecatedComponents.write(cssDeprecatedRollupConfig.output as OutputOptions); } -/** - * Function for deleting useless folders. - */ -function removeTempFiles(): void { - fs.rmSync(path.join(rootDir, 'temp'), { recursive: true }); -} +// eslint-disable-next-line no-console +build().catch(console.error); diff --git a/packages/x-components/build/build.utils.ts b/packages/x-components/build/build.utils.ts index 398eba5fb4..9cd88ad004 100644 --- a/packages/x-components/build/build.utils.ts +++ b/packages/x-components/build/build.utils.ts @@ -2,24 +2,24 @@ import fs from 'fs'; import path from 'path'; /** - * Asserts a file path directory exists recursively, creating it if it does not. + * Asserts a directory exist recursively, creating it if it does not. * - * @param filePath - The full path to the file, that may or may not exist. + * @param directoryPath - The full directory path, that may or may not exist. */ -export function ensureFilePathExists(filePath: string): void { - const dirName = path.dirname(filePath); - ensureDirectoryPathExists(dirName); +export function ensureDirectoryPathExists(directoryPath: string) { + if (!fs.existsSync(directoryPath)) { + fs.mkdirSync(directoryPath, { recursive: true }); + } } /** - * Asserts a directory exist recursively, creating it if it does not. + * Asserts a file path directory exists recursively, creating it if it does not. * - * @param directoryPath - The full directory path, that may or may not exists. + * @param filePath - The full path to the file, that may or may not exist. */ -export function ensureDirectoryPathExists(directoryPath: string): void { - if (!fs.existsSync(directoryPath)) { - fs.mkdirSync(directoryPath, { recursive: true }); - } +export function ensureFilePathExists(filePath: string) { + const dirName = path.dirname(filePath); + ensureDirectoryPathExists(dirName); } /** @@ -28,7 +28,7 @@ export function ensureDirectoryPathExists(directoryPath: string): void { * @param sourceFolder - Source folder to be copied. * @param targetFolder - Target folder. */ -export function copyFolderSync(sourceFolder: string, targetFolder: string): void { +export function copyFolderSync(sourceFolder: string, targetFolder: string) { if (!fs.existsSync(targetFolder)) { fs.mkdirSync(targetFolder); } @@ -49,6 +49,6 @@ export function copyFolderSync(sourceFolder: string, targetFolder: string): void * @param path - The path to normalize. * @returns A normalized path. */ -export function normalizePath(path: string): string { +export function normalizePath(path: string) { return path.replace(/\\/g, '/'); } diff --git a/packages/x-components/build/postcss-dir-pseudo-class.d.ts b/packages/x-components/build/postcss-dir-pseudo-class.d.ts deleted file mode 100644 index 97c67b6cbc..0000000000 --- a/packages/x-components/build/postcss-dir-pseudo-class.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module 'postcss-dir-pseudo-class' { - import { Options } from './postcss-types/options'; - - function postcssDirPseudoClass(options?: Options = {}): Plugin; - export = postcssDirPseudoClass; -} diff --git a/packages/x-components/build/postcss-logical.d.ts b/packages/x-components/build/postcss-logical.d.ts deleted file mode 100644 index 3e9b159118..0000000000 --- a/packages/x-components/build/postcss-logical.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module 'postcss-logical' { - import { Options } from './postcss-types/options'; - - function postcssLogical(options?: Options = {}): Plugin; - export = postcssLogical; -} diff --git a/packages/x-components/build/postcss-types/options.ts b/packages/x-components/build/postcss-types/options.ts deleted file mode 100644 index 39996ec735..0000000000 --- a/packages/x-components/build/postcss-types/options.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface Options { - dir?: 'rtl' | 'ltr'; - preserve?: boolean; -} diff --git a/packages/x-components/build/rollup-plugins/design-system.rollup-plugin.ts b/packages/x-components/build/rollup-plugins/design-system.rollup-plugin.ts index 19295040b1..18a73605dc 100644 --- a/packages/x-components/build/rollup-plugins/design-system.rollup-plugin.ts +++ b/packages/x-components/build/rollup-plugins/design-system.rollup-plugin.ts @@ -1,5 +1,4 @@ import fs from 'fs'; -import path from 'path'; import { Plugin } from 'rollup'; import { normalizePath } from '../build.utils'; @@ -12,28 +11,13 @@ import { normalizePath } from '../build.utils'; * returns `src/design-system/button/default.tokens.scss` if exists. * @internal */ -function getTokensFilePath(file: string): string | null { +function getTokensFilePath(file: string) { const fileParts = file.split('.'); const fileExtension = fileParts.pop() ?? ''; const tokensFile = `${fileParts.join('.')}.tokens.${fileExtension}`; return fs.existsSync(tokensFile) ? normalizePath(tokensFile) : null; } -/** - * This function returns the name for the CSS file using the component name and the variant. - * The component name is extracted from the folder name, and the variant name is extracted from - * the file name. - * - * @param file - The path of the file processed. - * @returns The name for the CSS file with the component and the variant. - * @example For `src/style/components/button/pill.scss` file this function returns `button-pill`. - * @internal - */ -export function renameComponentCssFile(file: string): string { - const parentFolder = path.dirname(file).split(path.sep)?.pop() ?? ''; - return `${parentFolder}-${path.basename(file).replace('.scss', '')}`; -} - /** * This function returns a {@link Plugin | RollupJS Plugin} to import the tokens files into the * components .scss files. For each `xxx.scss` processed, it looks for the `xxx.tokens.scss` tokens diff --git a/packages/x-components/build/rollup-plugins/x-components.rollup-plugin.ts b/packages/x-components/build/rollup-plugins/x-components.rollup-plugin.ts index 30719690bc..8de6bd9f38 100644 --- a/packages/x-components/build/rollup-plugins/x-components.rollup-plugin.ts +++ b/packages/x-components/build/rollup-plugins/x-components.rollup-plugin.ts @@ -17,9 +17,9 @@ export interface GenerateEntryFilesOptions { /** The path where the build will go. */ buildPath: string; /** The path to the directory where generated js files are stored. */ - jsOutputDirectory: string; + jsOutputDir: string; /** The path to the directory where generated .d.ts files are stored. */ - typesOutputDirectory: string; + typesOutputDir: string; } /** @@ -44,9 +44,9 @@ export function generateEntryFiles(options: GenerateEntryFilesOptions): Plugin { * - 1 Typings file per entry point. */ writeBundle() { - generateEntryPoints(options.buildPath, options.jsOutputDirectory, 'js'); - generateEntryPoints(options.buildPath, options.typesOutputDirectory, 'd.ts'); - copyIndexSourcemap(options.buildPath, options.jsOutputDirectory); + generateEntryPoints(options.buildPath, options.jsOutputDir, 'js'); + generateEntryPoints(options.buildPath, options.typesOutputDir, 'd.ts'); + copyIndexSourcemap(options.buildPath, options.jsOutputDir); } }; } diff --git a/packages/x-components/build/rollup.config.ts b/packages/x-components/build/rollup.config.ts index 7b3e71215e..bd23383a29 100644 --- a/packages/x-components/build/rollup.config.ts +++ b/packages/x-components/build/rollup.config.ts @@ -1,14 +1,12 @@ import path from 'path'; -import commonjs from '@rollup/plugin-commonjs'; import { sync as glob } from 'glob'; -import { RollupOptions } from 'rollup'; +import { RollupOptions, Plugin } from 'rollup'; import copy from 'rollup-plugin-copy'; import del from 'rollup-plugin-delete'; import styles from 'rollup-plugin-styles'; import typescript from 'rollup-plugin-typescript2'; -import vue, { VuePluginOptions } from 'rollup-plugin-vue'; -import packageJSON from '../package.json'; -import { normalizePath } from './build.utils'; +import vue3 from '@vitejs/plugin-vue'; +import { dependencies as pkgDeps, peerDependencies as pkgPeerDeps } from '../package.json'; import { apiDocumentation } from './docgen/documentation.rollup-plugin'; import { importTokens, omitJsFiles } from './rollup-plugins/design-system.rollup-plugin'; import { generateEntryFiles } from './rollup-plugins/x-components.rollup-plugin'; @@ -16,17 +14,21 @@ import { generateEntryFiles } from './rollup-plugins/x-components.rollup-plugin' const rootDir = path.resolve(__dirname, '../'); const buildPath = path.join(rootDir, 'dist'); -const dependencies = new Set( - Object.keys(packageJSON.dependencies).concat(Object.keys(packageJSON.peerDependencies)) -); -const jsOutputDirectory = path.join(buildPath, 'js'); -const typesOutputDirectory = path.join(buildPath, 'types'); -const cssOutputDirectory = path.join(buildPath, 'design-system'); +const jsOutputDir = path.join(buildPath, 'js'); +const typesOutputDir = path.join(buildPath, 'types'); -export const rollupConfig = createRollupOptions({ +const dependencies = new Set(Object.keys(pkgDeps).concat(Object.keys(pkgPeerDeps))); + +const vueDocs = { + name: 'vue-docs', + transform: (_code: unknown, id: string) => + !/vue&type=docs/.test(id) ? undefined : `export default ''` +}; + +export const rollupConfig: RollupOptions = { input: path.join(rootDir, 'src/index.ts'), output: { - dir: jsOutputDirectory, + dir: jsOutputDir, format: 'esm', sourcemap: true, preserveModules: true @@ -36,7 +38,7 @@ export const rollupConfig = createRollupOptions({ * Because of that, when rollup detects a circular dependency (it emits a warning), we stop * the build with an error */ if (warning.code === 'CIRCULAR_DEPENDENCY') { - throw Error(`Circular dependency found: ${warning.ids?.join(' ') as string}`); + throw Error(`Circular dependency found: ${warning.ids?.join(' ') ?? ''}`); } }, external(id) { @@ -44,26 +46,28 @@ export const rollupConfig = createRollupOptions({ Rollup treats by default all node_modules dependencies as external, but will launch a warning if you don't manually specify them. In our case apart from the package.json ones, we also need to add any dependency that starts with rxjs (due to rxjs having multiple - entry points), and the vue-runtime-helpers, which is a dependency added by the SFC compiler + entry points) */ return ( dependencies.has(id) || // Package.json dependencies /* As rxjs has multiple entry points, it needs to be declared this way */ - id.startsWith('rxjs') || - /* Vue SFC dependency. Needs to be here because rollup generates a relative import to the - node_modules folder */ - id.includes('vue-runtime-helpers') + id.startsWith('rxjs') ); }, plugins: [ - del({ targets: [`${buildPath}/*`, `${path.join(rootDir, 'docs')}/*`] }), - commonjs(), + del({ + targets: [ + `${buildPath}/*`, + `${path.join(rootDir, 'docs')}/*`, + `${path.join(rootDir, 'temp')}/*` + ] + }), typescript({ useTsconfigDeclarationDir: true, tsconfig: path.resolve(rootDir, 'tsconfig.json'), tsconfigOverride: { compilerOptions: { - declarationDir: typesOutputDirectory, + declarationDir: typesOutputDir, target: 'es2020' }, exclude: [ @@ -75,91 +79,50 @@ export const rollupConfig = createRollupOptions({ ] } }), - vue({ - css: false, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore Undocumented option to disable vue sourcemap generation because it breaks if - // lang is set to ts: - // https://github.com/vuejs/rollup-plugin-vue/issues/272#issuecomment-491721842 - needMap: false, + vue3({ template: { compilerOptions: { whitespace: 'condense' } - } as VuePluginOptions['template'], - style: { - postcssCleanOptions: { disabled: true } } - }), + }) as Plugin, styles({ + minimize: true, mode: [ 'inject', - (varname: string, id: string) => - `import { createInjector, createInjectorSSR } from 'vue-runtime-helpers'; - const isBrowser = /*#__PURE__*/ (function () { - return ( - Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) !== - '[object process]' - ); - })(); - const useBrowserInjector = - (typeof STRIP_SSR_INJECTOR !== 'undefined' && STRIP_SSR_INJECTOR) || isBrowser; - const injector = useBrowserInjector ? createInjector({}) : createInjectorSSR({}); - injector('${normalizePath(id)}',{source:${varname}});` + varname => { + const pathInjector = path.resolve('./tools/inject-css.js'); + return `import injectCss from '${pathInjector}';injectCss(${varname});`; + } ] }), - generateEntryFiles({ - buildPath, - jsOutputDirectory, - typesOutputDirectory - }), - apiDocumentation({ - buildPath - }), + vueDocs, + generateEntryFiles({ buildPath, jsOutputDir, typesOutputDir }), + apiDocumentation({ buildPath }), copy({ targets: [ - { - src: ['CHANGELOG.md', 'package.json', 'README.md', 'docs'], - dest: buildPath - } + { src: ['build/tools'], dest: buildPath }, + { src: ['CHANGELOG.md', 'package.json', 'README.md', 'docs'], dest: buildPath } ], hook: 'writeBundle' }) ] -}); +}; // Design System CSS generation +const cssOutputDir = path.join(buildPath, 'design-system'); -/** - * Common options for all CSS Rollup configs. - */ -const commonCssOptions = createRollupOptions({ +/** The config to generate one `.css` file with all the deprecated styles. */ +export const cssDeprecatedRollupConfig: RollupOptions = { + input: glob('src/design-system-deprecated/**/*.scss'), output: { - dir: cssOutputDirectory, + dir: cssOutputDir, assetFileNames: '[name][extname]', preserveModules: true - } -}); - -/** - * The config to generate one `.css` file with all the deprecated styles. - */ -export const cssDeprecatedComponentsRollupConfig = createRollupOptions({ - ...commonCssOptions, - input: glob('src/design-system-deprecated/**/*.scss'), + }, plugins: [ importTokens(), styles({ mode: ['extract', 'deprecated-full-theme.css'] }), omitJsFiles() ] -}); - -/** - * Util function to create type-safe Rollup options. - * - * @param options - The Rollup options to create. - * @returns Type-safe Rollup options. - */ -export function createRollupOptions(options: T): T { - return options; -} +}; diff --git a/packages/x-components/build/tools/inject-css.js b/packages/x-components/build/tools/inject-css.js new file mode 100644 index 0000000000..5de49db0ce --- /dev/null +++ b/packages/x-components/build/tools/inject-css.js @@ -0,0 +1,13 @@ +/** + * Simple CSS injector to append styles to the head. + * This injector can be overwritten at build time. + * + * @params css - CSS code. + */ +function injectCss(css) { + const el = document.createElement('style'); + el.textContent = css; + document.head.appendChild(el); +} + +export default injectCss; diff --git a/packages/x-components/package.json b/packages/x-components/package.json index b34cb11572..55ba512ed4 100644 --- a/packages/x-components/package.json +++ b/packages/x-components/package.json @@ -30,8 +30,8 @@ "./tests/**/*", "**/*.scss", "**/*.scss.js", - "**/*vue[0-9].js", "**/*.css", + "**/*vue[0-9].js", "**/*.vue" ], "repository": { @@ -79,7 +79,7 @@ "@empathyco/x-utils": "^1.0.3-alpha.1", "@vue/devtools-api": "~6.5.0", "@vueuse/core": "~10.7.1", - "js-md5": "^0.8.3", + "js-md5": "~0.8.3", "rxjs": "~7.8.0", "tslib": "~2.6.0", "vue-global-events": "~3.0.1" @@ -94,14 +94,13 @@ "@empathyco/x-tailwindcss": "^1.2.0-alpha.5", "@microsoft/api-documenter": "~7.23.0", "@microsoft/api-extractor": "~7.39.0", - "@rollup/plugin-commonjs": "~25.0.7", "@testing-library/jest-dom": "~5.17.0", "@types/autoprefixer": "~10.2.0", - "@types/glob": "^8.0.1", + "@types/glob": "~8.0.1", "@types/jest": "~27.5.0", "@types/node": "~18.19.0", "@types/testing-library__jest-dom": "~5.14.5", - "@vitejs/plugin-vue": "~5.0.5", + "@vitejs/plugin-vue": "~5.1.2", "@vue/test-utils": "~2.4.6", "@vue/vue3-jest": "~27.0.0", "autoprefixer": "~10.4.4", @@ -125,9 +124,9 @@ "start-server-and-test": "~2.0.0", "tailwindcss": "~3.4.0", "ts-jest": "~27.1.0", - "ts-node": "~10.9.1", + "ts-node": "~10.9.2", "typescript": "~4.9.4", - "vite": "^4.5.0", + "vite": "~4.5.0", "vite-plugin-vue-inspector": "~5.1.2", "vue": "~3.4.31", "vue-docgen-cli": "~4.79.0", diff --git a/packages/x-components/src/App.vue b/packages/x-components/src/App.vue index 429535e60b..38a0ad4873 100644 --- a/packages/x-components/src/App.vue +++ b/packages/x-components/src/App.vue @@ -10,7 +10,7 @@
  • - - diff --git a/packages/x-components/src/components/animations/collapse-height.vue b/packages/x-components/src/components/animations/collapse-height.vue index 15e009d8f2..3bb53e95ce 100644 --- a/packages/x-components/src/components/animations/collapse-height.vue +++ b/packages/x-components/src/components/animations/collapse-height.vue @@ -39,13 +39,11 @@ }); - diff --git a/packages/x-components/src/components/animations/collapse-width.vue b/packages/x-components/src/components/animations/collapse-width.vue index add9282e38..ae0a63bb33 100644 --- a/packages/x-components/src/components/animations/collapse-width.vue +++ b/packages/x-components/src/components/animations/collapse-width.vue @@ -39,13 +39,11 @@ }); - diff --git a/packages/x-components/src/components/animations/cross-fade.vue b/packages/x-components/src/components/animations/cross-fade.vue index e4257f7146..06b6a3940e 100644 --- a/packages/x-components/src/components/animations/cross-fade.vue +++ b/packages/x-components/src/components/animations/cross-fade.vue @@ -28,22 +28,20 @@ }); - diff --git a/packages/x-components/src/components/animations/fade-and-slide.vue b/packages/x-components/src/components/animations/fade-and-slide.vue index 77ab1f411f..387eeefb4a 100644 --- a/packages/x-components/src/components/animations/fade-and-slide.vue +++ b/packages/x-components/src/components/animations/fade-and-slide.vue @@ -43,27 +43,21 @@ }); - diff --git a/packages/x-components/src/components/animations/fade.vue b/packages/x-components/src/components/animations/fade.vue index c7cc5218ef..eea5070a37 100644 --- a/packages/x-components/src/components/animations/fade.vue +++ b/packages/x-components/src/components/animations/fade.vue @@ -26,17 +26,15 @@ }); - diff --git a/packages/x-components/src/components/animations/staggered-fade-and-slide.vue b/packages/x-components/src/components/animations/staggered-fade-and-slide.vue index 4842d30f7b..4f187c6fe5 100644 --- a/packages/x-components/src/components/animations/staggered-fade-and-slide.vue +++ b/packages/x-components/src/components/animations/staggered-fade-and-slide.vue @@ -113,18 +113,16 @@ }); - diff --git a/packages/x-components/src/components/base-grid.vue b/packages/x-components/src/components/base-grid.vue index 4306a12f05..6f57d626e4 100644 --- a/packages/x-components/src/components/base-grid.vue +++ b/packages/x-components/src/components/base-grid.vue @@ -210,32 +210,31 @@ }); - diff --git a/packages/x-components/src/components/base-rating.vue b/packages/x-components/src/components/base-rating.vue index 6bebc7e83b..4836ec3b30 100644 --- a/packages/x-components/src/components/base-rating.vue +++ b/packages/x-components/src/components/base-rating.vue @@ -89,38 +89,38 @@ }); - diff --git a/packages/x-components/src/components/base-switch.vue b/packages/x-components/src/components/base-switch.vue index 59944daa92..7bffa4ef29 100644 --- a/packages/x-components/src/components/base-switch.vue +++ b/packages/x-components/src/components/base-switch.vue @@ -11,7 +11,7 @@ - diff --git a/packages/x-components/src/components/decorators/injection.consts.ts b/packages/x-components/src/components/decorators/injection.consts.ts index 8500abd42e..8fd80e6f42 100644 --- a/packages/x-components/src/components/decorators/injection.consts.ts +++ b/packages/x-components/src/components/decorators/injection.consts.ts @@ -2,7 +2,7 @@ import { Result, ResultVariant } from '@empathyco/x-types'; import { ListItem } from '../../utils/types'; /** - * Type of the key passed to {@link XProvide} and {@link XInject} to be type-safe. With this type + * Type of the key passed to `provide` and `inject` to be type-safe. With this type * you can declare the type of the injected value directly in the injection key. * * @example diff --git a/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue b/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue index b576104544..1a95b42642 100644 --- a/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue +++ b/packages/x-components/src/components/layouts/fixed-header-and-asides-layout.vue @@ -135,16 +135,16 @@ }); - - diff --git a/packages/x-components/src/components/panels/base-header-toggle-panel.vue b/packages/x-components/src/components/panels/base-header-toggle-panel.vue index 99879618e1..a7ad0bd223 100644 --- a/packages/x-components/src/components/panels/base-header-toggle-panel.vue +++ b/packages/x-components/src/components/panels/base-header-toggle-panel.vue @@ -82,7 +82,7 @@ }); - diff --git a/packages/x-components/src/components/result/base-result-link.vue b/packages/x-components/src/components/result/base-result-link.vue index 00dfbdd173..f62d326430 100644 --- a/packages/x-components/src/components/result/base-result-link.vue +++ b/packages/x-components/src/components/result/base-result-link.vue @@ -103,7 +103,7 @@ }); - diff --git a/packages/x-components/src/components/suggestions/base-suggestions.vue b/packages/x-components/src/components/suggestions/base-suggestions.vue index f7138f3f67..9fd0032a6c 100644 --- a/packages/x-components/src/components/suggestions/base-suggestions.vue +++ b/packages/x-components/src/components/suggestions/base-suggestions.vue @@ -164,15 +164,15 @@ }); - diff --git a/packages/x-components/src/shims-tsx.d.ts b/packages/x-components/src/shims-tsx.d.ts deleted file mode 100644 index 335c815769..0000000000 --- a/packages/x-components/src/shims-tsx.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Vue, { VNode } from 'vue'; - -declare global { - namespace JSX { - interface Element extends VNode {} - interface ElementClass extends Vue {} - } -} diff --git a/packages/x-components/src/shims-vue.d.ts b/packages/x-components/src/shims-vue.d.ts index 506bf2e5c9..40f3f4bdf7 100644 --- a/packages/x-components/src/shims-vue.d.ts +++ b/packages/x-components/src/shims-vue.d.ts @@ -1,5 +1,5 @@ declare module '*.vue' { import { DefineComponent } from 'vue'; - const component: DefineComponent<{}, {}, any>; + const component: DefineComponent; export default component; } diff --git a/packages/x-components/src/views/accessibility/wai-base-event-button.vue b/packages/x-components/src/views/accessibility/wai-base-event-button.vue index 8042ba0551..8654b43156 100644 --- a/packages/x-components/src/views/accessibility/wai-base-event-button.vue +++ b/packages/x-components/src/views/accessibility/wai-base-event-button.vue @@ -127,7 +127,7 @@ }); - diff --git a/packages/x-components/src/views/home/result.vue b/packages/x-components/src/views/home/result.vue index 3e8e41134c..6063ebdef4 100644 --- a/packages/x-components/src/views/home/result.vue +++ b/packages/x-components/src/views/home/result.vue @@ -64,5 +64,3 @@ } }); - - diff --git a/packages/x-components/src/views/pdp.vue b/packages/x-components/src/views/pdp.vue index fb41a4ed06..0842225740 100644 --- a/packages/x-components/src/views/pdp.vue +++ b/packages/x-components/src/views/pdp.vue @@ -42,5 +42,3 @@ } }); - - diff --git a/packages/x-components/src/x-modules/facets/components/facets/facets-provider.vue b/packages/x-components/src/x-modules/facets/components/facets/facets-provider.vue index 34b2bc39cb..425ce5427c 100644 --- a/packages/x-components/src/x-modules/facets/components/facets/facets-provider.vue +++ b/packages/x-components/src/x-modules/facets/components/facets/facets-provider.vue @@ -115,7 +115,7 @@ }); - diff --git a/packages/x-components/src/x-modules/facets/components/lists/filters-list.vue b/packages/x-components/src/x-modules/facets/components/lists/filters-list.vue index 41b7be589a..55f40b4245 100644 --- a/packages/x-components/src/x-modules/facets/components/lists/filters-list.vue +++ b/packages/x-components/src/x-modules/facets/components/lists/filters-list.vue @@ -114,7 +114,7 @@ }); - diff --git a/packages/x-components/src/x-modules/facets/components/lists/selected-filters-list.vue b/packages/x-components/src/x-modules/facets/components/lists/selected-filters-list.vue index 98f123fb14..ed70086442 100644 --- a/packages/x-components/src/x-modules/facets/components/lists/selected-filters-list.vue +++ b/packages/x-components/src/x-modules/facets/components/lists/selected-filters-list.vue @@ -39,7 +39,8 @@ - - - diff --git a/packages/x-components/src/x-modules/search-box/components/search-input.vue b/packages/x-components/src/x-modules/search-box/components/search-input.vue index a828851df7..092befba64 100644 --- a/packages/x-components/src/x-modules/search-box/components/search-input.vue +++ b/packages/x-components/src/x-modules/search-box/components/search-input.vue @@ -280,7 +280,7 @@ }); - diff --git a/packages/x-components/src/x-modules/search/components/partial-results-list.vue b/packages/x-components/src/x-modules/search/components/partial-results-list.vue index 7af1027b26..7e80a0f64e 100644 --- a/packages/x-components/src/x-modules/search/components/partial-results-list.vue +++ b/packages/x-components/src/x-modules/search/components/partial-results-list.vue @@ -84,7 +84,7 @@ }); - diff --git a/packages/x-components/src/x-modules/search/components/redirection.vue b/packages/x-components/src/x-modules/search/components/redirection.vue index c028c3d881..ab2ab0720c 100644 --- a/packages/x-components/src/x-modules/search/components/redirection.vue +++ b/packages/x-components/src/x-modules/search/components/redirection.vue @@ -143,8 +143,6 @@ }); - - ## Events diff --git a/packages/x-components/src/x-modules/search/components/sort-list.vue b/packages/x-components/src/x-modules/search/components/sort-list.vue index 7591acf891..40885eec2d 100644 --- a/packages/x-components/src/x-modules/search/components/sort-list.vue +++ b/packages/x-components/src/x-modules/search/components/sort-list.vue @@ -91,7 +91,7 @@ }); - diff --git a/packages/x-components/src/components/animations/staggered-fade-and-slide.vue b/packages/x-components/src/components/animations/staggered-fade-and-slide.vue index 4f187c6fe5..fd46700548 100644 --- a/packages/x-components/src/components/animations/staggered-fade-and-slide.vue +++ b/packages/x-components/src/components/animations/staggered-fade-and-slide.vue @@ -107,7 +107,8 @@ return { name, onEnter, - onAfterEnter + onAfterEnter, + transitionDurationInMs: `${transitionDuration}ms` }; } }); @@ -117,12 +118,12 @@ /* 1. Declare transitions */ .x-staggered-fade-and-slide-enter-active, .x-staggered-fade-and-slide-leave-active { - transition: 250ms ease-out; + transition: v-bind(transitionDurationInMs) ease-out; transition-property: opacity, transform; } .x-staggered-fade-and-slide-move { - transition: transform 250ms ease-out; + transition: transform v-bind(transitionDurationInMs) ease-out; } /* 2. Declare enter, from and leave to state */ diff --git a/packages/x-components/src/components/auto-progress-bar.vue b/packages/x-components/src/components/auto-progress-bar.vue index 094c7c13e3..1548feb8ee 100644 --- a/packages/x-components/src/components/auto-progress-bar.vue +++ b/packages/x-components/src/components/auto-progress-bar.vue @@ -54,7 +54,7 @@ }); - diff --git a/packages/x-components/src/components/layouts/multi-column-max-width-layout.vue b/packages/x-components/src/components/layouts/multi-column-max-width-layout.vue index 62fe313ee5..bb53627668 100644 --- a/packages/x-components/src/components/layouts/multi-column-max-width-layout.vue +++ b/packages/x-components/src/components/layouts/multi-column-max-width-layout.vue @@ -128,7 +128,7 @@ }); - - diff --git a/packages/x-components/src/components/layouts/single-column-layout.vue b/packages/x-components/src/components/layouts/single-column-layout.vue index 8f465b4518..7a077638e8 100644 --- a/packages/x-components/src/components/layouts/single-column-layout.vue +++ b/packages/x-components/src/components/layouts/single-column-layout.vue @@ -110,8 +110,8 @@ }); - diff --git a/packages/x-components/src/design-system-deprecated/utilities/dev-mode.css b/packages/x-components/src/design-system-deprecated/utilities/dev-mode.css new file mode 100644 index 0000000000..8b4b9f0eb9 --- /dev/null +++ b/packages/x-components/src/design-system-deprecated/utilities/dev-mode.css @@ -0,0 +1,12 @@ +.dev-mode .slot-helper { + font-family: inherit; + color: grey; + box-sizing: border-box; + display: flex; + height: 100%; + width: 100%; + justify-content: center; + align-items: center; + border: dashed 1px grey; + border-radius: 10px; +} diff --git a/packages/x-components/src/design-system-deprecated/utilities/dev-mode.scss b/packages/x-components/src/design-system-deprecated/utilities/dev-mode.scss deleted file mode 100644 index 46871cd3ae..0000000000 --- a/packages/x-components/src/design-system-deprecated/utilities/dev-mode.scss +++ /dev/null @@ -1,14 +0,0 @@ -.dev-mode { - .slot-helper { - font-family: inherit; - color: grey; - box-sizing: border-box; - display: flex; - height: 100%; - width: 100%; - justify-content: center; - align-items: center; - border: dashed 1px grey; - border-radius: 10px; - } -} diff --git a/packages/x-components/src/views/ResultApp.vue b/packages/x-components/src/views/ResultApp.vue index 14ba6f8bfc..37ea764ea6 100644 --- a/packages/x-components/src/views/ResultApp.vue +++ b/packages/x-components/src/views/ResultApp.vue @@ -98,7 +98,7 @@ }); - diff --git a/packages/x-components/src/views/accessibility/wai-base-event-button.vue b/packages/x-components/src/views/accessibility/wai-base-event-button.vue index 8654b43156..37afc4eb6d 100644 --- a/packages/x-components/src/views/accessibility/wai-base-event-button.vue +++ b/packages/x-components/src/views/accessibility/wai-base-event-button.vue @@ -27,7 +27,7 @@

    BaseResultAddToCart

    - + Add to cart
    diff --git a/packages/x-components/src/views/home/Home.vue b/packages/x-components/src/views/home/Home.vue index e3f30b6fba..d01d2ad9bb 100644 --- a/packages/x-components/src/views/home/Home.vue +++ b/packages/x-components/src/views/home/Home.vue @@ -690,9 +690,9 @@ + From aff3151818c64885d7c28e69f511d33ae41b38f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Antonio=20Caba=C3=B1eros?= Date: Tue, 3 Sep 2024 12:08:21 +0200 Subject: [PATCH 22/43] ci(linter): fix linter issues to pass the CI (#1606) --- packages/x-components/.eslintrc.js | 13 +++- .../__tests__/location-provider.spec.ts | 11 +-- .../__tests__/snippet-callbacks.spec.ts | 24 +----- .../__tests__/use-disable-animation.spec.ts | 30 +++----- .../__tests__/base-events-modal.spec.ts | 9 ++- .../__tests__/base-id-modal-close.spec.ts | 2 +- .../__tests__/base-id-modal-open.spec.ts | 55 +++++--------- .../modals/__tests__/base-id-modal.spec.ts | 2 +- .../modals/__tests__/close-main-modal.spec.ts | 13 ++-- .../modals/__tests__/main-modal.spec.ts | 10 +-- .../modals/__tests__/open-main-modal.spec.ts | 8 +- .../base-id-toggle-panel-button.spec.ts | 4 +- .../__tests__/base-id-toggle-panel.spec.ts | 14 ++-- .../panels/__tests__/base-tabs-panel.spec.ts | 2 +- .../__tests__/base-result-add-to-cart.spec.ts | 76 ++++++------------- .../scroll/__tests__/base-scroll.spec.ts | 42 ++-------- .../src/components/scroll/base-scroll.vue | 8 +- .../__tests__/base-suggestion.spec.ts | 23 +++--- .../x-components/src/composables/use-x-bus.ts | 1 + .../x-components/src/plugins/x-emitters.ts | 8 +- .../x-components/src/store/store.types.ts | 5 +- .../src/store/utils/getters-proxy.utils.ts | 10 +-- .../src/store/utils/query.utils.ts | 3 +- .../src/store/utils/status-store.utils.ts | 6 +- .../src/utils/currency-formatter.ts | 6 +- packages/x-components/src/views/home/Home.vue | 29 ++++--- .../x-components/src/views/home/aside.vue | 36 ++++----- .../namespaced-wires-factory.spec.ts | 4 +- .../wiring/__tests__/wires-factory.spec.ts | 4 +- .../wiring/__tests__/wires-operators.spec.ts | 4 +- .../src/wiring/namespaced-wires.operators.ts | 3 +- .../x-components/src/wiring/wiring.types.ts | 2 +- .../x-components/src/wiring/wiring.utils.ts | 4 +- .../extra-params/components/extra-params.vue | 4 +- .../src/x-modules/facets/store/module.ts | 3 +- .../store/getters/history-queries.getter.ts | 3 +- .../fetch-next-query-preview.action.ts | 8 +- .../x-modules/queries-preview/store/types.ts | 12 +-- .../x-modules/scroll/components/scroll.vue | 2 +- .../src/x-modules/scroll/store/module.ts | 3 +- .../search-box/components/search-button.vue | 4 +- .../store/mutations/set-params.mutation.ts | 1 - 42 files changed, 215 insertions(+), 296 deletions(-) diff --git a/packages/x-components/.eslintrc.js b/packages/x-components/.eslintrc.js index 75aafd665d..1e20c248d9 100644 --- a/packages/x-components/.eslintrc.js +++ b/packages/x-components/.eslintrc.js @@ -1,6 +1,13 @@ module.exports = { extends: ['plugin:@empathyco/x/all'], - ignorePatterns: ['cypress.config.ts'], + // TODO - Reactivate linter for unit and e2e tests once they pass. + ignorePatterns: [ + 'cypress.config.ts', + '**/__tests__/**/*.spec.ts', + '**/tests/**/*.spec.ts', + '**/__tests__/**/utils.ts', + '**/tests/**/utils.ts' + ], parserOptions: { tsconfigRootDir: __dirname, project: 'tsconfig.eslint.json' @@ -8,8 +15,10 @@ module.exports = { rules: { 'no-dupe-class-members': 'off', '@typescript-eslint/no-unused-vars-experimental': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', 'vue/require-default-prop': 'off', - '@typescript-eslint/explicit-function-return-type': 'off' + 'vue/multi-word-component-names': 'off', + 'vue/no-v-for-template-key': 'off' }, overrides: [ { diff --git a/packages/x-components/src/components/__tests__/location-provider.spec.ts b/packages/x-components/src/components/__tests__/location-provider.spec.ts index 8888a2e8bc..5e8fd75f3c 100644 --- a/packages/x-components/src/components/__tests__/location-provider.spec.ts +++ b/packages/x-components/src/components/__tests__/location-provider.spec.ts @@ -1,15 +1,12 @@ -import { mount, VueWrapper } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import { defineComponent, inject } from 'vue'; import { FeatureLocation } from '../../types'; import LocationProvider from '../location-provider.vue'; const Child = defineComponent({ - name: 'Child', - template: `{{ injectedLocation }}`, - setup() { - const injectedLocation = inject('location'); - return { injectedLocation }; - } + name: 'ChildItem', + setup: () => ({ injectedLocation: inject('location') }), + template: `{{ injectedLocation }}` }); /** diff --git a/packages/x-components/src/components/__tests__/snippet-callbacks.spec.ts b/packages/x-components/src/components/__tests__/snippet-callbacks.spec.ts index 6061bcdfd2..0edca06fc5 100644 --- a/packages/x-components/src/components/__tests__/snippet-callbacks.spec.ts +++ b/packages/x-components/src/components/__tests__/snippet-callbacks.spec.ts @@ -1,16 +1,14 @@ -import { mount, VueWrapper } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import { baseSnippetConfig } from '../../views/base-config'; -import { XEventListeners } from '../../x-installer/api/api.types'; import SnippetCallbacks from '../snippet-callbacks.vue'; import { bus } from '../../plugins/x-bus'; import { dummyCreateEmitter } from '../../__tests__/bus.dummy'; // Making bus not repeat subjects +// eslint-disable-next-line @typescript-eslint/no-unsafe-argument jest.spyOn(bus, 'createEmitter' as any).mockImplementation(dummyCreateEmitter.bind(bus) as any); -function renderSnippetCallbacks({ - callbacks = {} -}: RenderSnippetCallbacksOptions = {}): RenderSnippetCallbacksAPI { +function renderSnippetCallbacks({ callbacks = {} } = {}) { const wrapper = mount(SnippetCallbacks, { global: { provide: { @@ -95,19 +93,3 @@ describe('testing SnippetCallbacks component', () => { }); }); }); - -/** - * Options to configure how the snippet callbacks component should be rendered. - */ -interface RenderSnippetCallbacksOptions { - /** The callbacks value to be provided. */ - callbacks?: XEventListeners; -} - -/** - * Tools to test how the snippet callbacks component behaves. - */ -interface RenderSnippetCallbacksAPI { - /** The wrapper of the container element. */ - wrapper: VueWrapper; -} diff --git a/packages/x-components/src/components/animations/__tests__/use-disable-animation.spec.ts b/packages/x-components/src/components/animations/__tests__/use-disable-animation.spec.ts index 33a09a2542..7cb10b12b9 100644 --- a/packages/x-components/src/components/animations/__tests__/use-disable-animation.spec.ts +++ b/packages/x-components/src/components/animations/__tests__/use-disable-animation.spec.ts @@ -1,8 +1,9 @@ import { mount } from '@vue/test-utils'; -import { defineComponent, provide, ref, h, Transition } from 'vue'; +import { defineComponent, provide, ref, h, TransitionGroup } from 'vue'; import { DISABLE_ANIMATIONS_KEY } from '../../decorators/injection.consts'; import { useDisableAnimation } from '../use-disable-animation'; -import { TransitionGroup } from 'vue'; + +// eslint-disable-next-line vue/one-component-per-file const Provider = defineComponent({ props: { disableAnimation: Boolean @@ -13,30 +14,27 @@ const Provider = defineComponent({ } }); +// eslint-disable-next-line vue/one-component-per-file const Animation = defineComponent({ setup() { return useDisableAnimation('x-animation'); }, template: ` - +

    Animation

    -
    + ` }); -function renderDisableAnimation({ disableAnimation = true }: DisableAnimationOptions = {}) { +function renderDisableAnimation({ disableAnimation = true } = {}) { const wrapper = mount({ template: ` - - - - `, + + + + `, components: { Provider, Animation }, - data() { - return { - disableAnimation - }; - } + data: () => ({ disableAnimation }) }); return { @@ -58,7 +56,3 @@ describe('testing disable animation', () => { expect(transitionGroup.attributes('name')).toBe('x-animation'); }); }); - -interface DisableAnimationOptions { - disableAnimation?: boolean; -} diff --git a/packages/x-components/src/components/modals/__tests__/base-events-modal.spec.ts b/packages/x-components/src/components/modals/__tests__/base-events-modal.spec.ts index 39fa42acd6..cc66bdb1f2 100644 --- a/packages/x-components/src/components/modals/__tests__/base-events-modal.spec.ts +++ b/packages/x-components/src/components/modals/__tests__/base-events-modal.spec.ts @@ -1,10 +1,11 @@ import { DOMWrapper, mount, VueWrapper } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import BaseEventsModal from '../base-events-modal.vue'; import { PropsWithType } from '../../../utils/types'; import { XEventsTypes, XEvent } from '../../../wiring/events.types'; -import { XPlugin } from '../../../plugins/index'; -import { nextTick } from 'vue'; +import { XPlugin } from '../../../plugins'; + /** * Mounts a {@link BaseEventsModal} component with the provided options and offers an API to easily * test it. @@ -108,7 +109,7 @@ describe('testing Base Events Modal component', () => { it('allows to customize the events listened for opening & closing', async () => { const eventToOpen = 'UserFocusedSearchBox'; const eventToClose = 'UserPressedClearSearchBoxButton'; - const { emit, getModalContent, wrapper } = mountBaseEventsModal({ + const { emit, getModalContent } = mountBaseEventsModal({ eventsToOpenModal: [eventToOpen], eventsToCloseModal: [eventToClose] }); @@ -129,7 +130,7 @@ describe('testing Base Events Modal component', () => { it('allows to customize the event emitted when clicking out of the modal', async () => { const bodyClickEvent = 'UserClickedASimpleFilter'; - const { wrapper, clickModalOverlay, emit, getModalContent } = mountBaseEventsModal({ + const { clickModalOverlay, emit, getModalContent } = mountBaseEventsModal({ bodyClickEvent, eventsToCloseModal: [bodyClickEvent] }); diff --git a/packages/x-components/src/components/modals/__tests__/base-id-modal-close.spec.ts b/packages/x-components/src/components/modals/__tests__/base-id-modal-close.spec.ts index cc7ef01f79..562e3c251e 100644 --- a/packages/x-components/src/components/modals/__tests__/base-id-modal-close.spec.ts +++ b/packages/x-components/src/components/modals/__tests__/base-id-modal-close.spec.ts @@ -1,8 +1,8 @@ import { mount, VueWrapper } from '@vue/test-utils'; +import { defineComponent } from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import BaseIdModalClose from '../base-id-modal-close.vue'; import { XPlugin } from '../../../plugins/index'; -import { defineComponent } from 'vue'; /** * Renders the {@link BaseIdModalClose} with the provided options. diff --git a/packages/x-components/src/components/modals/__tests__/base-id-modal-open.spec.ts b/packages/x-components/src/components/modals/__tests__/base-id-modal-open.spec.ts index fcaea7e304..3acb121715 100644 --- a/packages/x-components/src/components/modals/__tests__/base-id-modal-open.spec.ts +++ b/packages/x-components/src/components/modals/__tests__/base-id-modal-open.spec.ts @@ -1,4 +1,4 @@ -import { mount, VueWrapper } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import BaseIdModalOpen from '../base-id-modal-open.vue'; import { bus } from '../../../plugins/x-bus'; @@ -12,34 +12,31 @@ import { XPlugin } from '../../../plugins/index'; * @returns An small API to test the component. */ function renderBaseIdModalOpen({ - id = 'myModal', - template = `` -}: RenderBaseIdModalOpenOptions = {}): RenderBaseIdModalOpenAPI { + template = `` +} = {}) { // Making bus not repeat subjects + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument jest.spyOn(bus, 'createEmitter' as any).mockImplementation(dummyCreateEmitter.bind(bus) as any); + const modalId = 'myModal'; + const containerWrapper = mount( { - components: { - BaseIdModalOpen - }, + components: { BaseIdModalOpen }, template }, { - props: { modalId: id }, + props: { modalId }, global: { plugins: [installNewXPlugin()] } } ); const wrapper = containerWrapper.findComponent(BaseIdModalOpen); - const modalId = wrapper.props('modalId'); return { wrapper, modalId, - async click() { - await wrapper.trigger('click'); - } + click: async () => await wrapper.trigger('click') }; } @@ -63,16 +60,16 @@ describe('testing Open Button component', () => { expect(wrapper.text()).toEqual('Open'); }); - // eslint-disable-next-line max-len it('renders custom content replacing the default exposing the function that opens the modal', async () => { const { wrapper, click, modalId } = renderBaseIdModalOpen({ - template: ` - - ` + template: ` + + + ` }); const listener = jest.fn(); @@ -82,25 +79,9 @@ describe('testing Open Button component', () => { expect(listener).toHaveBeenCalledTimes(0); - wrapper.find(getDataTestSelector('custom-open-modal')).trigger('click'); + await wrapper.find(getDataTestSelector('custom-open-modal')).trigger('click'); expect(listener).toHaveBeenCalledTimes(1); expect(listener).toHaveBeenCalledWith(modalId); }); }); - -interface RenderBaseIdModalOpenOptions { - /** The id of the modal to open. */ - id?: string; - /** The template to render. */ - template?: string; -} - -interface RenderBaseIdModalOpenAPI { - /** The wrapper for the modal component. */ - wrapper: VueWrapper; - /** The modal id. */ - modalId: string; - /** Clicks the button. */ - click: () => Promise; -} diff --git a/packages/x-components/src/components/modals/__tests__/base-id-modal.spec.ts b/packages/x-components/src/components/modals/__tests__/base-id-modal.spec.ts index 6cef629bd9..eccee166d6 100644 --- a/packages/x-components/src/components/modals/__tests__/base-id-modal.spec.ts +++ b/packages/x-components/src/components/modals/__tests__/base-id-modal.spec.ts @@ -1,5 +1,5 @@ import { DOMWrapper, mount, VueWrapper } from '@vue/test-utils'; -import Vue, { nextTick } from 'vue'; +import { nextTick } from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import { XEvent } from '../../../wiring/events.types'; import BaseIdModal from '../base-id-modal.vue'; diff --git a/packages/x-components/src/components/modals/__tests__/close-main-modal.spec.ts b/packages/x-components/src/components/modals/__tests__/close-main-modal.spec.ts index e87337648f..a43ae54ff7 100644 --- a/packages/x-components/src/components/modals/__tests__/close-main-modal.spec.ts +++ b/packages/x-components/src/components/modals/__tests__/close-main-modal.spec.ts @@ -1,5 +1,5 @@ import { mount, VueWrapper } from '@vue/test-utils'; -import Vue, { defineComponent } from 'vue'; +import { defineComponent } from 'vue'; import { AnyFunction } from '@empathyco/x-utils'; import { installNewXPlugin } from '../../../__tests__/utils'; import CloseMainModal from '../close-main-modal.vue'; @@ -19,9 +19,8 @@ function renderCloseMainModal({ components: { CloseMainModal }, - - template, - methods + methods, + template }); const wrapper = mount(containerWrapper, { global: { plugins: [installNewXPlugin()] } @@ -29,15 +28,13 @@ function renderCloseMainModal({ return { wrapper: wrapper.findComponent(CloseMainModal), - async click() { - await wrapper.trigger('click'); - } + click: async () => await wrapper.trigger('click') }; } describe('testing Close Main Modal button component', () => { it('emits UserClickedCloseX by default when clicked', async () => { - const { wrapper, click } = renderCloseMainModal(); + const { click } = renderCloseMainModal(); const onUserClickedCloseX = jest.fn(); XPlugin.bus.on('UserClickedCloseX').subscribe(onUserClickedCloseX); diff --git a/packages/x-components/src/components/modals/__tests__/main-modal.spec.ts b/packages/x-components/src/components/modals/__tests__/main-modal.spec.ts index 957fc5131b..5140da9dfd 100644 --- a/packages/x-components/src/components/modals/__tests__/main-modal.spec.ts +++ b/packages/x-components/src/components/modals/__tests__/main-modal.spec.ts @@ -1,10 +1,11 @@ import { DOMWrapper, mount, VueWrapper } from '@vue/test-utils'; +import { defineComponent, nextTick } from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import MainModal from '../main-modal.vue'; import { PropsWithType } from '../../../utils/types'; -import { XEventsTypes } from '../../../wiring/events.types'; -import { XPlugin } from '../../../plugins/index'; -import { defineComponent, nextTick } from 'vue'; +import { XEventsTypes } from '../../../wiring'; +import { XPlugin } from '../../../plugins'; + /** * Renders a {@link MainModal} component with the provided options and offers an API to easily * test it. @@ -24,7 +25,6 @@ function renderMainModal({ template, global: { plugins: [installNewXPlugin()] }, - attachTo: parent // necessary to make the focus on body event to work in some environments. }); const wrapper = mount(containerWrapper, { @@ -37,7 +37,7 @@ function renderMainModal({ await wrapper.find(getDataTestSelector('modal-overlay'))?.trigger('click'); }, async emit(event) { - XPlugin.bus.emit(event); + await XPlugin.bus.emit(event); await nextTick(); }, getModalContent() { diff --git a/packages/x-components/src/components/modals/__tests__/open-main-modal.spec.ts b/packages/x-components/src/components/modals/__tests__/open-main-modal.spec.ts index 34db9fc1d2..adca0920ca 100644 --- a/packages/x-components/src/components/modals/__tests__/open-main-modal.spec.ts +++ b/packages/x-components/src/components/modals/__tests__/open-main-modal.spec.ts @@ -1,5 +1,5 @@ import { mount, VueWrapper } from '@vue/test-utils'; -import Vue, { defineComponent } from 'vue'; +import { defineComponent } from 'vue'; import { AnyFunction } from '@empathyco/x-utils'; import { installNewXPlugin } from '../../../__tests__/utils'; import OpenMainModal from '../open-main-modal.vue'; @@ -19,8 +19,8 @@ function renderOpenMainModal({ components: { OpenMainModal }, - template, - methods + methods, + template }); const wrapper = mount(containerWrapper, { @@ -37,7 +37,7 @@ function renderOpenMainModal({ describe('testing Open Main Modal button component', () => { it('emits UserClickedOpenX by default when clicked', async () => { - const { wrapper, click } = renderOpenMainModal(); + const { click } = renderOpenMainModal(); const onUserClickedOpenX = jest.fn(); XPlugin.bus.on('UserClickedOpenX').subscribe(onUserClickedOpenX); diff --git a/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel-button.spec.ts b/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel-button.spec.ts index 478734ae5d..61deb1334c 100644 --- a/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel-button.spec.ts +++ b/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel-button.spec.ts @@ -1,9 +1,9 @@ import { AnyFunction } from '@empathyco/x-utils'; import { mount, VueWrapper } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import { XEvent } from '../../../wiring'; import BaseIdTogglePanelButton from '../base-id-toggle-panel-button.vue'; -import { nextTick } from 'vue'; import { XPlugin } from '../../../plugins/index'; /** @@ -41,7 +41,7 @@ function renderBaseIdToggleButton({ describe('testing BaseIdTogglePanelButton component', () => { it('emits UserClickedPanelToggleButton with the panel id as payload', async () => { - const { wrapper, panelId, click } = renderBaseIdToggleButton(); + const { panelId, click } = renderBaseIdToggleButton(); const listener = jest.fn(); XPlugin.bus.on('UserClickedPanelToggleButton').subscribe(listener); diff --git a/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel.spec.ts b/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel.spec.ts index b32cc25f77..d1cdfdc932 100644 --- a/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel.spec.ts +++ b/packages/x-components/src/components/panels/__tests__/base-id-toggle-panel.spec.ts @@ -1,3 +1,10 @@ +import { mount, VueWrapper } from '@vue/test-utils'; +import { nextTick } from 'vue'; +import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; +import { XEvent } from '../../../wiring'; +import BaseIdTogglePanel from '../base-id-toggle-panel.vue'; +import { XPlugin } from '../../../plugins/index'; + /** * Mounts a {@link BaseIdTogglePanel} component with the provided options and offers an API to * easily test it. @@ -5,13 +12,6 @@ * @param options - The options to render the component with. * @returns An API to test the component. */ -import { mount, VueWrapper } from '@vue/test-utils'; -import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; -import { XEvent } from '../../../wiring'; -import BaseIdTogglePanel from '../base-id-toggle-panel.vue'; -import { nextTick } from 'vue'; -import { XPlugin } from '../../../plugins/index'; - function mountBaseIdTogglePanel({ panelId = 'myToggle', defaultSlot = `Panel: ${panelId}`, diff --git a/packages/x-components/src/components/panels/__tests__/base-tabs-panel.spec.ts b/packages/x-components/src/components/panels/__tests__/base-tabs-panel.spec.ts index 2167f6f926..3ecaf546ce 100644 --- a/packages/x-components/src/components/panels/__tests__/base-tabs-panel.spec.ts +++ b/packages/x-components/src/components/panels/__tests__/base-tabs-panel.spec.ts @@ -1,7 +1,7 @@ import { mount, VueWrapper, DOMWrapper } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { getDataTestSelector } from '../../../__tests__/utils'; import BaseTabsPanel from '../base-tabs-panel.vue'; -import { nextTick } from 'vue'; /** * Function that returns a BaseTabsPanel wrapper. The animation prop is not diff --git a/packages/x-components/src/components/result/__tests__/base-result-add-to-cart.spec.ts b/packages/x-components/src/components/result/__tests__/base-result-add-to-cart.spec.ts index 9a6a345c4a..eeefdcf923 100644 --- a/packages/x-components/src/components/result/__tests__/base-result-add-to-cart.spec.ts +++ b/packages/x-components/src/components/result/__tests__/base-result-add-to-cart.spec.ts @@ -1,47 +1,40 @@ -import { Result } from '@empathyco/x-types'; -import { Dictionary } from '@empathyco/x-utils'; -import { mount, VueWrapper, DOMWrapper } from '@vue/test-utils'; -import { XBus } from '@empathyco/x-bus'; +import { mount } from '@vue/test-utils'; import { createResultStub } from '../../../__stubs__/results-stubs.factory'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import BaseResultAddToCart from '../base-result-add-to-cart.vue'; -import { WireMetadata, XEventsTypes } from '../../../wiring/index'; -import { XPlugin } from '../../../plugins/index'; +import { XPlugin } from '../../../plugins'; -describe('testing BaseResultAddToCart component', () => { - function renderAddToCart({ - result = createResultStub('Result Test'), - template = '', - methods = {} - }: RenderAddToCartOptions): RenderAddToCartApi { - const wrapper = mount( - { template, data: () => ({ result }), methods }, - { - components: { BaseResultAddToCart }, - global: { plugins: [installNewXPlugin()] } - } - ); - return { - clickAddToCart(): Promise { - return wrapper - .find(getDataTestSelector('result-add-to-cart')) - .trigger('click') as Promise; - }, - addToCartWrapper: wrapper.find(getDataTestSelector('result-add-to-cart')) - }; - } +function render({ + result = createResultStub('Result Test'), + template = '', + methods = {} +} = {}) { + const wrapper = mount( + { template, data: () => ({ result }), methods }, + { + components: { BaseResultAddToCart }, + global: { plugins: [installNewXPlugin()] } + } + ); + return { + clickAddToCart: () => wrapper.find(getDataTestSelector('result-add-to-cart')).trigger('click'), + addToCartWrapper: wrapper.find(getDataTestSelector('result-add-to-cart')) + }; +} +describe('testing BaseResultAddToCart component', () => { it('emits UserClickedResultAddToCart when the user click on the component', () => { const testResult = createResultStub('My Result'); - const { clickAddToCart } = renderAddToCart({ result: testResult }); + const { clickAddToCart } = render({ result: testResult }); const listener = jest.fn(); XPlugin.bus.on('UserClickedResultAddToCart').subscribe(listener); clickAddToCart(); + expect(listener).toHaveBeenCalledWith(testResult); }); it('renders the content overriding default slot', () => { - const { addToCartWrapper } = renderAddToCart({ + const { addToCartWrapper } = render({ template: ` @@ -59,7 +52,7 @@ describe('testing BaseResultAddToCart component', () => { it('uses the listeners passed', () => { const listener = jest.fn(); - const { clickAddToCart } = renderAddToCart({ + const { clickAddToCart } = render({ template: '', methods: { miClick: listener @@ -71,24 +64,3 @@ describe('testing BaseResultAddToCart component', () => { expect(listener).toHaveBeenCalledWith(expect.any(MouseEvent)); }); }); - -/** - * The options for the `renderAddToCart` function. - */ -interface RenderAddToCartOptions { - /** The result to pass to `BaseResultAddToCart` as prop. A stub is used by default.*/ - result?: Result; - /** - * The template to render. Remember to use `:result="result"` as prop of the - * `BaseResultAddToCart`. - */ - template?: string; - /** The methods to add to mounted component to test listeners in the `BaseResultAddToCart`. */ - methods?: Dictionary<() => void>; -} -interface RenderAddToCartApi { - /** Triggers the click on the `BaseResultAddToCart`. */ - clickAddToCart: () => Promise; - /** The `BaseResultAddToCart` wrapper to use it for testing. */ - addToCartWrapper: DOMWrapper; -} diff --git a/packages/x-components/src/components/scroll/__tests__/base-scroll.spec.ts b/packages/x-components/src/components/scroll/__tests__/base-scroll.spec.ts index a50b2eb22f..c453215009 100644 --- a/packages/x-components/src/components/scroll/__tests__/base-scroll.spec.ts +++ b/packages/x-components/src/components/scroll/__tests__/base-scroll.spec.ts @@ -1,8 +1,7 @@ -import { mount, VueWrapper } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; -import { XEvent } from '../../../wiring/events.types'; import BaseScroll from '../base-scroll.vue'; -import { nextTick } from 'vue'; import { XPlugin } from '../../../plugins/index'; /** @@ -21,9 +20,9 @@ async function renderBaseScroll({ scrollHeight = 800, clientHeight = 200, distanceToBottom = 100, - resetOnChange, - resetOn -}: RenderBaseScrollOptions = {}): Promise { + resetOnChange = true, + resetOn = ['UserAcceptedAQuery'] +} = {}) { const wrapperContainer = mount( { components: { @@ -53,9 +52,9 @@ async function renderBaseScroll({ return { wrapper, - async scroll({ to, durationMs }) { + scroll: async ({ to = 0, durationMs = 0 }) => { scrollElement.scrollTop = to; - wrapper.trigger('scroll'); + await wrapper.trigger('scroll'); jest.advanceTimersByTime(durationMs); await nextTick(); } @@ -103,7 +102,6 @@ describe('testing Base Scroll Component', () => { expect(wrapper.emitted('scroll')).toEqual([[150]]); }); - // eslint-disable-next-line max-len it('emits the `scroll:direction-change` event when the user changes scrolling direction', async () => { const { wrapper, scroll } = await renderBaseScroll({ throttleMs: 200 @@ -160,7 +158,6 @@ describe('testing Base Scroll Component', () => { expect(wrapper.emitted('scroll:direction-change')).toEqual([['DOWN'], ['UP']]); }); - // eslint-disable-next-line max-len it('emits `scroll:almost-at-end` and `scroll:at-end` when the user scrolls to the bottom', async () => { const { wrapper, scroll } = await renderBaseScroll({ throttleMs: 200, @@ -228,28 +225,3 @@ describe('testing Base Scroll Component', () => { expect(wrapper.element.scrollTop).toEqual(300); }); }); - -interface RenderBaseScrollOptions { - /** The template to be rendered. */ - template?: string; - /** Number for throttle of scroll. */ - throttleMs?: number; - /** Number of scroll height of scroll. */ - scrollHeight?: number; - /** Number of client height of scroll. */ - clientHeight?: number; - /** Distance to the end of the scroll. */ - distanceToBottom?: number; - /** Flag to enable or disable resetting the scroll when the events at {@link BaseScroll.resetOn} - * are emitted. */ - resetOnChange?: boolean; - /** List of events to reset the scroll when they are emitted. */ - resetOn?: XEvent[]; -} - -interface RenderBaseScrollAPI { - /** The wrapper for the base scroll component. */ - wrapper: VueWrapper; - /** Function that launch the trigger scroll. */ - scroll: (options: { to: number; durationMs: number }) => Promise; -} diff --git a/packages/x-components/src/components/scroll/base-scroll.vue b/packages/x-components/src/components/scroll/base-scroll.vue index 3d0ad1ebe2..724153c3ff 100644 --- a/packages/x-components/src/components/scroll/base-scroll.vue +++ b/packages/x-components/src/components/scroll/base-scroll.vue @@ -10,7 +10,7 @@ + + +## Events + +This component emits no events. + +## See it in action + + + +:::warning Backend microservice required To use this component, the QuerySignals microservice +must be implemented. ::: + + + +Usually, this component is going to be used together with the `ResultsList` one. Related prompts +groups will be inserted between the results, guiding users to discover new searches directly from +the results list. + +```vue live + + + +``` + +### Play with the index that related prompts groups are inserted at + +The component allows to customise where are the related prompts groups inserted. In the following +example, the first group of related prompts will be inserted at the index `48` (`offset`), and then +a second group will be inserted at index `120` because of the `frequency` prop configured to `72`. +Finally, a third group will be inserted at index `192`. Because `maxGroups` is configured to `3`, no +more groups will be inserted. Each one of this groups will have up to `6` related prompts +(`maxRelatedPromptsPerGroup`). + +```vue live + + + +``` + +### Showing/hiding first related prompts group when no more items + +By default, the first related prompts group will be inserted when the total number of results is +smaller than the offset, but this behavior can be deactivated by setting the `showOnlyAfterOffset` +to `true`. + +```vue live + + + +``` + +### Customise the layout of the component + +This component will render by default the `id` of each search item, both the injected, and for the +groups of related prompts generated, but the common case is to integrate it with another layout +component, for example the `BaseGrid`. To do so, you can use the `default` slot + +```vue + + + +``` + diff --git a/packages/x-components/src/x-modules/related-prompts/store/__tests__/actions.spec.ts b/packages/x-components/src/x-modules/related-prompts/store/__tests__/actions.spec.ts new file mode 100644 index 0000000000..79efe65bec --- /dev/null +++ b/packages/x-components/src/x-modules/related-prompts/store/__tests__/actions.spec.ts @@ -0,0 +1,118 @@ +import { mount } from '@vue/test-utils'; +import { Store } from 'vuex'; +import { getRelatedPromptsStub } from '../../../../__stubs__'; +import { getMockedAdapter, installNewXPlugin } from '../../../../__tests__/utils'; +import { SafeStore } from '../../../../store/__tests__/utils'; +import { + RelatedPromptsActions, + RelatedPromptsGetters, + RelatedPromptsMutations, + RelatedPromptsState +} from '../types'; +import { relatedPromptsXStoreModule } from '../module'; +import { resetRelatedPromptsStateWith } from './utils'; + +describe('testing related prompts module actions', () => { + const mockedRelatedPrompts = getRelatedPromptsStub(); + + const adapter = getMockedAdapter({ + relatedPrompts: { relatedPrompts: mockedRelatedPrompts } + }); + + const store: SafeStore< + RelatedPromptsState, + RelatedPromptsGetters, + RelatedPromptsMutations, + RelatedPromptsActions + > = new Store(relatedPromptsXStoreModule as any); + mount( + {}, + { + global: { + plugins: [installNewXPlugin({ adapter, store })] + } + } + ); + + beforeEach(() => { + resetRelatedPromptsStateWith(store); + }); + + describe('fetchRelatedPrompts', () => { + it('should return related prompts', async () => { + resetRelatedPromptsStateWith(store, { + query: 'honeyboo' + }); + + const relatedPrompts = await store.dispatch('fetchRelatedPrompts', store.getters.request); + expect(relatedPrompts).toEqual(mockedRelatedPrompts); + }); + + it('should return `null` if there is not request', async () => { + const relatedPrompts = await store.dispatch('fetchRelatedPrompts', store.getters.request); + expect(relatedPrompts).toBeNull(); + }); + }); + + describe('fetchAndSaveRelatedPrompts', () => { + it('should request and store related prompts in the state', async () => { + resetRelatedPromptsStateWith(store, { + query: 'honeyboo' + }); + + const actionPromise = store.dispatch('fetchAndSaveRelatedPrompts', store.getters.request); + expect(store.state.status).toEqual('loading'); + await actionPromise; + expect(store.state.relatedPrompts).toEqual(mockedRelatedPrompts); + expect(store.state.status).toEqual('success'); + }); + + it('should not clear related prompts in the state if the query is empty', async () => { + resetRelatedPromptsStateWith(store, { relatedPrompts: mockedRelatedPrompts }); + + await store.dispatch('fetchAndSaveRelatedPrompts', store.getters.request); + expect(store.state.relatedPrompts).toEqual(mockedRelatedPrompts); + }); + + it('should cancel the previous request if it is not yet resolved', async () => { + resetRelatedPromptsStateWith(store, { query: 'steak' }); + const initialRelatedPrompts = store.state.relatedPrompts; + adapter.relatedPrompts.mockResolvedValueOnce({ + relatedPrompts: mockedRelatedPrompts.slice(0, 1) + }); + + const firstRequest = store.dispatch('fetchAndSaveRelatedPrompts', store.getters.request); + const secondRequest = store.dispatch('fetchAndSaveRelatedPrompts', store.getters.request); + + await firstRequest; + expect(store.state.status).toEqual('loading'); + expect(store.state.relatedPrompts).toBe(initialRelatedPrompts); + await secondRequest; + expect(store.state.status).toEqual('success'); + expect(store.state.relatedPrompts).toEqual(mockedRelatedPrompts); + }); + + it('should set the status to error when it fails', async () => { + resetRelatedPromptsStateWith(store, { query: 'milk' }); + adapter.relatedPrompts.mockRejectedValueOnce('Generic error'); + const relatedPrompts = store.state.relatedPrompts; + await store.dispatch('fetchAndSaveRelatedPrompts', store.getters.request); + + expect(store.state.relatedPrompts).toBe(relatedPrompts); + expect(store.state.status).toEqual('error'); + }); + }); + + describe('cancelFetchAndSaveRelatedPrompts', () => { + it('should cancel the request and do not modify the stored related prompts', async () => { + resetRelatedPromptsStateWith(store, { query: 'honeyboo' }); + const previousRelatedPrompts = store.state.relatedPrompts; + await Promise.all([ + store.dispatch('fetchAndSaveRelatedPrompts', store.getters.request), + store.dispatch('cancelFetchAndSaveRelatedPrompts') + ]); + expect(store.state.relatedPrompts).toEqual(previousRelatedPrompts); + expect(store.state.status).toEqual('success'); + }); + }); +}); diff --git a/packages/x-components/src/x-modules/related-prompts/store/__tests__/getters.spec.ts b/packages/x-components/src/x-modules/related-prompts/store/__tests__/getters.spec.ts new file mode 100644 index 0000000000..304ea29c0c --- /dev/null +++ b/packages/x-components/src/x-modules/related-prompts/store/__tests__/getters.spec.ts @@ -0,0 +1,37 @@ +import { RelatedPromptsRequest } from '@empathyco/x-types'; +import { map } from '@empathyco/x-utils'; +import { Store } from 'vuex'; +import { relatedPromptsXStoreModule } from '../module'; +import { RelatedPromptsState } from '../types'; +import { resetRelatedPromptsStateWith } from './utils'; + +describe('testing related prompts module getters', () => { + const gettersKeys = map(relatedPromptsXStoreModule.getters, getter => getter); + const store: Store = new Store(relatedPromptsXStoreModule as any); + + beforeEach(() => { + resetRelatedPromptsStateWith(store); + }); + + describe(`${gettersKeys.request} getter`, () => { + it('should return a request object if there is a query', () => { + resetRelatedPromptsStateWith(store, { + query: 'queso', + params: { + catalog: 'es' + } + }); + + expect(store.getters[gettersKeys.request]).toEqual({ + query: 'queso', + extraParams: { + catalog: 'es' + } + }); + }); + + it('should return null when there is not query', () => { + expect(store.getters[gettersKeys.request]).toBeNull(); + }); + }); +}); diff --git a/packages/x-components/src/x-modules/related-prompts/store/__tests__/utils.ts b/packages/x-components/src/x-modules/related-prompts/store/__tests__/utils.ts new file mode 100644 index 0000000000..cf4e0254f7 --- /dev/null +++ b/packages/x-components/src/x-modules/related-prompts/store/__tests__/utils.ts @@ -0,0 +1,21 @@ +import { DeepPartial } from '@empathyco/x-utils'; +import { Store } from 'vuex'; +import { resetStoreModuleState } from '../../../../__tests__/utils'; +import { relatedPromptsXStoreModule } from '../module'; +import { RelatedPromptsState } from '../types'; + +/** + * Reset related prompt module state with its original state and the partial state passes as + * parameter. + * + * @param store - Related prompt store state. + * @param state - Partial related prompt store state to be replaced. + * + * @internal + */ +export function resetRelatedPromptsStateWith( + store: Store, + state?: DeepPartial +): void { + resetStoreModuleState(store, relatedPromptsXStoreModule.state(), state); +} From 69e99764683b4cc37cbe6fa2cfb2f96a0c87586b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20CG?= Date: Thu, 31 Oct 2024 13:17:13 +0100 Subject: [PATCH 42/43] remove styling classes and add prop to customize next queries button --- packages/x-components/src/views/home/Home.vue | 3 +- .../components/related-prompt.vue | 31 ++++++++----------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/x-components/src/views/home/Home.vue b/packages/x-components/src/views/home/Home.vue index 3d1b0f6d4c..25799fafc5 100644 --- a/packages/x-components/src/views/home/Home.vue +++ b/packages/x-components/src/views/home/Home.vue @@ -390,8 +390,9 @@