1 | import { shallowMount } from '@vue/test-utils';
|
2 | import { useMockIntersectionObserver } from '~/utils/use_mock_intersection_observer';
|
3 | import GlIntersectionObserver from './intersection_observer.vue';
|
4 |
|
5 | const TEST_SLOT = '<p>Hello world! Lorem ipsum.</p>';
|
6 | const ENTRY_INTERSECTING = { ratio: 0.75, isIntersecting: true };
|
7 | const ENTRY_NOT_INTERSECTING = { ratio: 0, isIntersecting: false };
|
8 | const TEST_OPTIONS = {};
|
9 |
|
10 | describe('IntersectionObserver', () => {
|
11 | let wrapper;
|
12 | let allWrappers;
|
13 | const { getInstances, trigger } = useMockIntersectionObserver();
|
14 |
|
15 | const hasPrivateProps = (obj) => Object.keys(obj).some((x) => x.startsWith('$_gl_'));
|
16 | const triggerIntersectionObserver = (entry) => {
|
17 | trigger(getInstances()[0], null, { entry });
|
18 | };
|
19 | const createComponent = (props = {}) => {
|
20 | wrapper = shallowMount(GlIntersectionObserver, {
|
21 | propsData: {
|
22 | ...props,
|
23 | },
|
24 | slots: {
|
25 | default: TEST_SLOT,
|
26 | },
|
27 | });
|
28 | allWrappers.push(wrapper);
|
29 | };
|
30 |
|
31 | beforeEach(() => {
|
32 | allWrappers = [];
|
33 | });
|
34 |
|
35 | afterEach(() => {
|
36 | allWrappers.forEach((x) => x.destroy());
|
37 | allWrappers = null;
|
38 | wrapper = null;
|
39 |
|
40 |
|
41 | GlIntersectionObserver.getObserver.cache.clear();
|
42 | });
|
43 |
|
44 | describe('with default', () => {
|
45 | beforeEach(() => {
|
46 | createComponent();
|
47 | });
|
48 |
|
49 | it('renders slot', () => {
|
50 | expect(wrapper.html()).toContain(TEST_SLOT);
|
51 | });
|
52 |
|
53 | it('creates 1 intersection observer', () => {
|
54 | expect(getInstances()).toHaveLength(1);
|
55 | });
|
56 |
|
57 | it('adds some private props to element', () => {
|
58 | expect(hasPrivateProps(wrapper.vm.$el)).toBe(true);
|
59 | });
|
60 |
|
61 | describe('when destroyed', () => {
|
62 | beforeEach(() => {
|
63 | wrapper.destroy();
|
64 | });
|
65 |
|
66 | it('clears private props on element', () => {
|
67 | expect(hasPrivateProps(wrapper.vm.$el)).toBe(false);
|
68 | });
|
69 |
|
70 | it('stops observing on element', () => {
|
71 | triggerIntersectionObserver(ENTRY_INTERSECTING);
|
72 |
|
73 | expect(wrapper.emitted()).toEqual({});
|
74 | });
|
75 | });
|
76 | });
|
77 |
|
78 | describe('with 2 instances', () => {
|
79 | beforeEach(() => {
|
80 | createComponent();
|
81 | createComponent();
|
82 | });
|
83 |
|
84 | it('creates 1 IntersectionObserver', () => {
|
85 | expect(getInstances()).toHaveLength(1);
|
86 | });
|
87 |
|
88 | it.each`
|
89 | desc | entry | event
|
90 | ${'with interesecting'} | ${ENTRY_INTERSECTING} | ${'appear'}
|
91 | ${'without interesecting'} | ${ENTRY_NOT_INTERSECTING} | ${'disappear'}
|
92 | `('when triggered $desc, emits events', ({ entry, event }) => {
|
93 | const createExpectation = ({ element }) => ({
|
94 | [event]: [[]],
|
95 | update: [[{ ...entry, target: element }]],
|
96 | });
|
97 |
|
98 | triggerIntersectionObserver(entry);
|
99 |
|
100 | expect(allWrappers).toHaveLength(2);
|
101 | expect(allWrappers.map((x) => x.emitted())).toEqual(allWrappers.map(createExpectation));
|
102 | });
|
103 | });
|
104 |
|
105 | describe('with 2 instances with different options', () => {
|
106 | beforeEach(() => {
|
107 | createComponent();
|
108 | createComponent({ options: TEST_OPTIONS });
|
109 | });
|
110 |
|
111 | it('creates 2 IntersectionObservers', () => {
|
112 | expect(getInstances()).toHaveLength(2);
|
113 | });
|
114 | });
|
115 | });
|