diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue index 8482234c7b1241412ad0c6f4722a1f7cbf6c0774..4e580c88ef3760c0f5e2cd180a9064389407ee90 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue @@ -5,6 +5,7 @@ import { normalizeHeaders } from '~/lib/utils/common_utils'; import { sprintf, __ } from '~/locale'; import Poll from '~/lib/utils/poll'; import StatusIcon from '../extensions/status_icon.vue'; +import ActionButtons from '../action_buttons.vue'; import { EXTENSION_ICONS } from '../../constants'; const FETCH_TYPE_COLLAPSED = 'collapsed'; @@ -12,6 +13,7 @@ const FETCH_TYPE_EXPANDED = 'expanded'; export default { components: { + ActionButtons, StatusIcon, GlButton, GlLoadingIcon, @@ -74,6 +76,11 @@ export default { type: Boolean, required: true, }, + actionButtons: { + type: Array, + required: false, + default: () => [], + }, widgetName: { type: String, required: true, @@ -181,6 +188,11 @@ export default { <slot v-if="!error" name="summary">{{ isLoading ? loadingText : summary }}</slot> <span v-else>{{ error }}</span> </div> + <action-buttons + v-if="actionButtons.length > 0" + :widget="widgetName" + :tertiary-buttons="actionButtons" + /> <div v-if="isCollapsible" class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6" diff --git a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js index b5721b6644d22fc5cc96f0aa3e520a7e242b8ef9..049e5bcce92f9621e652249b411c5032a3801d25 100644 --- a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js +++ b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js @@ -3,6 +3,7 @@ import * as Sentry from '@sentry/browser'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue'; +import ActionButtons from '~/vue_merge_request_widget/components/action_buttons.vue'; import Widget from '~/vue_merge_request_widget/components/widget/widget.vue'; describe('MR Widget', () => { @@ -10,6 +11,7 @@ describe('MR Widget', () => { const findStatusIcon = () => wrapper.findComponent(StatusIcon); const findExpandedSection = () => wrapper.findByTestId('widget-extension-collapsed-section'); + const findActionButtons = () => wrapper.findComponent(ActionButtons); const findToggleButton = () => wrapper.findByTestId('toggle-button'); const createComponent = ({ propsData, slots } = {}) => { @@ -152,6 +154,29 @@ describe('MR Widget', () => { 'More complex summary', ); }); + + it('does not display action buttons if actionButtons is not provided', () => { + createComponent({ + propsData: { + fetchCollapsedData: () => Promise.resolve(), + }, + }); + + expect(findActionButtons().exists()).toBe(false); + }); + + it('does display action buttons if actionButtons is provided', () => { + const actionButtons = [{ text: 'click-me', href: '#' }]; + + createComponent({ + propsData: { + fetchCollapsedData: () => Promise.resolve(), + actionButtons, + }, + }); + + expect(findActionButtons().props('tertiaryButtons')).toEqual(actionButtons); + }); }); describe('handle collapse toggle', () => {