summaryrefslogtreecommitdiff
path: root/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
blob: 46523baadf342094210f43e6d1c80fa23feb6171 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import { GlAlert, GlLoadingIcon, GlTabs, GlTab } from '@gitlab/ui';

import { mockProjectPath, mockDefaultBranch, mockCiConfigPath, mockCiYml } from './mock_data';
import TextEditor from '~/pipeline_editor/components/text_editor.vue';
import EditorLite from '~/vue_shared/components/editor_lite.vue';
import PipelineGraph from '~/pipelines/components/pipeline_graph/pipeline_graph.vue';
import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';

describe('~/pipeline_editor/pipeline_editor_app.vue', () => {
  let wrapper;

  const createComponent = (
    { props = {}, data = {}, loading = false } = {},
    mountFn = shallowMount,
  ) => {
    wrapper = mountFn(PipelineEditorApp, {
      propsData: {
        projectPath: mockProjectPath,
        defaultBranch: mockDefaultBranch,
        ciConfigPath: mockCiConfigPath,
        ...props,
      },
      data() {
        return data;
      },
      stubs: {
        GlTabs,
        TextEditor,
      },
      mocks: {
        $apollo: {
          queries: {
            content: {
              loading,
            },
          },
        },
      },
    });
  };

  const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
  const findAlert = () => wrapper.find(GlAlert);
  const findTabAt = i => wrapper.findAll(GlTab).at(i);
  const findEditorLite = () => wrapper.find(EditorLite);

  beforeEach(() => {
    createComponent();
  });

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

  it('displays content', () => {
    createComponent({ data: { content: mockCiYml } });

    expect(findLoadingIcon().exists()).toBe(false);
    expect(findEditorLite().props('value')).toBe(mockCiYml);
  });

  it('displays a loading icon if the query is loading', () => {
    createComponent({ loading: true });

    expect(findLoadingIcon().exists()).toBe(true);
  });

  describe('tabs', () => {
    it('displays tabs and their content', () => {
      createComponent({ data: { content: mockCiYml } });

      expect(
        findTabAt(0)
          .find(EditorLite)
          .exists(),
      ).toBe(true);
      expect(
        findTabAt(1)
          .find(PipelineGraph)
          .exists(),
      ).toBe(true);
    });

    it('displays editor tab lazily, until editor is ready', async () => {
      createComponent({ data: { content: mockCiYml } });

      expect(findTabAt(0).attributes('lazy')).toBe('true');

      findEditorLite().vm.$emit('editor-ready');
      await nextTick();

      expect(findTabAt(0).attributes('lazy')).toBe(undefined);
    });
  });

  describe('when in error state', () => {
    class MockError extends Error {
      constructor(message, data) {
        super(message);
        if (data) {
          this.networkError = {
            response: { data },
          };
        }
      }
    }

    it('shows a generic error', () => {
      const error = new MockError('An error message');
      createComponent({ data: { error } });

      expect(findAlert().text()).toBe('CI file could not be loaded: An error message');
    });

    it('shows a ref missing error state', () => {
      const error = new MockError('Ref missing!', {
        error: 'ref is missing, ref is empty',
      });
      createComponent({ data: { error } });

      expect(findAlert().text()).toMatch(
        'CI file could not be loaded: ref is missing, ref is empty',
      );
    });

    it('shows a file missing error state', async () => {
      const error = new MockError('File missing!', {
        message: 'file not found',
      });

      await wrapper.setData({ error });

      expect(findAlert().text()).toMatch('CI file could not be loaded: file not found');
    });
  });
});