summaryrefslogtreecommitdiff
path: root/spec/frontend/content_editor/services/track_input_rules_and_shortcuts_spec.js
blob: 437714ba938b3a9416dea10bee8219116979be84 (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
import { BulletList } from '@tiptap/extension-bullet-list';
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight';
import { Document } from '@tiptap/extension-document';
import { Heading } from '@tiptap/extension-heading';
import { ListItem } from '@tiptap/extension-list-item';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
import { Editor, EditorContent } from '@tiptap/vue-2';
import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { mockTracking } from 'helpers/tracking_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import {
  KEYBOARD_SHORTCUT_TRACKING_ACTION,
  INPUT_RULE_TRACKING_ACTION,
  CONTENT_EDITOR_TRACKING_LABEL,
} from '~/content_editor/constants';
import trackInputRulesAndShortcuts from '~/content_editor/services/track_input_rules_and_shortcuts';
import { ENTER_KEY, BACKSPACE_KEY } from '~/lib/utils/keys';

describe('content_editor/services/track_input_rules_and_shortcuts', () => {
  let wrapper;
  let trackingSpy;
  let editor;
  const HEADING_TEXT = 'Heading text';

  const buildWrapper = () => {
    wrapper = extendedWrapper(
      mount(EditorContent, {
        propsData: {
          editor,
        },
      }),
    );
  };

  beforeEach(() => {
    trackingSpy = mockTracking(undefined, null, jest.spyOn);
  });

  afterEach(() => {
    wrapper.destroy();
  });

  describe('given the heading extension is instrumented', () => {
    beforeEach(() => {
      editor = new Editor({
        extensions: [
          Document,
          Paragraph,
          Text,
          Heading,
          CodeBlockLowlight,
          BulletList,
          ListItem,
        ].map(trackInputRulesAndShortcuts),
      });
    });

    beforeEach(async () => {
      buildWrapper();
      await nextTick();
    });

    describe('when creating a heading using an keyboard shortcut', () => {
      it('sends a tracking event indicating that a heading was created using an input rule', async () => {
        const shortcuts = Heading.config.addKeyboardShortcuts.call(Heading);
        const [firstShortcut] = Object.keys(shortcuts);
        const nodeName = Heading.name;

        editor.chain().keyboardShortcut(firstShortcut).insertContent(HEADING_TEXT).run();

        expect(trackingSpy).toHaveBeenCalledWith(undefined, KEYBOARD_SHORTCUT_TRACKING_ACTION, {
          label: CONTENT_EDITOR_TRACKING_LABEL,
          property: `${nodeName}.${firstShortcut}`,
        });
      });
    });

    it.each`
      extension                 | shortcut
      ${ListItem.name}          | ${ENTER_KEY}
      ${CodeBlockLowlight.name} | ${BACKSPACE_KEY}
    `('does not track $shortcut shortcut for $extension extension', ({ shortcut }) => {
      editor.chain().keyboardShortcut(shortcut).run();

      expect(trackingSpy).not.toHaveBeenCalled();
    });

    describe('when creating a heading using an input rule', () => {
      it('sends a tracking event indicating that a heading was created using an input rule', async () => {
        const nodeName = Heading.name;
        const { view } = editor;
        const { selection } = view.state;

        // Triggers the event handler that input rules listen to
        view.someProp('handleTextInput', (f) => f(view, selection.from, selection.to, '## '));

        editor.chain().insertContent(HEADING_TEXT).run();

        expect(trackingSpy).toHaveBeenCalledWith(undefined, INPUT_RULE_TRACKING_ACTION, {
          label: CONTENT_EDITOR_TRACKING_LABEL,
          property: `${nodeName}`,
        });
      });
    });
  });
});