Commit ca6cef2e authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '299902-remove-jquery-reference-from-stage-vue' into 'master'

Implement mini graph pipeline to use gl-dropdown [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!52821
parents 6acc8ef6 85f7fb65
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
* 3. Merge request widget * 3. Merge request widget
* 4. Commit widget * 4. Commit widget
*/ */
import $ from 'jquery'; import $ from 'jquery';
import { GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { GlDropdown, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash'; import { deprecatedCreateFlash as Flash } from '~/flash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
import JobItem from '../graph/job_item.vue'; import JobItem from '../graph/job_item.vue';
...@@ -24,14 +24,14 @@ import { PIPELINES_TABLE } from '../../constants'; ...@@ -24,14 +24,14 @@ import { PIPELINES_TABLE } from '../../constants';
export default { export default {
components: { components: {
GlIcon, GlIcon,
JobItem,
GlLoadingIcon, GlLoadingIcon,
GlDropdown,
JobItem,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
stage: { stage: {
type: Object, type: Object,
...@@ -50,30 +50,25 @@ export default { ...@@ -50,30 +50,25 @@ export default {
default: '', default: '',
}, },
}, },
data() { data() {
return { return {
isLoading: false, isLoading: false,
dropdownContent: '', dropdownContent: [],
}; };
}, },
computed: { computed: {
dropdownClass() { isCiMiniPipelineGlDropdown() {
return this.dropdownContent.length > 0 // Feature flag ci_mini_pipeline_gl_dropdown
? 'js-builds-dropdown-container' // See more at https://gitlab.com/gitlab-org/gitlab/-/issues/300400
: 'js-builds-dropdown-loading'; return this.glFeatures?.ciMiniPipelineGlDropdown;
}, },
triggerButtonClass() { triggerButtonClass() {
return `ci-status-icon-${this.stage.status.group}`; return `ci-status-icon-${this.stage.status.group}`;
}, },
borderlessIcon() { borderlessIcon() {
return `${this.stage.status.icon}_borderless`; return `${this.stage.status.icon}_borderless`;
}, },
}, },
watch: { watch: {
updateDropdown() { updateDropdown() {
if (this.updateDropdown && this.isDropdownOpen() && !this.isLoading) { if (this.updateDropdown && this.isDropdownOpen() && !this.isLoading) {
...@@ -81,14 +76,17 @@ export default { ...@@ -81,14 +76,17 @@ export default {
} }
}, },
}, },
updated() { updated() {
if (this.dropdownContent.length > 0) { if (!this.isCiMiniPipelineGlDropdown && this.dropdownContent.length) {
this.stopDropdownClickPropagation(); this.stopDropdownClickPropagation();
} }
}, },
methods: { methods: {
onShowDropdown() {
eventHub.$emit('clickedDropdown');
this.isLoading = true;
this.fetchJobs();
},
onClickStage() { onClickStage() {
if (!this.isDropdownOpen()) { if (!this.isDropdownOpen()) {
eventHub.$emit('clickedDropdown'); eventHub.$emit('clickedDropdown');
...@@ -96,7 +94,6 @@ export default { ...@@ -96,7 +94,6 @@ export default {
this.fetchJobs(); this.fetchJobs();
} }
}, },
fetchJobs() { fetchJobs() {
axios axios
.get(this.stage.dropdown_path) .get(this.stage.dropdown_path)
...@@ -105,13 +102,16 @@ export default { ...@@ -105,13 +102,16 @@ export default {
this.isLoading = false; this.isLoading = false;
}) })
.catch(() => { .catch(() => {
if (this.isCiMiniPipelineGlDropdown) {
this.$refs.stageGlDropdown.hide();
} else {
this.closeDropdown(); this.closeDropdown();
}
this.isLoading = false; this.isLoading = false;
Flash(__('Something went wrong on our end.')); Flash(__('Something went wrong on our end.'));
}); });
}, },
/** /**
* When the user right clicks or cmd/ctrl + click in the job name * 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, * the dropdown should not be closed and the link should open in another tab,
...@@ -119,6 +119,8 @@ export default { ...@@ -119,6 +119,8 @@ export default {
* *
* Since this component is rendered multiple times per page we need to guarantee we only * Since this component is rendered multiple times per page we need to guarantee we only
* target the click event of this component. * target the click event of this component.
*
* Note: This should be removed once ci_mini_pipeline_gl_dropdown FF is removed as true.
*/ */
stopDropdownClickPropagation() { stopDropdownClickPropagation() {
$( $(
...@@ -128,23 +130,24 @@ export default { ...@@ -128,23 +130,24 @@ export default {
e.stopPropagation(); e.stopPropagation();
}); });
}, },
closeDropdown() { closeDropdown() {
if (this.isDropdownOpen()) { if (this.isDropdownOpen()) {
$(this.$refs.dropdown).dropdown('toggle'); $(this.$refs.dropdown).dropdown('toggle');
} }
}, },
isDropdownOpen() { isDropdownOpen() {
return this.$el.classList.contains('show'); return this.$el.classList.contains('show');
}, },
pipelineActionRequestComplete() { pipelineActionRequestComplete() {
if (this.type === PIPELINES_TABLE) { if (this.type === PIPELINES_TABLE) {
// warn the table to update // warn the table to update
eventHub.$emit('refreshPipelinesTable'); eventHub.$emit('refreshPipelinesTable');
} else { return;
}
// close the dropdown in mr widget // close the dropdown in mr widget
if (this.isCiMiniPipelineGlDropdown) {
this.$refs.stageGlDropdown.hide();
} else {
$(this.$refs.dropdown).dropdown('toggle'); $(this.$refs.dropdown).dropdown('toggle');
} }
}, },
...@@ -154,6 +157,42 @@ export default { ...@@ -154,6 +157,42 @@ export default {
<template> <template>
<div class="dropdown"> <div class="dropdown">
<gl-dropdown
v-if="isCiMiniPipelineGlDropdown"
ref="stageGlDropdown"
v-gl-tooltip.hover
data-testid="mini-pipeline-graph-dropdown"
:title="stage.title"
variant="link"
:lazy="true"
:popper-opts="{ placement: 'bottom' }"
:toggle-class="['mini-pipeline-graph-gl-dropdown-toggle', triggerButtonClass]"
menu-class="mini-pipeline-graph-dropdown-menu"
@show="onShowDropdown"
>
<template #button-content>
<span class="gl-pointer-events-none">
<gl-icon :name="borderlessIcon" />
</span>
</template>
<gl-loading-icon v-if="isLoading" />
<ul
v-else
class="js-builds-dropdown-list scrollable-menu"
data-testid="mini-pipeline-graph-dropdown-menu-list"
>
<li v-for="job in dropdownContent" :key="job.id">
<job-item
:dropdown-length="dropdownContent.length"
:job="job"
css-class-job-name="mini-pipeline-graph-dropdown-item"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
</li>
</ul>
</gl-dropdown>
<template v-else>
<button <button
id="stageDropdown" id="stageDropdown"
ref="dropdown" ref="dropdown"
...@@ -190,5 +229,6 @@ export default { ...@@ -190,5 +229,6 @@ export default {
</li> </li>
</ul> </ul>
</div> </div>
</template>
</div> </div>
</template> </template>
...@@ -67,7 +67,8 @@ ...@@ -67,7 +67,8 @@
// Mini Pipelines // Mini Pipelines
.stage-cell { .stage-cell {
.mini-pipeline-graph-dropdown-toggle { .mini-pipeline-graph-dropdown-toggle,
.mini-pipeline-graph-gl-dropdown-toggle {
svg { svg {
height: $ci-action-icon-size; height: $ci-action-icon-size;
width: $ci-action-icon-size; width: $ci-action-icon-size;
...@@ -138,7 +139,13 @@ ...@@ -138,7 +139,13 @@
} }
// Dropdown button in mini pipeline graph // Dropdown button in mini pipeline graph
button.mini-pipeline-graph-dropdown-toggle { button.mini-pipeline-graph-dropdown-toggle,
// As the `mini-pipeline-item` mixin specificity is lower
// than the toggle of dropdown with 'variant="link"' we add
// classes ".gl-button.btn-link" to make it more specific.
// Once FF ci_mini_pipeline_gl_dropdown is removed, the `mini-pipeline-item`
// itself could increase its specificity to simplify this selector
button.gl-button.btn-link.mini-pipeline-graph-gl-dropdown-toggle {
@include mini-pipeline-item(); @include mini-pipeline-item();
} }
......
...@@ -18,6 +18,9 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -18,6 +18,9 @@ class Projects::CommitController < Projects::ApplicationController
before_action :define_commit_vars, only: [:show, :diff_for_path, :diff_files, :pipelines, :merge_requests] before_action :define_commit_vars, only: [:show, :diff_for_path, :diff_files, :pipelines, :merge_requests]
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: [:pipelines] do
push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, @project, type: :development, default_enabled: :yaml)
end
BRANCH_SEARCH_LIMIT = 1000 BRANCH_SEARCH_LIMIT = 1000
......
...@@ -45,6 +45,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -45,6 +45,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:suggestions_custom_commit, @project) push_frontend_feature_flag(:suggestions_custom_commit, @project)
push_frontend_feature_flag(:local_file_reviews, default_enabled: :yaml) push_frontend_feature_flag(:local_file_reviews, default_enabled: :yaml)
push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml) push_frontend_feature_flag(:paginated_notes, @project, default_enabled: :yaml)
push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, @project, type: :development, default_enabled: :yaml)
record_experiment_user(:invite_members_version_a) record_experiment_user(:invite_members_version_a)
record_experiment_user(:invite_members_version_b) record_experiment_user(:invite_members_version_b)
......
...@@ -16,6 +16,7 @@ class Projects::PipelinesController < Projects::ApplicationController ...@@ -16,6 +16,7 @@ class Projects::PipelinesController < Projects::ApplicationController
push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: true) push_frontend_feature_flag(:new_pipeline_form, project, default_enabled: true)
push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml) push_frontend_feature_flag(:graphql_pipeline_details, project, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml) push_frontend_feature_flag(:graphql_pipeline_details_users, current_user, type: :development, default_enabled: :yaml)
push_frontend_feature_flag(:ci_mini_pipeline_gl_dropdown, project, type: :development, default_enabled: :yaml)
end end
before_action :ensure_pipeline, only: [:show] before_action :ensure_pipeline, only: [:show]
before_action :push_experiment_to_gon, only: :index, if: :html_request? before_action :push_experiment_to_gon, only: :index, if: :html_request?
......
---
name: ci_mini_pipeline_gl_dropdown
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52821
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/300400
milestone: '13.9'
type: development
group: group::continuous integration
default_enabled: false
...@@ -18,6 +18,7 @@ RSpec.describe 'User adds a merge request to a merge train', :js do ...@@ -18,6 +18,7 @@ RSpec.describe 'User adds a merge request to a merge train', :js do
before do before do
stub_feature_flags(disable_merge_trains: false) stub_feature_flags(disable_merge_trains: false)
stub_feature_flags(ci_mini_pipeline_gl_dropdown: false)
stub_licensed_features(merge_pipelines: true, merge_trains: true) stub_licensed_features(merge_pipelines: true, merge_trains: true)
project.add_maintainer(user) project.add_maintainer(user)
project.update!(merge_pipelines_enabled: true, merge_trains_enabled: true) project.update!(merge_pipelines_enabled: true, merge_trains_enabled: true)
......
...@@ -9,15 +9,23 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do ...@@ -9,15 +9,23 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: 'master', status: 'running', sha: project.commit.id) } let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: 'master', status: 'running', sha: project.commit.id) }
let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test') } let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test') }
dropdown_toggle_selector = '[data-testid="mini-pipeline-graph-dropdown-toggle"]' shared_examples 'mini pipeline renders' do |ci_mini_pipeline_gl_dropdown_enabled|
before do before do
build.run build.run
build.trace.set('hello') build.trace.set('hello')
sign_in(user) sign_in(user)
stub_feature_flags(ci_mini_pipeline_gl_dropdown: ci_mini_pipeline_gl_dropdown_enabled)
visit_merge_request visit_merge_request
end end
let_it_be(:dropdown_toggle_selector) do
if ci_mini_pipeline_gl_dropdown_enabled
'[data-testid="mini-pipeline-graph-dropdown"] .dropdown-toggle'
else
'[data-testid="mini-pipeline-graph-dropdown-toggle"]'
end
end
def visit_merge_request(format: :html, serializer: nil) def visit_merge_request(format: :html, serializer: nil)
visit project_merge_request_path(project, merge_request, format: format, serializer: serializer) visit project_merge_request_path(project, merge_request, format: format, serializer: serializer)
end end
...@@ -67,10 +75,9 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do ...@@ -67,10 +75,9 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
page.driver.browser.action.click_and_hold(toggle.native).perform page.driver.browser.action.click_and_hold(toggle.native).perform
active_background_color, active_foreground_color, active_box_shadow = get_toggle_colors(dropdown_toggle_selector) active_background_color, active_foreground_color, active_box_shadow = get_toggle_colors(dropdown_toggle_selector)
page.driver.browser.action.release(toggle.native).perform
page.driver.browser.action.release(toggle.native) page.driver.browser.action.click(toggle.native).move_by(100, 100).perform
.move_by(100, 100)
.perform
focus_background_color, focus_foreground_color, focus_box_shadow = get_toggle_colors(dropdown_toggle_selector) focus_background_color, focus_foreground_color, focus_box_shadow = get_toggle_colors(dropdown_toggle_selector)
expect(default_background_color).not_to eq(hover_background_color) expect(default_background_color).not_to eq(hover_background_color)
...@@ -144,6 +151,15 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do ...@@ -144,6 +151,15 @@ RSpec.describe 'Merge request < User sees mini pipeline graph', :js do
end end
end end
end end
end
context 'with ci_mini_pipeline_gl_dropdown disabled' do
it_behaves_like "mini pipeline renders", false
end
context 'with ci_mini_pipeline_gl_dropdown enabled' do
it_behaves_like "mini pipeline renders", true
end
private private
......
...@@ -518,6 +518,7 @@ RSpec.describe 'Pipelines', :js do ...@@ -518,6 +518,7 @@ RSpec.describe 'Pipelines', :js do
end end
end end
shared_examples 'mini pipeline renders' do |ci_mini_pipeline_gl_dropdown_enabled|
context 'mini pipeline graph' do context 'mini pipeline graph' do
let!(:build) do let!(:build) do
create(:ci_build, :pending, pipeline: pipeline, create(:ci_build, :pending, pipeline: pipeline,
...@@ -525,12 +526,19 @@ RSpec.describe 'Pipelines', :js do ...@@ -525,12 +526,19 @@ RSpec.describe 'Pipelines', :js do
name: 'build') name: 'build')
end end
dropdown_toggle_selector = '[data-testid="mini-pipeline-graph-dropdown-toggle"]'
before do before do
stub_feature_flags(ci_mini_pipeline_gl_dropdown: ci_mini_pipeline_gl_dropdown_enabled)
visit_project_pipelines visit_project_pipelines
end end
let_it_be(:dropdown_toggle_selector) do
if ci_mini_pipeline_gl_dropdown_enabled
'[data-testid="mini-pipeline-graph-dropdown"] .dropdown-toggle'
else
'[data-testid="mini-pipeline-graph-dropdown-toggle"]'
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="widget-mini-pipeline-graph"]')
expect(page).to have_selector(dropdown_toggle_selector) expect(page).to have_selector(dropdown_toggle_selector)
...@@ -569,6 +577,15 @@ RSpec.describe 'Pipelines', :js do ...@@ -569,6 +577,15 @@ RSpec.describe 'Pipelines', :js do
end end
end end
end end
end
context 'with ci_mini_pipeline_gl_dropdown disabled' do
it_behaves_like "mini pipeline renders", false
end
context 'with ci_mini_pipeline_gl_dropdown enabled' do
it_behaves_like "mini pipeline renders", true
end
context 'with pagination' do context 'with pagination' do
before do before do
......
import 'bootstrap/js/dist/dropdown'; import 'bootstrap/js/dist/dropdown';
import $ from 'jquery';
import { GlDropdown } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
...@@ -9,6 +11,7 @@ import { stageReply } from './mock_data'; ...@@ -9,6 +11,7 @@ import { stageReply } from './mock_data';
describe('Pipelines stage component', () => { describe('Pipelines stage component', () => {
let wrapper; let wrapper;
let mock; let mock;
let glFeatures;
const defaultProps = { const defaultProps = {
stage: { stage: {
...@@ -22,8 +25,6 @@ describe('Pipelines stage component', () => { ...@@ -22,8 +25,6 @@ describe('Pipelines stage component', () => {
updateDropdown: false, updateDropdown: false,
}; };
const isDropdownOpen = () => wrapper.classes('show');
const createComponent = (props = {}) => { const createComponent = (props = {}) => {
wrapper = mount(StageComponent, { wrapper = mount(StageComponent, {
attachTo: document.body, attachTo: document.body,
...@@ -31,20 +32,29 @@ describe('Pipelines stage component', () => { ...@@ -31,20 +32,29 @@ describe('Pipelines stage component', () => {
...defaultProps, ...defaultProps,
...props, ...props,
}, },
provide: {
glFeatures,
},
}); });
}; };
beforeEach(() => { beforeEach(() => {
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
jest.spyOn(eventHub, '$emit');
glFeatures = {};
}); });
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
eventHub.$emit.mockRestore();
mock.restore(); mock.restore();
}); });
describe('when ci_mini_pipeline_gl_dropdown feature flag is disabled', () => {
const isDropdownOpen = () => wrapper.classes('show');
describe('default', () => { describe('default', () => {
beforeEach(() => { beforeEach(() => {
createComponent(); createComponent();
...@@ -64,7 +74,6 @@ describe('Pipelines stage component', () => { ...@@ -64,7 +74,6 @@ describe('Pipelines stage component', () => {
}); });
it('should render the received data and emit `clickedDropdown` event', async () => { it('should render the received data and emit `clickedDropdown` event', async () => {
jest.spyOn(eventHub, '$emit');
wrapper.find('button').trigger('click'); wrapper.find('button').trigger('click');
await axios.waitForAll(); await axios.waitForAll();
...@@ -80,6 +89,7 @@ describe('Pipelines stage component', () => { ...@@ -80,6 +89,7 @@ describe('Pipelines stage component', () => {
mock.onGet('path.json').reply(500); mock.onGet('path.json').reply(500);
createComponent(); createComponent();
wrapper.find({ ref: 'dropdown' }).trigger('click'); wrapper.find({ ref: 'dropdown' }).trigger('click');
expect(isDropdownOpen()).toBe(true); expect(isDropdownOpen()).toBe(true);
wrapper.find('button').trigger('click'); wrapper.find('button').trigger('click');
...@@ -120,22 +130,168 @@ describe('Pipelines stage component', () => { ...@@ -120,22 +130,168 @@ describe('Pipelines stage component', () => {
beforeEach(() => { beforeEach(() => {
mock.onGet('path.json').reply(200, stageReply); mock.onGet('path.json').reply(200, stageReply);
mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200); mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
createComponent({ type: 'PIPELINES_TABLE' });
}); });
const clickCiAction = async () => {
wrapper.find('button').trigger('click');
await axios.waitForAll();
wrapper.find('.js-ci-action').trigger('click');
await axios.waitForAll();
};
describe('within pipeline table', () => { describe('within pipeline table', () => {
it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => { it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => {
jest.spyOn(eventHub, '$emit'); createComponent({ type: 'PIPELINES_TABLE' });
wrapper.find('button').trigger('click'); await clickCiAction();
expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
});
});
describe('in MR widget', () => {
beforeEach(() => {
jest.spyOn($.fn, 'dropdown');
});
it('closes the dropdown when `pipelineActionRequestComplete` is triggered', async () => {
createComponent();
await clickCiAction();
expect($.fn.dropdown).toHaveBeenCalledWith('toggle');
});
});
});
});
describe('when ci_mini_pipeline_gl_dropdown feature flag is enabled', () => {
const findDropdown = () => wrapper.find(GlDropdown);
const findDropdownToggle = () => wrapper.find('button.gl-dropdown-toggle');
const findDropdownMenu = () =>
wrapper.find('[data-testid="mini-pipeline-graph-dropdown-menu-list"]');
const findCiActionBtn = () => wrapper.find('.js-ci-action');
const openGlDropdown = () => {
findDropdownToggle().trigger('click');
return new Promise((resolve) => {
wrapper.vm.$root.$on('bv::dropdown::show', resolve);
});
};
beforeEach(() => {
glFeatures = { ciMiniPipelineGlDropdown: true };
});
describe('default', () => {
beforeEach(() => {
createComponent();
});
it('should render a dropdown with the status icon', () => {
expect(findDropdown().exists()).toBe(true);
expect(findDropdownToggle().classes('gl-dropdown-toggle')).toEqual(true);
expect(wrapper.find('[data-testid="status_success_borderless-icon"]').exists()).toBe(true);
});
});
describe('with successful request', () => {
beforeEach(() => {
mock.onGet('path.json').reply(200, stageReply);
createComponent();
});
it('should render the received data and emit `clickedDropdown` event', async () => {
await openGlDropdown();
await axios.waitForAll(); await axios.waitForAll();
wrapper.find('.js-ci-action').trigger('click'); expect(findDropdownMenu().text()).toContain(stageReply.latest_statuses[0].name);
expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
});
});
it('when request fails should close the dropdown', async () => {
mock.onGet('path.json').reply(500);
createComponent();
await openGlDropdown();
await axios.waitForAll();
expect(findDropdown().classes('show')).toBe(false);
});
describe('update endpoint correctly', () => {
beforeEach(async () => {
const copyStage = { ...stageReply };
copyStage.latest_statuses[0].name = 'this is the updated content';
mock.onGet('bar.json').reply(200, copyStage);
createComponent({
stage: {
status: {
group: 'running',
icon: 'status_running',
title: 'running',
},
dropdown_path: 'bar.json',
},
});
await axios.waitForAll();
});
it('should update the stage to request the new endpoint provided', async () => {
await openGlDropdown();
await axios.waitForAll();
expect(findDropdownMenu().text()).toContain('this is the updated content');
});
});
describe('pipelineActionRequestComplete', () => {
beforeEach(() => {
mock.onGet('path.json').reply(200, stageReply);
mock.onPost(`${stageReply.latest_statuses[0].status.action.path}.json`).reply(200);
});
const clickCiAction = async () => {
await openGlDropdown();
await axios.waitForAll();
findCiActionBtn().trigger('click');
await axios.waitForAll(); await axios.waitForAll();
};
describe('within pipeline table', () => {
beforeEach(() => {
createComponent({ type: 'PIPELINES_TABLE' });
});
it('emits `refreshPipelinesTable` event when `pipelineActionRequestComplete` is triggered', async () => {
await clickCiAction();
expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable'); expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
}); });
}); });
describe('in MR widget', () => {
beforeEach(() => {
jest.spyOn($.fn, 'dropdown');
createComponent();
});
it('closes the dropdown when `pipelineActionRequestComplete` is triggered', async () => {
const hidden = jest.fn();
wrapper.vm.$root.$on('bv::dropdown::hide', hidden);
expect(hidden).toHaveBeenCalledTimes(0);
await clickCiAction();
expect(hidden).toHaveBeenCalledTimes(1);
});
});
});
}); });
}); });
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