summaryrefslogtreecommitdiff
path: root/spec/frontend/content_editor/components/toolbar_image_button_spec.js
blob: 5473d43f5a1b0a93f8108b2adc6b62e2369c85ae (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
import { GlButton, GlFormInputGroup, GlDropdown } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import ToolbarImageButton from '~/content_editor/components/toolbar_image_button.vue';
import Attachment from '~/content_editor/extensions/attachment';
import Image from '~/content_editor/extensions/image';
import { stubComponent } from 'helpers/stub_component';
import { createTestEditor, mockChainedCommands } from '../test_utils';

describe('content_editor/components/toolbar_image_button', () => {
  let wrapper;
  let editor;

  const buildWrapper = () => {
    wrapper = mountExtended(ToolbarImageButton, {
      provide: {
        tiptapEditor: editor,
      },
      stubs: {
        GlDropdown: stubComponent(GlDropdown),
      },
    });
  };

  const findImageURLInput = () =>
    wrapper.findComponent(GlFormInputGroup).find('input[type="text"]');
  const findApplyImageButton = () => wrapper.findComponent(GlButton);
  const findDropdown = () => wrapper.findComponent(GlDropdown);

  const selectFile = async (file) => {
    const input = wrapper.findComponent({ ref: 'fileSelector' });

    // override the property definition because `input.files` isn't directly modifyable
    Object.defineProperty(input.element, 'files', { value: [file], writable: true });
    await input.trigger('change');
  };

  beforeEach(() => {
    editor = createTestEditor({
      extensions: [
        Image,
        Attachment.configure({
          renderMarkdown: jest.fn(),
          uploadsPath: '/uploads/',
        }),
      ],
    });

    buildWrapper();
  });

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

  it('sets the image to the value in the URL input when "Insert" button is clicked', async () => {
    const commands = mockChainedCommands(editor, ['focus', 'setImage', 'run']);

    await findImageURLInput().setValue('https://example.com/img.jpg');
    await findApplyImageButton().trigger('click');

    expect(commands.focus).toHaveBeenCalled();
    expect(commands.setImage).toHaveBeenCalledWith({
      alt: 'img',
      src: 'https://example.com/img.jpg',
      canonicalSrc: 'https://example.com/img.jpg',
    });
    expect(commands.run).toHaveBeenCalled();

    expect(wrapper.emitted().execute[0]).toEqual([{ contentType: 'image', value: 'url' }]);
  });

  it('uploads the selected image when file input changes', async () => {
    const commands = mockChainedCommands(editor, ['focus', 'uploadAttachment', 'run']);
    const file = new File(['foo'], 'foo.png', { type: 'image/png' });

    await selectFile(file);

    expect(commands.focus).toHaveBeenCalled();
    expect(commands.uploadAttachment).toHaveBeenCalledWith({ file });
    expect(commands.run).toHaveBeenCalled();

    expect(wrapper.emitted().execute[0]).toEqual([{ contentType: 'image', value: 'upload' }]);
  });

  describe('a11y tests', () => {
    it('sets text, title, and text-sr-only properties to the table button dropdown', () => {
      buildWrapper();

      expect(findDropdown().props()).toMatchObject({
        text: 'Insert image',
        textSrOnly: true,
      });
      expect(findDropdown().attributes('title')).toBe('Insert image');
    });
  });
});