debian-mirror-gitlab/spec/frontend/user_popovers_spec.js

189 lines
5.6 KiB
JavaScript
Raw Normal View History

2022-07-16 23:28:13 +05:30
import { within } from '@testing-library/dom';
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
2019-02-15 15:39:39 +05:30
import UsersCache from '~/lib/utils/users_cache';
2021-03-11 19:13:27 +05:30
import initUserPopovers from '~/user_popovers';
2022-07-16 23:28:13 +05:30
import waitForPromises from 'helpers/wait_for_promises';
jest.mock('~/api/user_api', () => ({
followUser: jest.fn().mockResolvedValue({}),
unfollowUser: jest.fn().mockResolvedValue({}),
}));
2019-02-15 15:39:39 +05:30
describe('User Popovers', () => {
2020-03-13 15:44:24 +05:30
const fixtureTemplate = 'merge_requests/merge_request_with_mentions.html';
2019-02-15 15:39:39 +05:30
2020-03-13 15:44:24 +05:30
const selector = '.js-user-link, .gfm-project_member';
2021-04-17 20:07:23 +05:30
const findFixtureLinks = () => {
return Array.from(document.querySelectorAll(selector)).filter(
({ dataset }) => dataset.user || dataset.userId,
);
};
const createUserLink = () => {
const link = document.createElement('a');
link.classList.add('js-user-link');
2022-07-23 23:45:48 +05:30
link.dataset.user = '1';
2021-04-17 20:07:23 +05:30
return link;
};
2022-07-23 23:45:48 +05:30
const findPopovers = () => {
return Array.from(document.querySelectorAll('[data-testid="user-popover"]'));
};
2019-02-15 15:39:39 +05:30
2022-07-16 23:28:13 +05:30
const dummyUser = { name: 'root', username: 'root', is_followed: false };
2019-02-15 15:39:39 +05:30
const dummyUserStatus = { message: 'active' };
const triggerEvent = (eventName, el) => {
2020-03-13 15:44:24 +05:30
const event = new MouseEvent(eventName, {
bubbles: true,
cancelable: true,
view: window,
});
2019-02-15 15:39:39 +05:30
el.dispatchEvent(event);
};
beforeEach(() => {
2022-07-16 23:28:13 +05:30
loadHTMLFixture(fixtureTemplate);
2019-02-15 15:39:39 +05:30
const usersCacheSpy = () => Promise.resolve(dummyUser);
2021-03-08 18:12:59 +05:30
jest.spyOn(UsersCache, 'retrieveById').mockImplementation((userId) => usersCacheSpy(userId));
2019-02-15 15:39:39 +05:30
const userStatusCacheSpy = () => Promise.resolve(dummyUserStatus);
2020-06-23 00:09:42 +05:30
jest
.spyOn(UsersCache, 'retrieveStatusById')
2021-03-08 18:12:59 +05:30
.mockImplementation((userId) => userStatusCacheSpy(userId));
2022-07-16 23:28:13 +05:30
jest.spyOn(UsersCache, 'updateById');
2019-02-15 15:39:39 +05:30
2022-07-23 23:45:48 +05:30
initUserPopovers((popoverInstance) => {
const mountingRoot = document.createElement('div');
document.body.appendChild(mountingRoot);
popoverInstance.$mount(mountingRoot);
});
2019-02-15 15:39:39 +05:30
});
2022-07-16 23:28:13 +05:30
afterEach(() => {
resetHTMLFixture();
});
2022-07-23 23:45:48 +05:30
describe('shows a placeholder popover on hover', () => {
let linksWithUsers;
beforeEach(() => {
linksWithUsers = findFixtureLinks();
linksWithUsers.forEach((el) => {
triggerEvent('mouseover', el);
});
});
2019-02-15 15:39:39 +05:30
2022-07-23 23:45:48 +05:30
it('for initial links', () => {
expect(findPopovers().length).toBe(linksWithUsers.length);
});
2019-02-15 15:39:39 +05:30
2022-07-23 23:45:48 +05:30
it('for elements added after initial load', async () => {
const addedLinks = [createUserLink(), createUserLink()];
addedLinks.forEach((link) => {
document.body.appendChild(link);
});
2021-04-17 20:07:23 +05:30
2022-07-23 23:45:48 +05:30
jest.runOnlyPendingTimers();
2021-04-17 20:07:23 +05:30
2022-07-23 23:45:48 +05:30
addedLinks.forEach((link) => {
triggerEvent('mouseover', link);
});
expect(findPopovers().length).toBe(linksWithUsers.length + addedLinks.length);
});
2021-04-17 20:07:23 +05:30
});
2022-07-23 23:45:48 +05:30
it('does not initialize the user popovers twice for the same element', async () => {
const [firstUserLink] = findFixtureLinks();
triggerEvent('mouseover', firstUserLink);
jest.runOnlyPendingTimers();
triggerEvent('mouseleave', firstUserLink);
jest.runOnlyPendingTimers();
triggerEvent('mouseover', firstUserLink);
jest.runOnlyPendingTimers();
2019-02-15 15:39:39 +05:30
2022-07-23 23:45:48 +05:30
expect(findPopovers().length).toBe(1);
2020-03-13 15:44:24 +05:30
});
2019-02-15 15:39:39 +05:30
2022-07-23 23:45:48 +05:30
describe('when user link emits mouseenter event with empty user cache', () => {
2020-03-13 15:44:24 +05:30
let userLink;
2019-02-15 15:39:39 +05:30
2020-03-13 15:44:24 +05:30
beforeEach(() => {
2020-06-23 00:09:42 +05:30
UsersCache.retrieveById.mockReset();
2022-07-23 23:45:48 +05:30
[userLink] = findFixtureLinks();
2019-02-15 15:39:39 +05:30
2022-07-23 23:45:48 +05:30
triggerEvent('mouseover', userLink);
2020-03-13 15:44:24 +05:30
});
2019-02-15 15:39:39 +05:30
2022-07-23 23:45:48 +05:30
it('populates popover with preloaded user data', () => {
2020-03-13 15:44:24 +05:30
const { name, userId, username } = userLink.dataset;
2022-07-23 23:45:48 +05:30
expect(userLink.user).toEqual(
2020-06-23 00:09:42 +05:30
expect.objectContaining({
2020-03-13 15:44:24 +05:30
name,
userId,
username,
}),
);
});
2022-07-23 23:45:48 +05:30
});
describe('when user link emits mouseenter event', () => {
let userLink;
beforeEach(() => {
[userLink] = findFixtureLinks();
triggerEvent('mouseover', userLink);
});
it('removes title attribute from user links', () => {
expect(userLink.getAttribute('title')).toBeFalsy();
expect(userLink.dataset.originalTitle).toBeFalsy();
});
2020-03-13 15:44:24 +05:30
it('fetches user info and status from the user cache', () => {
const { userId } = userLink.dataset;
2019-02-15 15:39:39 +05:30
2020-03-13 15:44:24 +05:30
expect(UsersCache.retrieveById).toHaveBeenCalledWith(userId);
expect(UsersCache.retrieveStatusById).toHaveBeenCalledWith(userId);
2019-02-15 15:39:39 +05:30
});
2020-03-13 15:44:24 +05:30
2022-07-23 23:45:48 +05:30
it('removes aria-describedby attribute from the user link on mouseleave', () => {
userLink.setAttribute('aria-describedby', 'popover');
triggerEvent('mouseleave', userLink);
2020-03-13 15:44:24 +05:30
2022-07-23 23:45:48 +05:30
expect(userLink.getAttribute('aria-describedby')).toBe(null);
});
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
it('updates toggle follow button and `UsersCache` when toggle follow button is clicked', async () => {
const [firstPopover] = findPopovers();
const withinFirstPopover = within(firstPopover);
const findFollowButton = () => withinFirstPopover.queryByRole('button', { name: 'Follow' });
const findUnfollowButton = () =>
withinFirstPopover.queryByRole('button', { name: 'Unfollow' });
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
jest.runOnlyPendingTimers();
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
const { userId } = document.querySelector(selector).dataset;
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
triggerEvent('click', findFollowButton());
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
await waitForPromises();
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
expect(findUnfollowButton()).not.toBe(null);
expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: true });
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
triggerEvent('click', findUnfollowButton());
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
await waitForPromises();
2022-07-16 23:28:13 +05:30
2022-07-23 23:45:48 +05:30
expect(findFollowButton()).not.toBe(null);
expect(UsersCache.updateById).toHaveBeenCalledWith(userId, { is_followed: false });
});
2022-07-16 23:28:13 +05:30
});
2019-02-15 15:39:39 +05:30
});