summaryrefslogtreecommitdiff
path: root/spec/frontend/lib/utils/navigation_utility_spec.js
blob: 632a8904578dcbb364e9ee825d7842a38384f554 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
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');

describe('findAndFollowLink', () => {
  it('visits a link when the selector exists', () => {
    const href = '/some/path';

    setHTMLFixture(`<a class="my-shortcut" href="${href}">link</a>`);

    findAndFollowLink('.my-shortcut');

    expect(visitUrl).toHaveBeenCalledWith(href);

    resetHTMLFixture();
  });

  it('does not throw an exception when the selector does not exist', () => {
    // this should not throw an exception
    findAndFollowLink('.this-selector-does-not-exist');

    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,
      );
    });
  });
});