Commit 2516aeb2 authored by Mark Florian's avatar Mark Florian

Merge branch '300403-replace-commit-box-minipipeline-remove-ff' into 'master'

Remove ci_commit_pipeline_mini_graph_vue flag [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!56510
parents a8310e4d e1fd7d0d
import $ from 'jquery';
import { deprecatedCreateFlash as flash } from './flash';
import axios from './lib/utils/axios_utils';
import { __ } from './locale';
/**
* In each pipelines table we have a mini pipeline graph for each pipeline.
*
* When we click in a pipeline stage, we need to make an API call to get the
* builds list to render in a dropdown.
*
* The container should be the table element.
*
* The stage icon clicked needs to have the following HTML structure:
* <div class="dropdown">
* <button class="dropdown js-builds-dropdown-button" data-toggle="dropdown"></button>
* <div class="js-builds-dropdown-container dropdown-menu"></div>
* </div>
*/
export default class MiniPipelineGraph {
constructor(opts = {}) {
this.container = opts.container || '';
this.dropdownListSelector = '.js-builds-dropdown-container';
this.getBuildsList = this.getBuildsList.bind(this);
}
/**
* Adds the event listener when the dropdown is opened.
* All dropdown events are fired at the .dropdown-menu's parent element.
*/
bindEvents() {
$(document)
.off('shown.bs.dropdown', this.container)
.on('shown.bs.dropdown', this.container, this.getBuildsList);
}
/**
* When the user right clicks or cmd/ctrl + click in the job name
* the dropdown should not be closed and the link should open in another tab,
* so we stop propagation of the click event inside the dropdown.
*
* Since this component is rendered multiple times per page we need to guarantee we only
* target the click event of this component.
*/
stopDropdownClickPropagation() {
$(document).on(
'click',
`${this.container} .js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`,
(e) => {
e.stopPropagation();
},
);
}
/**
* For the clicked stage, renders the given data in the dropdown list.
*
* @param {HTMLElement} stageContainer
* @param {Object} data
*/
renderBuildsList(stageContainer, data) {
const dropdownContainer = stageContainer.parentElement.querySelector(
`${this.dropdownListSelector} .js-builds-dropdown-list ul`,
);
dropdownContainer.innerHTML = data;
}
/**
* For the clicked stage, gets the list of builds.
*
* All dropdown events have a relatedTarget property,
* whose value is the toggling anchor element.
*
* @param {Object} e bootstrap dropdown event
* @return {Promise}
*/
getBuildsList(e) {
const button = e.relatedTarget;
const endpoint = button.dataset.stageEndpoint;
this.renderBuildsList(button, '');
this.toggleLoading(button);
axios
.get(endpoint)
.then(({ data }) => {
this.toggleLoading(button);
this.renderBuildsList(button, data.html);
this.stopDropdownClickPropagation();
})
.catch(() => {
this.toggleLoading(button);
if ($(button).parent().hasClass('open')) {
$(button).dropdown('toggle');
}
flash(__('An error occurred while fetching the builds.'), 'alert');
});
}
/**
* Toggles the visibility of the loading icon.
*
* @param {HTMLElement} stageContainer
* @return {type}
*/
toggleLoading(stageContainer) {
stageContainer.parentElement
.querySelector(`${this.dropdownListSelector} .js-builds-dropdown-loading`)
.classList.toggle('hidden');
}
}
...@@ -36,7 +36,7 @@ export default { ...@@ -36,7 +36,7 @@ export default {
}; };
</script> </script>
<template> <template>
<div data-testid="widget-mini-pipeline-graph"> <div data-testid="pipeline-mini-graph">
<div <div
v-for="stage in stages" v-for="stage in stages"
:key="stage.name" :key="stage.name"
......
import { fetchCommitMergeRequests } from '~/commit_merge_requests'; import { fetchCommitMergeRequests } from '~/commit_merge_requests';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
import { initCommitPipelineMiniGraph } from './init_commit_pipeline_mini_graph'; import { initCommitPipelineMiniGraph } from './init_commit_pipeline_mini_graph';
import { initDetailsButton } from './init_details_button'; import { initDetailsButton } from './init_details_button';
import { loadBranches } from './load_branches'; import { loadBranches } from './load_branches';
export const initCommitBoxInfo = (containerSelector = '.js-commit-box-info') => { export const initCommitBoxInfo = () => {
const containerEl = document.querySelector(containerSelector);
// Display commit related branches // Display commit related branches
loadBranches(containerEl); loadBranches();
// Related merge requests to this commit // Related merge requests to this commit
fetchCommitMergeRequests(); fetchCommitMergeRequests();
// Display pipeline mini graph for this commit // Display pipeline mini graph for this commit
// Feature flag ci_commit_pipeline_mini_graph_vue initCommitPipelineMiniGraph();
if (gon.features.ciCommitPipelineMiniGraphVue) {
initCommitPipelineMiniGraph();
} else {
new MiniPipelineGraph({
container: '.js-commit-pipeline-graph',
}).bindEvents();
}
initDetailsButton(); initDetailsButton();
}; };
...@@ -2,7 +2,8 @@ import axios from 'axios'; ...@@ -2,7 +2,8 @@ import axios from 'axios';
import { sanitize } from '~/lib/dompurify'; import { sanitize } from '~/lib/dompurify';
import { __ } from '~/locale'; import { __ } from '~/locale';
export const loadBranches = (containerEl) => { export const loadBranches = (containerSelector = '.js-commit-box-info') => {
const containerEl = document.querySelector(containerSelector);
if (!containerEl) { if (!containerEl) {
return; return;
} }
......
...@@ -19,11 +19,6 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -19,11 +19,6 @@ class Projects::CommitController < Projects::ApplicationController
before_action :define_commit_box_vars, only: [:show, :pipelines] before_action :define_commit_box_vars, only: [:show, :pipelines]
before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files] before_action :define_note_vars, only: [:show, :diff_for_path, :diff_files]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick] before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
before_action only: [:show, :pipelines] do
push_frontend_feature_flag(:ci_commit_pipeline_mini_graph_vue, @project, default_enabled: :yaml)
end
before_action do before_action do
push_frontend_feature_flag(:pick_into_project) push_frontend_feature_flag(:pick_into_project)
end end
...@@ -214,7 +209,6 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -214,7 +209,6 @@ class Projects::CommitController < Projects::ApplicationController
def define_commit_box_vars def define_commit_box_vars
@last_pipeline = @commit.last_pipeline @last_pipeline = @commit.last_pipeline
return unless ::Gitlab::Ci::Features.ci_commit_pipeline_mini_graph_vue_enabled?(@project)
return unless @commit.last_pipeline return unless @commit.last_pipeline
@last_pipeline_stages = StageSerializer.new(project: @project, current_user: @current_user).represent(@last_pipeline.stages) @last_pipeline_stages = StageSerializer.new(project: @project, current_user: @current_user).represent(@last_pipeline.stages)
......
...@@ -152,15 +152,6 @@ class Projects::PipelinesController < Projects::ApplicationController ...@@ -152,15 +152,6 @@ class Projects::PipelinesController < Projects::ApplicationController
.represent(@stage, details: true, retried: params[:retried]) .represent(@stage, details: true, retried: params[:retried])
end end
# TODO: This endpoint is used by mini-pipeline-graph
# TODO: This endpoint should be migrated to `stage.json`
def stage_ajax
@stage = pipeline.legacy_stage(params[:stage])
return not_found unless @stage
render json: { html: view_to_html_string('projects/pipelines/_stage') }
end
def retry def retry
pipeline.retry_failed(current_user) pipeline.retry_failed(current_user)
......
-# Renders the content of each li in the dropdown
- subject = local_assigns.fetch(:subject)
- status = subject.detailed_status(current_user)
- klass = "ci-status-icon ci-status-icon-#{status.group}"
- tooltip = "#{subject.name} - #{status.status_tooltip}"
- if status.has_details?
= link_to status.details_path, class: 'mini-pipeline-graph-dropdown-item d-flex', data: { toggle: 'tooltip', title: tooltip, container: 'body' } do
%span{ class: klass }= sprite_icon(status.icon)
%span.gl-text-truncate.mw-70p.gl-pl-2= subject.name
- else
.menu-item.mini-pipeline-graph-dropdown-item.d-flex{ data: { toggle: 'tooltip', title: tooltip, container: 'body' } }
%span{ class: klass }= sprite_icon(status.icon)
%span.gl-text-truncate.mw-70p.gl-pl-2= subject.name
- if status.has_action?
= link_to status.action_path, class: "gl-button ci-action-icon-container ci-action-icon-wrapper js-ci-action-icon", method: status.action_method, data: { toggle: 'tooltip', title: status.action_title, container: 'body' } do
= sprite_icon(status.action_icon, css_class: "icon-action-#{status.action_icon}")
...@@ -59,11 +59,8 @@ ...@@ -59,11 +59,8 @@
- if @last_pipeline.stages_count.nonzero? - if @last_pipeline.stages_count.nonzero?
#{ n_(s_('Pipeline|with stage'), s_('Pipeline|with stages'), @last_pipeline.stages_count) } #{ n_(s_('Pipeline|with stage'), s_('Pipeline|with stages'), @last_pipeline.stages_count) }
.mr-widget-pipeline-graph .mr-widget-pipeline-graph
- if ::Gitlab::Ci::Features.ci_commit_pipeline_mini_graph_vue_enabled?(@project) .stage-cell
.stage-cell .js-commit-pipeline-mini-graph{ data: { stages: @last_pipeline_stages.to_json.html_safe } }
.js-commit-pipeline-mini-graph{ data: { stages: @last_pipeline_stages.to_json.html_safe } }
- else
= render 'shared/mini_pipeline_graph', pipeline: @last_pipeline, klass: 'js-commit-pipeline-graph'
- if @last_pipeline.duration - if @last_pipeline.duration
in in
= time_interval_in_words @last_pipeline.duration = time_interval_in_words @last_pipeline.duration
......
- grouped_statuses = @stage.statuses.latest_ordered.group_by(&:status)
- Ci::HasStatus::ORDERED_STATUSES.each do |ordered_status|
- grouped_statuses.fetch(ordered_status, []).each do |status|
%li
= render 'ci/status/dropdown_graph_badge', subject: status
.stage-cell
- pipeline.legacy_stages.each do |stage|
- if stage.status
- detailed_status = stage.detailed_status(current_user)
- icon_status = "#{detailed_status.icon}_borderless"
.stage-container.mt-0.ml-1.dropdown{ class: klass }
%button.mini-pipeline-graph-dropdown-toggle.has-tooltip.js-builds-dropdown-button{ class: "ci-status-icon-#{detailed_status.group}", type: 'button', data: { toggle: 'dropdown', title: "#{stage.name}: #{detailed_status.label}", placement: 'top', "stage-endpoint" => stage_ajax_project_pipeline_path(pipeline.project, pipeline, stage: stage.name) } }
= sprite_icon(icon_status)
%ul.dropdown-menu.mini-pipeline-graph-dropdown-menu.js-builds-dropdown-container
%li.js-builds-dropdown-list.scrollable-menu
%ul
%li.js-builds-dropdown-loading.hidden
.loading-container.text-center
%span.spinner{ 'aria-label': _('Loading') }
---
title: Update mini pipeline appearance in commit page to match other mini pipelines
in the application
merge_request: 56510
author:
type: changed
---
name: ci_commit_pipeline_mini_graph_vue
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55363
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323356
milestone: '13.10'
type: development
group: group::pipeline authoring
default_enabled: true
...@@ -12,7 +12,6 @@ resources :pipelines, only: [:index, :new, :create, :show, :destroy] do ...@@ -12,7 +12,6 @@ resources :pipelines, only: [:index, :new, :create, :show, :destroy] do
member do member do
get :stage get :stage
get :stage_ajax
post :cancel post :cancel
post :retry post :retry
get :builds get :builds
......
...@@ -64,10 +64,6 @@ module Gitlab ...@@ -64,10 +64,6 @@ module Gitlab
::Feature.enabled?(:multiple_cache_per_job, default_enabled: :yaml) ::Feature.enabled?(:multiple_cache_per_job, default_enabled: :yaml)
end end
def self.ci_commit_pipeline_mini_graph_vue_enabled?(project)
::Feature.enabled?(:ci_commit_pipeline_mini_graph_vue, project, default_enabled: :yaml)
end
def self.remove_duplicate_artifact_exposure_paths?(project) def self.remove_duplicate_artifact_exposure_paths?(project)
::Feature.enabled?(:remove_duplicate_artifact_exposure_paths, project, default_enabled: :yaml) ::Feature.enabled?(:remove_duplicate_artifact_exposure_paths, project, default_enabled: :yaml)
end end
......
...@@ -3449,9 +3449,6 @@ msgstr "" ...@@ -3449,9 +3449,6 @@ msgstr ""
msgid "An error occurred while fetching the board lists. Please try again." msgid "An error occurred while fetching the board lists. Please try again."
msgstr "" msgstr ""
msgid "An error occurred while fetching the builds."
msgstr ""
msgid "An error occurred while fetching the job log." msgid "An error occurred while fetching the job log."
msgstr "" msgstr ""
......
...@@ -628,44 +628,6 @@ RSpec.describe Projects::PipelinesController do ...@@ -628,44 +628,6 @@ RSpec.describe Projects::PipelinesController do
end end
end end
describe 'GET stages_ajax.json' do
let(:pipeline) { create(:ci_pipeline, project: project) }
context 'when accessing existing stage' do
before do
create(:ci_build, pipeline: pipeline, stage: 'build')
get_stage_ajax('build')
end
it 'returns html source for stage dropdown' do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to render_template('projects/pipelines/_stage')
expect(json_response).to include('html')
end
end
context 'when accessing unknown stage' do
before do
get_stage_ajax('test')
end
it 'responds with not found' do
expect(response).to have_gitlab_http_status(:not_found)
end
end
def get_stage_ajax(name)
get :stage_ajax, params: {
namespace_id: project.namespace,
project_id: project,
id: pipeline.id,
stage: name
},
format: :json
end
end
describe 'GET status.json' do describe 'GET status.json' do
let(:pipeline) { create(:ci_pipeline, project: project) } let(:pipeline) { create(:ci_pipeline, project: project) }
let(:status) { pipeline.detailed_status(double('user')) } let(:status) { pipeline.detailed_status(double('user')) }
......
...@@ -23,7 +23,7 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do ...@@ -23,7 +23,7 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
end end
it 'displays a mini pipeline graph' do it 'displays a mini pipeline graph' do
expect(page).to have_selector('.mr-widget-pipeline-graph') expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
end end
context 'as json' do context 'as json' do
......
...@@ -16,46 +16,28 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do ...@@ -16,46 +16,28 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
let(:build) { create(:ci_build, pipeline: pipeline, status: :running) } let(:build) { create(:ci_build, pipeline: pipeline, status: :running) }
shared_examples 'shows ci icon and mini pipeline' do before do
before do build.run
build.run visit project_commit_path(project, project.commit.id)
visit project_commit_path(project, project.commit.id) end
end
it 'display icon with status' do
expect(page).to have_selector('.ci-status-icon-running')
end
it 'displays a mini pipeline graph' do
expect(page).to have_selector('.mr-widget-pipeline-graph')
first('.mini-pipeline-graph-dropdown-toggle').click
wait_for_requests
page.within '.js-builds-dropdown-list' do
expect(page).to have_selector('.ci-status-icon-running')
expect(page).to have_content(build.stage)
end
build.drop it 'display icon with status' do
end expect(page).to have_selector('.ci-status-icon-running')
end end
context 'when ci_commit_pipeline_mini_graph_vue is disabled' do it 'displays a mini pipeline graph' do
before do expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
stub_feature_flags(ci_commit_pipeline_mini_graph_vue: false)
end
it_behaves_like 'shows ci icon and mini pipeline' first('.mini-pipeline-graph-dropdown-toggle').click
end
context 'when ci_commit_pipeline_mini_graph_vue is enabled' do wait_for_requests
before do
stub_feature_flags(ci_commit_pipeline_mini_graph_vue: true) page.within '.js-builds-dropdown-list' do
expect(page).to have_selector('.ci-status-icon-running')
expect(page).to have_content(build.stage)
end end
it_behaves_like 'shows ci icon and mini pipeline' build.drop
end end
end end
...@@ -65,7 +47,7 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do ...@@ -65,7 +47,7 @@ RSpec.describe 'Mini Pipeline Graph in Commit View', :js do
end end
it 'does not display a mini pipeline graph' do it 'does not display a mini pipeline graph' do
expect(page).not_to have_selector('.mr-widget-pipeline-graph') expect(page).not_to have_selector('[data-testid="pipeline-mini-graph"]')
end end
end end
end end
...@@ -534,7 +534,7 @@ RSpec.describe 'Pipelines', :js do ...@@ -534,7 +534,7 @@ RSpec.describe 'Pipelines', :js do
end end
it 'renders a mini pipeline graph' do it 'renders a mini pipeline graph' do
expect(page).to have_selector('[data-testid="widget-mini-pipeline-graph"]') expect(page).to have_selector('[data-testid="pipeline-mini-graph"]')
expect(page).to have_selector(dropdown_selector) expect(page).to have_selector(dropdown_selector)
end end
......
<div class="js-builds-dropdown-tests dropdown dropdown" data-testid="widget-mini-pipeline-graph">
<button class="js-builds-dropdown-button" data-toggle="dropdown" data-stage-endpoint="foobar">
Dropdown
</button>
<ul class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container">
<li class="js-builds-dropdown-list scrollable-menu">
<ul></ul>
</li>
<li class="js-builds-dropdown-loading hidden">
<span class="gl-spinner"></span>
</li>
</ul>
</div>
import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
describe('Mini Pipeline Graph Dropdown', () => {
beforeEach(() => {
loadFixtures('static/mini_dropdown_graph.html');
});
describe('When is initialized', () => {
it('should initialize without errors when no options are given', () => {
const miniPipelineGraph = new MiniPipelineGraph();
expect(miniPipelineGraph.dropdownListSelector).toEqual('.js-builds-dropdown-container');
});
it('should set the container as the given prop', () => {
const container = '.foo';
const miniPipelineGraph = new MiniPipelineGraph({ container });
expect(miniPipelineGraph.container).toEqual(container);
});
});
describe('When dropdown is clicked', () => {
let mock;
beforeEach(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.restore();
});
it('should call getBuildsList', () => {
const getBuildsListSpy = jest
.spyOn(MiniPipelineGraph.prototype, 'getBuildsList')
.mockImplementation(() => {});
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
document.querySelector('.js-builds-dropdown-button').click();
expect(getBuildsListSpy).toHaveBeenCalled();
});
it('should make a request to the endpoint provided in the html', () => {
const ajaxSpy = jest.spyOn(axios, 'get');
mock.onGet('foobar').reply(200, {
html: '',
});
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
document.querySelector('.js-builds-dropdown-button').click();
expect(ajaxSpy.mock.calls[0][0]).toEqual('foobar');
});
it('should not close when user uses cmd/ctrl + click', (done) => {
mock.onGet('foobar').reply(200, {
html: `<li>
<a class="mini-pipeline-graph-dropdown-item" href="#">
<span class="ci-status-icon ci-status-icon-failed"></span>
<span>build</span>
</a>
<a class="ci-action-icon-wrapper js-ci-action-icon" href="#"></a>
</li>`,
});
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
document.querySelector('.js-builds-dropdown-button').click();
waitForPromises()
.then(() => {
document.querySelector('a.mini-pipeline-graph-dropdown-item').click();
})
.then(waitForPromises)
.then(() => {
expect($('.js-builds-dropdown-list').is(':visible')).toEqual(true);
})
.then(done)
.catch(done.fail);
});
it('should close the dropdown when request returns an error', (done) => {
mock.onGet('foobar').networkError();
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
document.querySelector('.js-builds-dropdown-button').click();
setImmediate(() => {
expect($('.js-builds-dropdown-tests .dropdown').hasClass('open')).toEqual(false);
done();
});
});
});
});
import axios from 'axios'; import axios from 'axios';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import { setHTMLFixture } from 'helpers/fixtures';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { loadBranches } from '~/projects/commit_box/info/load_branches'; import { loadBranches } from '~/projects/commit_box/info/load_branches';
...@@ -9,32 +10,38 @@ const mockBranchesRes = ...@@ -9,32 +10,38 @@ const mockBranchesRes =
describe('~/projects/commit_box/info/load_branches', () => { describe('~/projects/commit_box/info/load_branches', () => {
let mock; let mock;
let el;
const getElInnerHtml = () => document.querySelector('.js-commit-box-info').innerHTML;
beforeEach(() => { beforeEach(() => {
setHTMLFixture(`
<div class="js-commit-box-info" data-commit-path="${mockCommitPath}">
<div class="commit-info branches">
<span class="spinner"/>
</div>
</div>`);
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
mock.onGet(mockCommitPath).reply(200, mockBranchesRes); mock.onGet(mockCommitPath).reply(200, mockBranchesRes);
el = document.createElement('div');
el.dataset.commitPath = mockCommitPath;
el.innerHTML = '<div class="commit-info branches"><span class="spinner"/></div>';
}); });
it('loads and renders branches info', async () => { it('loads and renders branches info', async () => {
loadBranches(el); loadBranches();
await waitForPromises(); await waitForPromises();
expect(el.innerHTML).toBe(`<div class="commit-info branches">${mockBranchesRes}</div>`); expect(getElInnerHtml()).toMatchInterpolatedText(
`<div class="commit-info branches">${mockBranchesRes}</div>`,
);
}); });
it('does not load when no container is provided', async () => { it('does not load when no container is provided', async () => {
loadBranches(null); loadBranches('.js-another-class');
await waitForPromises(); await waitForPromises();
expect(mock.history.get).toHaveLength(0); expect(mock.history.get).toHaveLength(0);
}); });
describe('when braches request returns unsafe content', () => { describe('when branches request returns unsafe content', () => {
beforeEach(() => { beforeEach(() => {
mock mock
.onGet(mockCommitPath) .onGet(mockCommitPath)
...@@ -42,25 +49,25 @@ describe('~/projects/commit_box/info/load_branches', () => { ...@@ -42,25 +49,25 @@ describe('~/projects/commit_box/info/load_branches', () => {
}); });
it('displays sanitized html', async () => { it('displays sanitized html', async () => {
loadBranches(el); loadBranches();
await waitForPromises(); await waitForPromises();
expect(el.innerHTML).toBe( expect(getElInnerHtml()).toMatchInterpolatedText(
'<div class="commit-info branches"><a href="/-/commits/master">master</a></div>', '<div class="commit-info branches"><a href="/-/commits/master">master</a></div>',
); );
}); });
}); });
describe('when braches request fails', () => { describe('when branches request fails', () => {
beforeEach(() => { beforeEach(() => {
mock.onGet(mockCommitPath).reply(500, 'Error!'); mock.onGet(mockCommitPath).reply(500, 'Error!');
}); });
it('attempts to load and renders an error', async () => { it('attempts to load and renders an error', async () => {
loadBranches(el); loadBranches();
await waitForPromises(); await waitForPromises();
expect(el.innerHTML).toBe( expect(getElInnerHtml()).toMatchInterpolatedText(
'<div class="commit-info branches">Failed to load branches. Please try again.</div>', '<div class="commit-info branches">Failed to load branches. Please try again.</div>',
); );
}); });
......
...@@ -34,14 +34,6 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do ...@@ -34,14 +34,6 @@ RSpec.describe 'projects/commit/_commit_box.html.haml' do
expect(rendered).to have_selector('.js-commit-pipeline-mini-graph') expect(rendered).to have_selector('.js-commit-pipeline-mini-graph')
end end
it 'shows pipeline stages in haml when feature flag is disabled' do
stub_feature_flags(ci_commit_pipeline_mini_graph_vue: false)
render
expect(rendered).to have_selector('.js-commit-pipeline-graph')
end
end end
context 'when there are multiple pipelines for a commit' do context 'when there are multiple pipelines for a commit' do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'projects/pipelines/_stage' do
let(:project) { create(:project, :repository) }
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:stage) { build(:ci_stage, pipeline: pipeline) }
before do
assign :stage, stage
end
context 'when there are only latest builds present' do
before do
create(:ci_build, name: 'test:build',
stage: stage.name,
pipeline: pipeline)
end
it 'shows the builds in the stage' do
render
expect(rendered).to have_text 'test:build'
end
end
context 'when build belongs to different stage' do
before do
create(:ci_build, name: 'test:build',
stage: 'other:stage',
pipeline: pipeline)
end
it 'does not render build' do
render
expect(rendered).not_to have_text 'test:build'
end
end
context 'when there are retried builds present' do
before do
create(:ci_build, name: 'test:build', stage: stage.name, pipeline: pipeline, retried: true)
create(:ci_build, name: 'test:build', stage: stage.name, pipeline: pipeline)
end
it 'shows only latest builds' do
render
expect(rendered).to have_text 'test:build', count: 1
end
end
context 'when there are multiple builds' do
before do
Ci::HasStatus::AVAILABLE_STATUSES.each do |status|
create_build(status)
end
end
it 'shows them in order' do
render
expect(rendered).to have_text(Ci::HasStatus::ORDERED_STATUSES.join(" "))
end
def create_build(status)
create(:ci_build, name: status, status: status,
pipeline: pipeline, stage: stage.name)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment