Skip to content

Commit

Permalink
feat: modify use-$x composable (#1434)
Browse files Browse the repository at this point in the history
  • Loading branch information
annacv authored Apr 4, 2024
1 parent ea2ecb9 commit cd9a0d1
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -1,41 +1,46 @@
import { mount, Wrapper } from '@vue/test-utils';
import Vue, { ComponentOptions, nextTick } from 'vue';
import Vue, { ComponentOptions } from 'vue';
import { Result } from '@empathyco/x-types';
import { getDataTestSelector } from '../../__tests__/utils';
import { getDataTestSelector, installNewXPlugin } from '../../__tests__/utils';
import PageLoaderButton from '../page-loader-button.vue';
import { getResultsStub } from '../../__stubs__/index';
import { bus } from '../../plugins/index';

function renderPageLoaderButton({
query = 'dress',
results = getResultsStub(48),
totalResults = 100,
scopedSlots
}: RenderPageLoaderButtonOptions = {}): RenderPageLoaderButtonAPI {
const emit = jest.fn();
const [, localVue] = installNewXPlugin();

const wrapper = mount(PageLoaderButton as ComponentOptions<Vue>, {
propsData: {
buttonClasses: '',
buttonEvents: {}
},
mocks: {
$x: {
emit,
localVue,
scopedSlots,
data() {
return {
query,
results,
totalResults
}
},
scopedSlots
};
}
});

return {
emit,
wrapper
wrapper,
emitSpy: jest.spyOn(bus, 'emit')
};
}

describe('testing PageLoaderButton component', () => {
beforeAll(() => {
jest.useFakeTimers();
});

beforeEach(() => {
jest.clearAllMocks();
});
Expand Down Expand Up @@ -73,35 +78,47 @@ describe('testing PageLoaderButton component', () => {
expect(wrapper.find('.x-rounded-full').exists()).toBe(true);
});

it('emits the event UserReachedResultsListEnd when the button is clicked', async () => {
const { wrapper, emit } = renderPageLoaderButton();
// TODO: Enable test when BaseEventButton component is migrated
// eslint-disable-next-line jest/no-disabled-tests
it.skip('emits the event UserReachedResultsListEnd when the button is clicked', () => {
const { wrapper, emitSpy } = renderPageLoaderButton();
const baseEventButton = wrapper.find(getDataTestSelector('load-content'));

baseEventButton.trigger('click');
await nextTick();

expect(emit).toHaveBeenCalledTimes(1);
expect(emit).toHaveBeenCalledWith('UserReachedResultsListEnd', undefined, {
target: baseEventButton.element
expect(emitSpy).toHaveBeenCalledTimes(1);
expect(emitSpy).toHaveBeenCalledWith('UserReachedResultsListEnd', undefined, {
target: baseEventButton.element,
location: 'none',
moduleName: null,
replaceable: true
});
});

it('emits an event passed via prop', async () => {
const { wrapper, emit } = renderPageLoaderButton();
// TODO: Enable test when BaseEventButton component is migrated
// eslint-disable-next-line jest/no-disabled-tests
it.skip('emits an event passed via prop', async () => {
const { wrapper, emitSpy } = renderPageLoaderButton();
const baseEventButton = wrapper.find(getDataTestSelector('load-content'));

wrapper.setProps({ buttonEvents: { UserClickedCloseX: undefined } });
await wrapper.vm.$nextTick();

baseEventButton.trigger('click');
await nextTick();

expect(emit).toHaveBeenCalledTimes(2);
expect(emit).toHaveBeenCalledWith('UserReachedResultsListEnd', undefined, {
target: baseEventButton.element
jest.runAllTimers();

expect(emitSpy).toHaveBeenCalledTimes(2);
expect(emitSpy).toHaveBeenCalledWith('UserReachedResultsListEnd', undefined, {
target: baseEventButton.element,
location: 'none',
moduleName: null,
replaceable: true
});
expect(emit).toHaveBeenCalledWith('UserClickedCloseX', undefined, {
target: baseEventButton.element
expect(emitSpy).toHaveBeenCalledWith('UserClickedCloseX', undefined, {
target: baseEventButton.element,
location: 'none',
moduleName: null,
replaceable: true
});
});
});
Expand All @@ -124,8 +141,8 @@ interface RenderPageLoaderButtonOptions {
* Options to configure how the page loader button component should be rendered.
*/
interface RenderPageLoaderButtonAPI {
/** Mock of the {@link XBus.emit} function. */
emit: jest.Mock;
/** The wrapper for the page loader button component. */
wrapper: Wrapper<Vue>;
/* A jest spy of the X emit method. */
emitSpy: ReturnType<typeof jest.spyOn>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -13,6 +15,9 @@ function renderBaseIdModalClose({
id = 'random',
template = `<BaseIdModalClose modalId="${id}" v-bind="$attrs"/>`
}: 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(
{
Expand All @@ -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();

Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -13,6 +15,9 @@ function renderBaseIdModalOpen({
id = 'myModal',
template = `<BaseIdModalOpen modalId="${id}" v-bind="$attrs"/>`
}: 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(
{
Expand All @@ -21,7 +26,10 @@ function renderBaseIdModalOpen({
},
template
},
{ propsData: { modalId: id }, localVue }
{
propsData: { modalId: id },
localVue
}
);

const wrapper = containerWrapper.findComponent(BaseIdModalOpen);
Expand All @@ -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();

Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { XEvent, XEventsTypes } from '../../../wiring/events.types';
import BaseResultLink from '../base-result-link.vue';
import { WireMetadata } from '../../../wiring/index';
import { PropsWithType } from '../../../utils/index';
import { bus } from '../../../plugins/index';
import { dummyCreateEmitter } from '../../../__tests__/bus.dummy';

describe('testing BaseResultLink component', () => {
const result = createResultStub('Product 001', {
Expand All @@ -16,6 +18,12 @@ describe('testing BaseResultLink component', () => {
let localVue: typeof Vue;
let resultLinkWrapper: Wrapper<Vue>;
const template = '<BaseResultLink :result="result"/>';
// Making bus not repeat subjects
jest.spyOn(bus, 'createEmitter' as any).mockImplementation(dummyCreateEmitter.bind(bus) as any);

beforeAll(() => {
jest.useFakeTimers();
});

beforeEach(() => {
[, localVue] = installNewXPlugin();
Expand All @@ -33,24 +41,26 @@ describe('testing BaseResultLink component', () => {
});

// eslint-disable-next-line max-len
it('emits UserClickedAResult when the user clicks in the left, middle or right button on the component', () => {
it('emits UserClickedAResult when the user clicks in the left, middle or right button on the component', async () => {
const listener = jest.fn();
resultLinkWrapper.vm.$x.on('UserClickedAResult').subscribe(listener);
bus.on('UserClickedAResult').subscribe(listener);

resultLinkWrapper.trigger('click');
await resultLinkWrapper.trigger('click');
jest.runAllTimers();
expect(listener).toHaveBeenNthCalledWith(1, result);

resultLinkWrapper.trigger('click', { button: 1 });
await resultLinkWrapper.trigger('click', { button: 1 });
jest.runAllTimers();
expect(listener).toHaveBeenNthCalledWith(2, result);

resultLinkWrapper.trigger('click', { button: 2 });
await resultLinkWrapper.trigger('click', { button: 2 });
jest.runAllTimers();
expect(listener).toHaveBeenNthCalledWith(3, result);

expect(listener).toHaveBeenCalledTimes(3);
});

it('emits events provided from parent element with provided location in metadata', () => {
const listener = jest.fn();
it('emits events provided from parent element with provided location in metadata', async () => {
const resultLinkWrapper = mount(
{
components: { BaseResultLink },
Expand All @@ -66,8 +76,13 @@ describe('testing BaseResultLink component', () => {
propsData: { result }
}
);
resultLinkWrapper.vm.$x.on('UserClickedResultAddToCart', true).subscribe(listener);
resultLinkWrapper.trigger('click');

const listener = jest.fn();
bus.on('UserClickedResultAddToCart', true).subscribe(listener);

await resultLinkWrapper.trigger('click');
jest.runAllTimers();

expect(listener).toHaveBeenCalledWith({
eventPayload: result,
metadata: expect.objectContaining({
Expand All @@ -76,7 +91,7 @@ describe('testing BaseResultLink component', () => {
});
});

it('emits events with the extra metadata provided from parent element', () => {
it('emits events with the extra metadata provided from parent element', async () => {
const injectedResultLinkMetadataPerEvent: Partial<
Record<
PropsWithType<XEventsTypes, Result>,
Expand All @@ -90,8 +105,6 @@ describe('testing BaseResultLink component', () => {
replaceable: false
}
};
const resultClickListener = jest.fn();
const addToCartClickListener = jest.fn();

const resultLinkWrapper = mount(
{
Expand All @@ -108,11 +121,15 @@ describe('testing BaseResultLink component', () => {
propsData: { result }
}
);
resultLinkWrapper.vm.$x.on('UserClickedAResult', true).subscribe(resultClickListener);
resultLinkWrapper.vm.$x
.on('UserClickedResultAddToCart', true)
.subscribe(addToCartClickListener);
resultLinkWrapper.trigger('click');

const resultClickListener = jest.fn();
bus.on('UserClickedAResult', true).subscribe(resultClickListener);

const addToCartClickListener = jest.fn();
bus.on('UserClickedResultAddToCart', true).subscribe(addToCartClickListener);

await resultLinkWrapper.trigger('click');
jest.runAllTimers();

expect(resultClickListener).toHaveBeenCalledTimes(1);
expect(resultClickListener).toHaveBeenCalledWith({
Expand Down
Loading

0 comments on commit cd9a0d1

Please sign in to comment.