status_bar.test.ts 7.4 KB
Newer Older
1 2 3
import * as vscode from 'vscode';
import * as gitLabService from './gitlab_service';
import { pipeline, mr, issue } from './test_utils/entities';
4
import { USER_COMMANDS } from './command_names';
5
import { gitExtensionWrapper } from './git/git_extension_wrapper';
T
Tomas Vik 已提交
6
import { asMock } from './test_utils/as_mock';
7 8

jest.mock('./gitlab_service');
9
jest.mock('./git/git_extension_wrapper');
10 11

asMock(vscode.workspace.getConfiguration).mockReturnValue({
12 13 14 15
  showStatusBarLinks: true,
  showIssueLinkOnStatusBar: true,
  showMrStatusOnStatusBar: true,
});
16 17 18 19 20 21 22 23 24 25 26 27

// StatusBar needs to be imported after we mock the configuration because it uses the configuration
// during module initialization
// eslint-disable-next-line import/first
import { StatusBar } from './status_bar';

const createFakeItem = (): vscode.StatusBarItem =>
  (({
    show: jest.fn(),
    hide: jest.fn(),
    dispose: jest.fn(),
  } as unknown) as vscode.StatusBarItem);
28

29 30 31
// StatusBar is only interested in whether the project exists or not
const mockedGitLabProject = {};

32
describe('status_bar', () => {
33 34
  let fakeItems: vscode.StatusBarItem[];
  let statusBar: StatusBar;
35
  const getPipelineItem = () => fakeItems[0];
T
Tomas Vik 已提交
36 37
  const getMrItem = () => fakeItems[1];
  const getClosingIssueItem = () => fakeItems[2];
38 39 40 41

  beforeEach(() => {
    fakeItems = [];
    statusBar = new StatusBar();
42
    asMock(vscode.window.createStatusBarItem).mockImplementation(() => {
43 44 45 46
      const fakeItem = createFakeItem();
      fakeItems.push(fakeItem);
      return fakeItem;
    });
47 48
    asMock(gitExtensionWrapper.getActiveRepository).mockReturnValue({
      rootFsPath: '/folder',
49
      getProject: async () => ({}),
50
    });
51
  });
52 53 54 55 56 57

  afterEach(() => {
    statusBar.dispose();
  });

  it('hides all items when the workspace does not contain GitLab project', async () => {
58 59 60 61
    asMock(gitExtensionWrapper.getActiveRepository).mockReturnValue({
      rootFsPath: '/folder',
      getProject: async () => undefined,
    });
62 63 64 65 66 67
    await statusBar.init();
    expect(getPipelineItem().hide).toHaveBeenCalled();
    expect(getMrItem().hide).toHaveBeenCalled();
    expect(getClosingIssueItem().hide).toHaveBeenCalled();
  });

68 69
  describe('pipeline item', () => {
    beforeEach(() => {
70
      asMock(gitLabService.fetchLastJobsForCurrentBranch).mockReset();
71 72 73
    });

    it('initializes the pipeline item with success', async () => {
74
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({ pipeline });
75 76 77 78 79 80 81
      await statusBar.init();
      expect(getPipelineItem().show).toHaveBeenCalled();
      expect(getPipelineItem().hide).not.toHaveBeenCalled();
      expect(getPipelineItem().text).toBe('$(check) GitLab: Pipeline passed');
    });

    it('prints jobs for running pipeline', async () => {
82
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({
T
Tomas Vik 已提交
83 84 85 86
        pipeline: {
          ...pipeline,
          status: 'running',
        },
87
      });
88
      asMock(gitLabService.fetchLastJobsForCurrentBranch).mockReturnValue([
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
        {
          status: 'running',
          name: 'Unit Tests',
        },
        {
          status: 'running',
          name: 'Integration Tests',
        },
        {
          status: 'success',
          name: 'Lint',
        },
      ]);
      await statusBar.init();
      expect(getPipelineItem().text).toBe(
        '$(pulse) GitLab: Pipeline running (Unit Tests, Integration Tests)',
      );
    });

    it('shows no pipeline text when there is no pipeline', async () => {
109 110 111
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({
        pipeline: null,
      });
112 113 114 115 116 117 118 119 120 121 122 123 124
      await statusBar.init();
      expect(getPipelineItem().text).toBe('GitLab: No pipeline.');
    });

    it.each`
      status        | itemText
      ${'running'}  | ${'$(pulse) GitLab: Pipeline running'}
      ${'success'}  | ${'$(check) GitLab: Pipeline passed'}
      ${'pending'}  | ${'$(clock) GitLab: Pipeline pending'}
      ${'failed'}   | ${'$(x) GitLab: Pipeline failed'}
      ${'canceled'} | ${'$(circle-slash) GitLab: Pipeline canceled'}
      ${'skipped'}  | ${'$(diff-renamed) GitLab: Pipeline skipped'}
    `('shows $itemText for pipeline with status $status', async ({ status, itemText }) => {
125
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({
T
Tomas Vik 已提交
126 127 128 129
        pipeline: {
          ...pipeline,
          status,
        },
130 131 132 133 134 135
      });
      await statusBar.init();
      expect(getPipelineItem().text).toBe(itemText);
    });
  });

T
Tomas Vik 已提交
136
  describe('MR item', () => {
137
    beforeEach(() => {
138
      asMock(gitLabService.fetchCurrentPipelineProject).mockReturnValue(mockedGitLabProject);
139
      // FIXME: why is closing issue fetched from normal remote and pipeline result from pipeline remote?
140 141 142 143
      asMock(gitExtensionWrapper.getActiveRepository).mockReturnValue({
        rootFsPath: '/folder',
        getProject: async () => mockedGitLabProject,
      });
144 145
    });

T
Tomas Vik 已提交
146
    it('shows MR item', async () => {
147
      asMock(gitLabService.fetchMRIssues).mockReturnValue([]);
148
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({ mr });
149
      await statusBar.init();
T
Tomas Vik 已提交
150 151 152
      expect(getMrItem().show).toHaveBeenCalled();
      expect(getMrItem().hide).not.toHaveBeenCalled();
      expect(getMrItem().text).toBe('$(git-pull-request) GitLab: MR !2000');
153 154
      const command = getMrItem().command as vscode.Command;
      expect(command.command).toBe('vscode.open');
155
      expect(command.arguments?.[0]).toEqual(vscode.Uri.parse(mr.web_url));
156 157
    });

T
Tomas Vik 已提交
158
    it('shows create MR text when there is no MR', async () => {
159
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({});
160
      await statusBar.init();
T
Tomas Vik 已提交
161
      expect(getMrItem().text).toBe('$(git-pull-request) GitLab: Create MR.');
162
      expect(getMrItem().command).toBe(USER_COMMANDS.OPEN_CREATE_NEW_MR);
163 164 165
    });
  });

T
Tomas Vik 已提交
166
  describe('MR closing issue item', () => {
167
    beforeEach(() => {
168
      asMock(gitLabService.fetchCurrentPipelineProject).mockReturnValue(mockedGitLabProject);
169
      // FIXME: why is closing issue fetched from normal remote and pipeline result from pipeline remote?
170 171 172 173
      asMock(gitExtensionWrapper.getActiveRepository).mockReturnValue({
        rootFsPath: '/folder',
        getProject: async () => mockedGitLabProject,
      });
174 175
    });

T
Tomas Vik 已提交
176
    it('shows closing issue for an MR', async () => {
177
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({ mr });
T
Tomas Vik 已提交
178
      asMock(gitLabService.fetchMRIssues).mockReturnValue([issue]);
179
      await statusBar.init();
T
Tomas Vik 已提交
180 181 182
      expect(getClosingIssueItem().show).toHaveBeenCalled();
      expect(getClosingIssueItem().hide).not.toHaveBeenCalled();
      expect(getClosingIssueItem().text).toBe('$(code) GitLab: Issue #1000');
183 184
      const command = getClosingIssueItem().command as vscode.Command;
      expect(command.command).toBe('vscode.open');
185
      expect(command.arguments?.[0]).toEqual(vscode.Uri.parse(issue.web_url));
186 187
    });

T
Tomas Vik 已提交
188
    it('shows no issue when there is not a closing issue', async () => {
189
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({ mr });
T
Tomas Vik 已提交
190 191 192
      asMock(gitLabService.fetchMRIssues).mockReturnValue([]);
      await statusBar.init();
      expect(getClosingIssueItem().text).toBe('$(code) GitLab: No issue.');
193
      expect(getClosingIssueItem().command).toBe(undefined);
T
Tomas Vik 已提交
194 195
    });

196
    it('hides the item when there is is no MR', async () => {
197
      asMock(gitLabService.fetchPipelineAndMrForCurrentBranch).mockResolvedValue({});
198
      await statusBar.init();
199
      expect(getClosingIssueItem().hide).toHaveBeenCalled();
200 201 202
    });
  });
});