Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(components): fix tests after Vue3 update #1586

Merged
merged 12 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions packages/x-components/src/__tests__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,29 +181,26 @@ function mergeStates<State extends Dictionary>(
}

/**
* Makes a clean installation of the {@link XPlugin} into the passed Vue object.
* This also resets the bus, and all the hardcoded dependencies of the XPlugin.
* Creates a new instance of the {@link XPlugin}. This also resets the bus.
*
* @param options - The options for installing the {@link XPlugin}. The
* {@link XComponentsAdapterDummy} is added by default.
* @param localVue - A clone of the Vue constructor to isolate tests.
* @param bus - The event bus to use.
* If not provided, one will be created.
* @returns An array containing the `xPlugin` singleton and the `localVue` and objects.
* @returns An array containing the `xPlugin` singleton and an object with
* the plugin install options.
*/
export function installNewXPlugin(
options: Partial<XPluginOptions> = {},
localVue = undefined,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to remove the localVue parameter from the jsdoc

bus = new XDummyBus()
): [XPlugin, undefined] {
): [XPlugin, XPluginOptions] {
XPlugin.resetInstance();
const xPlugin = new XPlugin(bus);
// const installOptions: XPluginOptions = {
// adapter: XComponentsAdapterDummy,
// ...options
// };
// localVue.use(xPlugin, installOptions);
return [xPlugin, localVue];
const installOptions: XPluginOptions = {
adapter: XComponentsAdapterDummy,
...options
};
return [xPlugin, installOptions];
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function renderDropdown({
data: () => ({ value: initialValue })
},
{
propsData: { items }
props: { items }
}
);

Expand All @@ -42,7 +42,7 @@ function renderDropdown({
}

const clickToggleButton = () => getDropdownToggle().trigger('click');
const clickNthItem = (nth: number) => getListItems().at(nth).trigger('click');
const clickNthItem = (nth: number) => getListItems().at(nth)?.trigger('click');
const pressKeyFromToggle = (key: Key) => getDropdownToggle().trigger(`keydown`, { key });
const pressKeyFromFocusedItem = (key: Key) => getHighlightedItem().trigger(`keydown`, { key });

Expand Down Expand Up @@ -71,7 +71,7 @@ function renderDropdown({
}

function isListVisible() {
const element = dropdown.find(getDataTestSelector('dropdown-list')).element;
const element = dropdown.find(getDataTestSelector('dropdown-list')).element as HTMLElement;
return element.style.display !== 'none';
}

Expand Down Expand Up @@ -116,7 +116,7 @@ describe('testing Dropdown component', () => {
const listItemWrappers = getListItems();
expect(listItemWrappers).toHaveLength(4);
items.forEach((item, index) => {
expect(listItemWrappers.at(index).text()).toBe(typeof item === 'string' ? item : item.id);
expect(listItemWrappers.at(index)?.text()).toBe(typeof item === 'string' ? item : item.id);
});
});

Expand All @@ -143,8 +143,8 @@ describe('testing Dropdown component', () => {
const listItemWrappers = getListItems();
expect(getDropdownToggle().text()).toBe('select something');
expect(listItemWrappers.length).toBeGreaterThan(0);
expect(getHighlightedItem().text()).toBe(listItemWrappers.at(0).text());
expect(getSelectedItem().element).toBeUndefined();
expect(getHighlightedItem().text()).toBe(listItemWrappers.at(0)?.text());
expect(getSelectedItem().exists()).toBeFalsy();
});

it('allows to customize the toggle button', async () => {
Expand Down Expand Up @@ -177,7 +177,7 @@ describe('testing Dropdown component', () => {
await pressKeyFromToggle('ArrowDown');

const selectedElement = getListItems().at(selectedIndex);
expect(getHighlightedItem().text()).toBe(selectedElement.text());
expect(getHighlightedItem().text()).toBe(selectedElement?.text());
});

it('opens and focuses the selected element when the button has focus and arrow UP key is pressed', async () => {
Expand All @@ -189,7 +189,7 @@ describe('testing Dropdown component', () => {
await pressKeyFromToggle('ArrowUp');

const selectedElement = getListItems().at(selectedIndex);
expect(getHighlightedItem().text()).toBe(selectedElement.text());
expect(getHighlightedItem().text()).toBe(selectedElement?.text());
});
});

Expand Down Expand Up @@ -291,10 +291,10 @@ describe('testing Dropdown component', () => {
const listItems = getListItems();

await pressKeyFromFocusedItem('End');
expect(getHighlightedItem().text()).toBe(listItems.at(-1).text());
expect(getHighlightedItem().text()).toBe(listItems.at(-1)?.text());

await pressKeyFromFocusedItem('Home');
expect(getHighlightedItem().text()).toBe(listItems.at(0).text());
expect(getHighlightedItem().text()).toBe(listItems.at(0)?.text());
});

it('focuses the first element starting to search from the focused one which its text starts with the typed characters', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
import { mount } from '@vue/test-utils';
import { ComponentMountingOptions, mount } from '@vue/test-utils';
import { installNewXPlugin } from '../../__tests__/utils';
import { XPlugin } from '../../plugins';
import { WireMetadata } from '../../wiring/wiring.types';
import BaseEventButton from '../base-event-button.vue';
import { XEventsTypes } from 'src/wiring';

function render() {
installNewXPlugin();
const stubSlot = `<span class="test-msg">button text</span>
<i class="test-icon"></i>`;

const wrapper = mount(
{
template: `<BaseEventButton :events="events">
<span class="test-msg">button text</span>
<i class="test-icon"></i>
</BaseEventButton>`,
components: { BaseEventButton },
props: ['events']
},
{
propsData: { events: {} }
}
);
function render(options: ComponentMountingOptions<typeof BaseEventButton> = {}) {
const wrapper = mount(BaseEventButton, {
props: { events: {} },
slots: { default: stubSlot },
global: { plugins: [installNewXPlugin()] },
...options
});

return {
wrapper,
Expand All @@ -44,7 +39,7 @@ describe('testing Base Event Button Component', () => {
it('emits an event with a payload', async () => {
const { wrapper, emitSpy, expectedMetadata } = render();

await wrapper.setProps({ events: { testEvent: 'test-payload' } });
await wrapper.setProps({ events: { testEvent: 'test-payload' } as Partial<XEventsTypes> });
await wrapper.trigger('click');

expect(emitSpy).toHaveBeenCalledTimes(1);
Expand All @@ -54,7 +49,7 @@ describe('testing Base Event Button Component', () => {
it('emits an event with no payload', async () => {
const { wrapper, emitSpy, expectedMetadata } = render();

await wrapper.setProps({ events: { testEvent: undefined } });
await wrapper.setProps({ events: { testEvent: undefined } as Partial<XEventsTypes> });
await wrapper.trigger('click');

expect(emitSpy).toHaveBeenCalledTimes(1);
Expand All @@ -68,7 +63,7 @@ describe('testing Base Event Button Component', () => {
testEvent1: 'test-payload-1',
testEvent2: 'test-payload-2',
testEvent3: undefined
};
} as Partial<XEventsTypes>;
await wrapper.setProps({ events });
await wrapper.trigger('click');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import { SearchInput } from '../../x-modules/search-box/components/index';
import { installNewXPlugin } from '../../__tests__/utils';
import BaseKeyboardNavigation from '../base-keyboard-navigation.vue';
import { DirectionalFocusNavigationService } from '../../services/directional-focus-navigation.service';
import { XPlugin } from '../../plugins/x-plugin';

describe('testing keyboard navigation component', () => {
let localVue: typeof Vue;

beforeEach(() => {
[, localVue] = installNewXPlugin();
});

it('takes control of the navigation when a defined condition is triggered', () => {
const navigateToSpy = jest.spyOn(
DirectionalFocusNavigationService.prototype as any,
'navigateTo'
);
const searchInput = mount(SearchInput, { localVue });
mount(BaseKeyboardNavigation, {
localVue,
propsData: {
global: { plugins: [installNewXPlugin()] },
props: {
navigationHijacker: [
{
xEvent: 'UserPressedArrowKey',
Expand All @@ -30,6 +23,8 @@ describe('testing keyboard navigation component', () => {
]
}
});

const searchInput = mount(SearchInput);
searchInput.trigger('keydown', { key: 'ArrowUp' });
expect(navigateToSpy).not.toHaveBeenCalled();

Expand All @@ -44,15 +39,14 @@ describe('testing keyboard navigation component', () => {
.spyOn(DirectionalFocusNavigationService.prototype as any, 'navigateTo')
.mockReturnValue(undefined);
const keyboardNavigation = mount(BaseKeyboardNavigation, {
localVue,
propsData: {
takeNavigationControl: [],
global: { plugins: [installNewXPlugin()] },
props: {
eventsForDirectionLimit: {
ArrowUp: 'UserReachedEmpathizeTop'
}
}
});
keyboardNavigation.vm.$x.on('UserReachedEmpathizeTop').subscribe(listener);
XPlugin.bus.on('UserReachedEmpathizeTop').subscribe(listener);
keyboardNavigation.trigger('keydown', { key: 'ArrowUp' });

expect(listener).toHaveBeenCalled();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { mount, WrapperArray } from '@vue/test-utils';
import { mount, DOMWrapper } from '@vue/test-utils';
import { getDataTestSelector } from '../../__tests__/utils';
import BaseRating from '../base-rating.vue';

function renderBaseRating({ template }: RenderBaseRatingOptions): RenderBaseRatingApi {
const wrapper = mount({ template }, { components: { BaseRating } });

return {
getFilledIcons: (): WrapperArray<Vue> =>
getFilledIcons: (): DOMWrapper<Element>[] =>
wrapper.find(getDataTestSelector('rating-filled')).findAll(':scope > *'),
getEmptyIcons: (): WrapperArray<Vue> =>
getEmptyIcons: (): DOMWrapper<Element>[] =>
wrapper.find(getDataTestSelector('rating-empty')).findAll(':scope > *')
};
}
Expand Down Expand Up @@ -39,6 +39,6 @@ interface RenderBaseRatingOptions {
}

interface RenderBaseRatingApi {
getFilledIcons: () => WrapperArray<Vue>;
getEmptyIcons: () => WrapperArray<Vue>;
getFilledIcons: () => DOMWrapper<Element>[];
getEmptyIcons: () => DOMWrapper<Element>[];
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { mount, Wrapper } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { getSearchResponseStub } from '../../__stubs__/search-response-stubs.factory';
import { getDataTestSelector, installNewXPlugin } from '../../__tests__/utils';
import { ListItem } from '../../utils/types';
import BaseVariableColumnGrid from '../base-variable-column-grid.vue';
import { XPlugin } from '../../plugins/x-plugin';
import { XDummyBus } from '../../__tests__/bus.dummy';

const searchResponse = getSearchResponseStub();
const itemsStub = [
Expand All @@ -13,16 +13,16 @@ const itemsStub = [
...searchResponse.results
];

function renderComponent({ items = itemsStub }: RenderOptions = {}): RenderAPI {
const [, localVue] = installNewXPlugin();
function mountComponent(): Wrapper<Vue> {
const sharedBus = new XDummyBus();

function renderComponent({ items = itemsStub } = {}) {
function mountComponent() {
return mount(BaseVariableColumnGrid, {
props: ['items'],
propsData: {
global: { plugins: [installNewXPlugin({}, sharedBus)] },
props: {
items
},
localVue,
scopedSlots: {
slots: {
default: '<span data-test="default-slot" slot-scope="{ item }">{{ item.id }}</span>',
result: '<span data-test="result-slot" slot-scope="{ item }">{{ item.name }}</span>'
}
Expand All @@ -34,12 +34,9 @@ function renderComponent({ items = itemsStub }: RenderOptions = {}): RenderAPI {
return {
wrapper: wrapper,
mountComponent,
hasColumns(columns: number): boolean {
return wrapper.classes(`x-base-grid--cols-${columns}`);
},
isScopedSlotOverridden(selector): boolean {
return wrapper.find(getDataTestSelector(selector)).exists();
}
hasColumns: (columns: number) => wrapper.classes(`x-base-grid--cols-${columns}`),
isScopedSlotOverridden: (selector: string) =>
wrapper.find(getDataTestSelector(selector)).exists()
};
}

Expand Down Expand Up @@ -70,22 +67,9 @@ describe('testing BaseVariableColumnGrid component', () => {
expect(hasColumns(6)).toBe(true);

const wrapper2 = mountComponent();

await nextTick();

expect(wrapper2.classes('x-base-grid--cols-6')).toBe(true);
});
});

interface RenderOptions {
/** The array of items to render in the grid. */
items?: ListItem[];
}

interface RenderAPI {
/** The grid's wrapper. */
wrapper: Wrapper<Vue>;
/** Mounts the grid component. */
mountComponent: () => Wrapper<Vue>;
/** Checks if the grid has a certain number of columns. */
hasColumns: (columns: number) => boolean;
/** Check if a scoped slot is overridden. */
isScopedSlotOverridden: (selector: string) => boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ function render({
});

return {
wrapper: wrapper.findComponent(DisplayEmitter),
wrapper,
displayEmiter: wrapper.findComponent(DisplayEmitter),
element: wrapper.find(getDataTestSelector('child')).element,
payload,
eventMetadata
Expand All @@ -38,9 +39,9 @@ describe('testing DisplayEmitter component', () => {
});

it('renders everything passed to its default slot', () => {
const { wrapper } = render();
const { displayEmiter } = render();

expect(wrapper.find(getDataTestSelector('child')).exists()).toBeTruthy();
expect(displayEmiter.find(getDataTestSelector('child')).exists()).toBeTruthy();
});

it('executes `useEmitDisplayEvent` composable underneath', () => {
Expand Down Expand Up @@ -70,7 +71,7 @@ describe('testing DisplayEmitter component', () => {
it('removes the watcher on unmount', async () => {
const { wrapper } = render();

wrapper.destroy();
wrapper.unmount();
await nextTick();

expect(unwatchDisplaySpy).toHaveBeenCalled();
Expand Down
Loading
Loading