Commit ef3024ea authored by Tim Zallmann's avatar Tim Zallmann

Added Specs for navigation utility prefetching

parent 266d51b6
......@@ -15,16 +15,15 @@ export default function findAndFollowLink(selector) {
}
export function prefetchDocument(url) {
const newPrefetchLink = document.createElement("link");
newPrefetchLink.rel = "prefetch";
const newPrefetchLink = document.createElement('link');
newPrefetchLink.rel = 'prefetch';
newPrefetchLink.href = url;
newPrefetchLink.as = "document";
newPrefetchLink.setAttribute('as', 'document');
document.head.appendChild(newPrefetchLink);
}
export function initPrefetchLinks(selector) {
document.querySelectorAll(selector)
.forEach((el) => {
document.querySelectorAll(selector).forEach((el) => {
let mouseOverTimer;
const mouseOutHandler = () => {
......@@ -33,21 +32,21 @@ export function initPrefetchLinks(selector) {
mouseOverTimer = undefined;
}
};
const mouseOverHandler = () => {
el.addEventListener('mouseout', mouseOutHandler, { passive: true });
mouseOverTimer = setTimeout(() => {
if (el.href) prefetchDocument(el.href);
// Only execute once
el.removeEventListener('mouseover', mouseOverHandler, true);
el.removeEventListener('mouseout', mouseOutHandler);
mouseOverTimer = undefined;
}, 100);
};
el.addEventListener('mouseover', mouseOverHandler, {
capture: true,
passive: true,
......
......@@ -9,7 +9,7 @@
.issuable-main-info
.merge-request-title.title
%span.merge-request-title-text.js-onboarding-mr-item
= link_to merge_request.title, merge_request_path(merge_request)
= link_to merge_request.title, merge_request_path(merge_request), class: 'js-prefetch-document'
- if merge_request.tasks?
%span.task-status.d-none.d-sm-inline-block
 
......
import findAndFollowLink from '~/lib/utils/navigation_utility';
import * as navigationUtils from '~/lib/utils/navigation_utility';
import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility');
......@@ -21,3 +22,92 @@ describe('findAndFollowLink', () => {
expect(visitUrl).not.toHaveBeenCalled();
});
});
describe('prefetchDocument', () => {
it('creates a prefetch link tag', () => {
const linkElement = document.createElement('link');
jest.spyOn(document, 'createElement').mockImplementation(() => linkElement);
jest.spyOn(document.head, 'appendChild');
navigationUtils.prefetchDocument('index.htm');
expect(document.head.appendChild).toHaveBeenCalledWith(linkElement);
expect(linkElement.href).toEqual('http://test.host/index.htm');
expect(linkElement.rel).toEqual('prefetch');
expect(linkElement.getAttribute('as')).toEqual('document');
});
});
describe('initPrefetchLinks', () => {
let newLink;
beforeEach(() => {
newLink = document.createElement('a');
newLink.href = 'index_prefetch.htm';
newLink.classList.add('js-test-prefetch-link');
document.body.appendChild(newLink);
});
it('adds to all links mouse out handlers when hovered', () => {
const mouseOverEvent = new Event('mouseover');
jest.spyOn(newLink, 'addEventListener');
navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
newLink.dispatchEvent(mouseOverEvent);
expect(newLink.addEventListener).toHaveBeenCalled();
});
it('it is not fired when less then 100ms over link', () => {
const mouseOverEvent = new Event('mouseover');
const mouseOutEvent = new Event('mouseout');
jest.spyOn(newLink, 'addEventListener');
jest.spyOn(navigationUtils, 'prefetchDocument').mockImplementation(() => true);
navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
newLink.dispatchEvent(mouseOverEvent);
newLink.dispatchEvent(mouseOutEvent);
expect(navigationUtils.prefetchDocument).not.toHaveBeenCalled();
});
describe('executes correctly when hovering long enough', () => {
const mouseOverEvent = new Event('mouseover');
beforeEach(() => {
jest.useFakeTimers();
jest.spyOn(global, 'setTimeout');
jest.spyOn(newLink, 'removeEventListener');
});
it('calls prefetchDocument which adds to document', () => {
jest.spyOn(document.head, 'appendChild');
navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
newLink.dispatchEvent(mouseOverEvent);
jest.runAllTimers();
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 100);
expect(document.head.appendChild).toHaveBeenCalled();
});
it('removes Event Listener when fired so only done once', () => {
navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
newLink.dispatchEvent(mouseOverEvent);
jest.runAllTimers();
expect(newLink.removeEventListener).toHaveBeenCalledWith(
'mouseover',
expect.any(Function),
true,
);
expect(newLink.removeEventListener).toHaveBeenCalledWith('mouseout', expect.any(Function));
});
});
});
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