Commit 5857f7b7 authored by Phil Hughes's avatar Phil Hughes

Merge branch 'tor/defect/missing-popovers-from-async-DOM' into 'master'

Attach user popovers to DOM nodes added after the initial DOM query

See merge request gitlab-org/gitlab!54411
parents c0201419 7dcf2744
......@@ -59,11 +59,33 @@ const populateUserInfo = (user) => {
};
const initializedPopovers = new Map();
let domObservedForChanges = false;
export default (elements = document.querySelectorAll('.js-user-link')) => {
const addPopoversToModifiedTree = new MutationObserver(() => {
const userLinks = document?.querySelectorAll('.js-user-link, .gfm-project_member');
if (userLinks) {
addPopovers(userLinks); /* eslint-disable-line no-use-before-define */
}
});
function observeBody() {
if (!domObservedForChanges) {
addPopoversToModifiedTree.observe(document.body, {
subtree: true,
childList: true,
});
domObservedForChanges = true;
}
}
export default function addPopovers(elements = document.querySelectorAll('.js-user-link')) {
const userLinks = Array.from(elements);
const UserPopoverComponent = Vue.extend(UserPopover);
observeBody();
return userLinks
.filter(({ dataset }) => dataset.user || dataset.userId)
.map((el) => {
......@@ -105,4 +127,4 @@ export default (elements = document.querySelectorAll('.js-user-link')) => {
return renderedPopover;
});
};
}
---
title: React to new DOM nodes being added to the page to bind the user information
popover to them
merge_request: 54411
author:
type: fixed
......@@ -6,6 +6,19 @@ describe('User Popovers', () => {
preloadFixtures(fixtureTemplate);
const selector = '.js-user-link, .gfm-project_member';
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');
link.setAttribute('data-user', '1');
return link;
};
const dummyUser = { name: 'root' };
const dummyUserStatus = { message: 'active' };
......@@ -37,13 +50,20 @@ describe('User Popovers', () => {
});
it('initializes a popover for each user link with a user id', () => {
const linksWithUsers = Array.from(document.querySelectorAll(selector)).filter(
({ dataset }) => dataset.user || dataset.userId,
);
const linksWithUsers = findFixtureLinks();
expect(linksWithUsers.length).toBe(popovers.length);
});
it('adds popovers to user links added to the DOM tree after the initial call', async () => {
document.body.appendChild(createUserLink());
document.body.appendChild(createUserLink());
const linksWithUsers = findFixtureLinks();
expect(linksWithUsers.length).toBe(popovers.length + 2);
});
it('does not initialize the user popovers twice for the same element', () => {
const newPopovers = initUserPopovers(document.querySelectorAll(selector));
const samePopovers = popovers.every((popover, index) => newPopovers[index] === popover);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment