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 fa5f94a2ae..bf6435c758 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 @@ -2,6 +2,8 @@ import { mount, Wrapper } from '@vue/test-utils'; import Vue from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import BaseIdModalClose from '../base-id-modal-close.vue'; +import { bus } from '../../../plugins/index'; +import { dummyCreateEmitter } from '../../../__tests__/bus.dummy'; /** * Renders the {@link BaseIdModalClose} with the provided options. @@ -13,6 +15,9 @@ function renderBaseIdModalClose({ id = 'random', template = `` }: RenderBaseIdModalCloseOptions = {}): RenderBaseIdModalCloseAPI { + // Making bus not repeat subjects + jest.spyOn(bus, 'createEmitter' as any).mockImplementation(dummyCreateEmitter.bind(bus) as any); + const [, localVue] = installNewXPlugin(); const containerWrapper = mount( { @@ -32,15 +37,20 @@ function renderBaseIdModalClose({ modalId, async click() { await wrapper.trigger('click'); + jest.runAllTimers(); } }; } describe('testing Close Button component', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + it("emits UserClickedCloseModal with the component's id as payload", async () => { - const { wrapper, modalId, click } = renderBaseIdModalClose(); + const { modalId, click } = renderBaseIdModalClose(); const listener = jest.fn(); - wrapper.vm.$x.on('UserClickedCloseModal').subscribe(listener); + bus.on('UserClickedCloseModal').subscribe(listener); await click(); @@ -69,20 +79,22 @@ describe('testing Close Button component', () => { }); const listener = jest.fn(); - wrapper.vm.$x.on('UserClickedCloseModal').subscribe(listener); + bus.on('UserClickedCloseModal').subscribe(listener); await click(); expect(listener).toHaveBeenCalledTimes(0); wrapper.find(getDataTestSelector('custom-close-modal')).trigger('click'); + jest.runAllTimers(); + expect(listener).toHaveBeenCalledTimes(1); expect(listener).toHaveBeenCalledWith(modalId); }); }); interface RenderBaseIdModalCloseOptions { - /** Id of the modal to close. */ + /** The id of the modal to close. */ id?: string; /** The template to render. */ template?: string; 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 248a3a4c26..e7532f2bef 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 @@ -2,6 +2,8 @@ import { mount, Wrapper } from '@vue/test-utils'; import Vue from 'vue'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; import BaseIdModalOpen from '../base-id-modal-open.vue'; +import { bus } from '../../../plugins/x-bus'; +import { dummyCreateEmitter } from '../../../__tests__/bus.dummy'; /** * Renders the {@link BaseIdModalOpen} with the provided options. @@ -13,6 +15,9 @@ function renderBaseIdModalOpen({ id = 'myModal', template = `` }: RenderBaseIdModalOpenOptions = {}): RenderBaseIdModalOpenAPI { + // Making bus not repeat subjects + jest.spyOn(bus, 'createEmitter' as any).mockImplementation(dummyCreateEmitter.bind(bus) as any); + const [, localVue] = installNewXPlugin(); const containerWrapper = mount( { @@ -21,7 +26,10 @@ function renderBaseIdModalOpen({ }, template }, - { propsData: { modalId: id }, localVue } + { + propsData: { modalId: id }, + localVue + } ); const wrapper = containerWrapper.findComponent(BaseIdModalOpen); @@ -32,15 +40,20 @@ function renderBaseIdModalOpen({ modalId, async click() { await wrapper.trigger('click'); + jest.runAllTimers(); } }; } describe('testing Open Button component', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + it("emits UserClickedOpenModal with the component's id as payload", async () => { - const { wrapper, modalId, click } = renderBaseIdModalOpen(); + const { modalId, click } = renderBaseIdModalOpen(); const listener = jest.fn(); - wrapper.vm.$x.on('UserClickedOpenModal').subscribe(listener); + bus.on('UserClickedOpenModal').subscribe(listener); await click(); @@ -69,20 +82,22 @@ describe('testing Open Button component', () => { }); const listener = jest.fn(); - wrapper.vm.$x.on('UserClickedOpenModal').subscribe(listener); + bus.on('UserClickedOpenModal').subscribe(listener); await click(); expect(listener).toHaveBeenCalledTimes(0); wrapper.find(getDataTestSelector('custom-open-modal')).trigger('click'); + jest.runAllTimers(); + expect(listener).toHaveBeenCalledTimes(1); expect(listener).toHaveBeenCalledWith(modalId); }); }); interface RenderBaseIdModalOpenOptions { - /** Id of the modal to open. */ + /** The id of the modal to open. */ id?: string; /** The template to render. */ template?: string; diff --git a/packages/x-components/src/components/result/__tests__/base-result-rating.spec.ts b/packages/x-components/src/components/result/__tests__/base-result-rating.spec.ts index 03d24d4f06..5a762f02b3 100644 --- a/packages/x-components/src/components/result/__tests__/base-result-rating.spec.ts +++ b/packages/x-components/src/components/result/__tests__/base-result-rating.spec.ts @@ -2,8 +2,8 @@ import { Result } from '@empathyco/x-types'; import { mount, WrapperArray } from '@vue/test-utils'; import { createResultStub } from '../../../__stubs__/results-stubs.factory'; import { getDataTestSelector, installNewXPlugin } from '../../../__tests__/utils'; -import { XComponentBusAPI } from '../../../plugins/x-plugin.types'; import BaseResultRating from '../base-result-rating.vue'; +import { bus } from '../../../plugins/index'; const result = createResultStub('Product Test', { rating: { @@ -37,13 +37,17 @@ function renderBaseResultRating({ getEmptyIcons: (): WrapperArray => wrapper.find(getDataTestSelector('rating-empty')).findAll(':scope > *'), clickRating: async () => { - wrapper.findComponent(BaseResultRating).trigger('click'); - return await wrapper.vm.$nextTick(); - }, - on: wrapper.vm.$x.on + await wrapper.findComponent(BaseResultRating).trigger('click'); + jest.runAllTimers(); + } }; } + describe('testing BaserResultRating component', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + it('renders the default icons a number of times based on the max prop', () => { const { getFilledIcons, getEmptyIcons } = renderBaseResultRating({ template: ``, @@ -76,12 +80,12 @@ describe('testing BaserResultRating component', () => { }); it('emits event when clicked with the result as payload', async () => { - const { on, clickRating } = renderBaseResultRating({ + const { clickRating } = renderBaseResultRating({ template: ``, result }); const eventListener = jest.fn(); - on('UserClickedAResultRating').subscribe(eventListener); + bus.on('UserClickedAResultRating').subscribe(eventListener); await clickRating(); expect(eventListener).toHaveBeenCalledWith(result); @@ -89,14 +93,19 @@ describe('testing BaserResultRating component', () => { }); interface RenderBaseResultRatingOptions { + /** The template to render. */ template: string; + /** The result with the rating to be interacted with. */ result: Result; } interface RenderBaseResultRatingApi { + /** Retrieves the wrapper with the main html content. */ getHtml: () => string; + /** Retrieves the wrapper that matches the rating filled icons. */ getFilledIcons: () => WrapperArray; + /** Retrieves the wrapper that matches the rating empty icons. */ getEmptyIcons: () => WrapperArray; + /** Clicks the rating icons and waits for the view to update. */ clickRating: () => Promise; - on: XComponentBusAPI['on']; } diff --git a/packages/x-components/src/x-modules/next-queries/components/__tests__/next-query.spec.ts b/packages/x-components/src/x-modules/next-queries/components/__tests__/next-query.spec.ts index d3d806d614..04bd6beff8 100644 --- a/packages/x-components/src/x-modules/next-queries/components/__tests__/next-query.spec.ts +++ b/packages/x-components/src/x-modules/next-queries/components/__tests__/next-query.spec.ts @@ -5,45 +5,51 @@ import { getDataTestSelector, installNewXPlugin } from '../../../../__tests__/ut import { getXComponentXModuleName, isXComponent } from '../../../../components/x-component.utils'; import { WireMetadata } from '../../../../wiring/wiring.types'; import { default as NextQueryComponent } from '../next-query.vue'; -import { XComponentAPI } from '../../../../plugins/x-plugin.types'; +import { bus } from '../../../../plugins/index'; +import { dummyCreateEmitter } from '../../../../__tests__/bus.dummy'; -describe('testing next query item component', () => { - function renderNextQuery({ - suggestion = createNextQueryStub('milk'), - template = '' - }: RenderNextQueryOptions = {}): RenderNextQueryAPI { - const [, localVue] = installNewXPlugin(); - const wrapperTemplate = mount( - { - props: ['suggestion', 'highlightCurated'], - components: { - NextQuery: NextQueryComponent - }, - template - }, - { - localVue, - propsData: { suggestion } - } - ); - const wrapper = wrapperTemplate.findComponent(NextQueryComponent); - const $x = wrapperTemplate.vm.$x; - - return { - wrapper, - $x, - suggestion, - async clickNextQuery() { - wrapper.trigger('click'); - await localVue.nextTick(); +function renderNextQuery({ + suggestion = createNextQueryStub('milk'), + template = '' +}: RenderNextQueryOptions = {}): RenderNextQueryAPI { + // Making bus not repeat subjects + jest.spyOn(bus, 'createEmitter' as any).mockImplementation(dummyCreateEmitter.bind(bus) as any); + + const [, localVue] = installNewXPlugin(); + const wrapperTemplate = mount( + { + props: ['suggestion', 'highlightCurated'], + components: { + NextQuery: NextQueryComponent }, - hasIsCuratedClass() { - return wrapper - .find(getDataTestSelector('next-query')) - .element.classList.contains('x-next-query--is-curated'); - } - }; - } + template + }, + { + localVue, + propsData: { suggestion } + } + ); + const wrapper = wrapperTemplate.findComponent(NextQueryComponent); + + return { + wrapper, + suggestion, + async clickNextQuery() { + wrapper.trigger('click'); + await localVue.nextTick(); + }, + hasIsCuratedClass() { + return wrapper + .find(getDataTestSelector('next-query')) + .element.classList.contains('x-next-query--is-curated'); + } + }; +} + +describe('testing next query item component', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); it('is an XComponent and has an XModule', () => { const { wrapper } = renderNextQuery(); @@ -52,10 +58,12 @@ describe('testing next query item component', () => { }); it('emits UserSelectedANextQuery when a next query is selected', async () => { + const { clickNextQuery, suggestion, wrapper } = renderNextQuery(); const listener = jest.fn(); - const { $x, clickNextQuery, suggestion, wrapper } = renderNextQuery(); - $x.on('UserSelectedANextQuery', true).subscribe(listener); + bus.on('UserSelectedANextQuery', true).subscribe(listener); + await clickNextQuery(); + jest.runAllTimers(); expect(listener).toHaveBeenCalled(); expect(listener).toHaveBeenCalledWith({ @@ -111,8 +119,10 @@ describe('testing next query item component', () => { interface RenderNextQueryOptions { /** The next query data to render. */ suggestion?: NextQuery; - /** The template to render. Receives the `nextQuery` via prop, and has registered the - * {@link NextQueryComponent} as `NextQuery`. */ + /** + * The template to render. Receives the `nextQuery` via prop, and has registered the + * {@link NextQueryComponent} as `NextQuery`. + */ template?: string; } @@ -120,8 +130,6 @@ interface RenderNextQueryAPI { /** The Vue testing utils wrapper for the {@link NextQueryComponent}. */ wrapper: Wrapper; /** The {@link XComponentAPI} used by the rendered {@link NextQueryComponent}. */ - $x: XComponentAPI; - /** The rendered next query data. */ suggestion: NextQuery; /** Clicks the next query and waits for the view to update. */ clickNextQuery: () => Promise; diff --git a/packages/x-components/src/x-modules/popular-searches/components/__tests__/popular-search.spec.ts b/packages/x-components/src/x-modules/popular-searches/components/__tests__/popular-search.spec.ts index 1f8efb77ea..4891fe5484 100644 --- a/packages/x-components/src/x-modules/popular-searches/components/__tests__/popular-search.spec.ts +++ b/packages/x-components/src/x-modules/popular-searches/components/__tests__/popular-search.spec.ts @@ -5,11 +5,11 @@ import Vuex, { Store } from 'vuex'; import { createPopularSearch } from '../../../../__stubs__/popular-searches-stubs.factory'; import { installNewXPlugin } from '../../../../__tests__/utils'; import { getXComponentXModuleName, isXComponent } from '../../../../components/x-component.utils'; -import { XPlugin } from '../../../../plugins/x-plugin'; import { RootXStoreState } from '../../../../store/store.types'; import { WireMetadata } from '../../../../wiring/wiring.types'; import { popularSearchesXModule } from '../../x-module'; import PopularSearch from '../popular-search.vue'; +import { bus } from '../../../../plugins/index'; function renderPopularSearch({ suggestion = createPopularSearch('baileys'), @@ -38,11 +38,15 @@ function renderPopularSearch({ return { wrapper: wrapper.findComponent(PopularSearch), suggestion, - emitSpy: jest.spyOn(XPlugin.bus, 'emit') + emitSpy: jest.spyOn(bus, 'emit') }; } describe('testing popular-search component', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + it('is an XComponent that belongs to the popular searches', () => { const { wrapper } = renderPopularSearch(); expect(isXComponent(wrapper.vm)).toEqual(true); diff --git a/packages/x-components/src/x-modules/query-suggestions/components/__tests__/query-suggestion.spec.ts b/packages/x-components/src/x-modules/query-suggestions/components/__tests__/query-suggestion.spec.ts index 9c72ef59f3..f80b72d387 100644 --- a/packages/x-components/src/x-modules/query-suggestions/components/__tests__/query-suggestion.spec.ts +++ b/packages/x-components/src/x-modules/query-suggestions/components/__tests__/query-suggestion.spec.ts @@ -5,11 +5,11 @@ import Vuex, { Store } from 'vuex'; import { createQuerySuggestion } from '../../../../__stubs__/query-suggestions-stubs.factory'; import { getDataTestSelector, installNewXPlugin } from '../../../../__tests__/utils'; import { getXComponentXModuleName, isXComponent } from '../../../../components/x-component.utils'; -import { XPlugin } from '../../../../plugins/x-plugin'; import { RootXStoreState } from '../../../../store/store.types'; import { WireMetadata } from '../../../../wiring/wiring.types'; import { querySuggestionsXModule } from '../../x-module'; import QuerySuggestion from '../query-suggestion.vue'; +import { bus } from '../../../../plugins/index'; import { resetXQuerySuggestionsStateWith } from './utils'; function renderQuerySuggestion({ @@ -41,7 +41,7 @@ function renderQuerySuggestion({ return { wrapper: wrapper.findComponent(QuerySuggestion), suggestion, - emitSpy: jest.spyOn(XPlugin.bus, 'emit'), + emitSpy: jest.spyOn(bus, 'emit'), getMatchingPart() { return wrapper.get(getDataTestSelector('matching-part')); } @@ -49,6 +49,10 @@ function renderQuerySuggestion({ } describe('testing query-suggestion component', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + it('is an XComponent that belongs to the query suggestions', () => { const { wrapper } = renderQuerySuggestion(); expect(isXComponent(wrapper.vm)).toEqual(true); diff --git a/packages/x-components/src/x-modules/semantic-queries/components/__tests__/semantic-query.spec.ts b/packages/x-components/src/x-modules/semantic-queries/components/__tests__/semantic-query.spec.ts index 2b44f219a3..a654e78ae3 100644 --- a/packages/x-components/src/x-modules/semantic-queries/components/__tests__/semantic-query.spec.ts +++ b/packages/x-components/src/x-modules/semantic-queries/components/__tests__/semantic-query.spec.ts @@ -7,12 +7,16 @@ import SemanticQuery from '../semantic-query.vue'; import { getXComponentXModuleName, isXComponent } from '../../../../components/index'; import { createSemanticQuery } from '../../../../__stubs__/index'; import { getDataTestSelector, installNewXPlugin } from '../../../../__tests__/utils'; -import { XPlugin } from '../../../../plugins/index'; +import { bus } from '../../../../plugins/index'; import { RootXStoreState } from '../../../../store/store.types'; import { semanticQueriesXModule } from '../../x-module'; import { resetSemanticQueriesStateWith } from './utils'; describe('semantic queries component', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + function renderSemanticQuery({ template = '', suggestion = createSemanticQuery({ query: 'jeans' }), @@ -44,7 +48,7 @@ describe('semantic queries component', () => { return { wrapper: wrapper.findComponent(SemanticQuery), - emitSpy: jest.spyOn(XPlugin.bus, 'emit'), + emitSpy: jest.spyOn(bus, 'emit'), suggestion }; }