diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
index 806f8f939a6c4933c30183800de74733fe6c6c6a..6bcf88713a52d1487749f0075db5b5c6e12251d5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
@@ -1,7 +1,17 @@
-
+
({
+ updateMergeRequest: jest.fn(),
+}));
+jest.mock('~/vue_shared/plugins/global_toast');
+
+useMockLocationHelper();
const MOCK_DATA = {
+ iid: 1,
metrics: {
mergedBy: {},
closedBy: {
@@ -19,22 +38,39 @@ const MOCK_DATA = {
},
targetBranchPath: '/twitter/flight/commits/so_long_jquery',
targetBranch: 'so_long_jquery',
+ targetProjectId: 'twitter/flight',
};
+function createComponent({ shallow = true, props = {} } = {}) {
+ const mounter = shallow ? shallowMount : mount;
+
+ return mounter(closedComponent, {
+ propsData: {
+ mr: MOCK_DATA,
+ ...props,
+ },
+ });
+}
+
+function findActions(wrapper) {
+ return wrapper.findComponent(StateContainer).findComponent(Actions);
+}
+
+function findReopenActionButton(wrapper) {
+ return findActions(wrapper).find('button[data-testid="extension-actions-reopen-button"]');
+}
+
describe('MRWidgetClosed', () => {
let wrapper;
beforeEach(() => {
- wrapper = shallowMount(closedComponent, {
- propsData: {
- mr: MOCK_DATA,
- },
- });
+ wrapper = createComponent();
});
afterEach(() => {
- wrapper.destroy();
- wrapper = null;
+ if (wrapper) {
+ wrapper.destroy();
+ }
});
it('renders closed icon', () => {
@@ -51,4 +87,93 @@ describe('MRWidgetClosed', () => {
dateReadable: MOCK_DATA.metrics.readableClosedAt,
});
});
+
+ describe('actions', () => {
+ describe('reopen', () => {
+ beforeEach(() => {
+ window.gon = { current_user_id: 1 };
+ api.updateMergeRequest.mockResolvedValue(true);
+ wrapper = createComponent({ shallow: false });
+ });
+
+ it('shows the "reopen" button', () => {
+ expect(wrapper.findComponent(StateContainer).props().actions.length).toBe(1);
+ expect(findReopenActionButton(wrapper).text()).toBe('Reopen');
+ });
+
+ it('does not show widget actions when the user is not logged in', () => {
+ window.gon = {};
+
+ wrapper = createComponent();
+
+ expect(findActions(wrapper).exists()).toBe(false);
+ });
+
+ it('makes the reopen request with the correct MR information', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ reopenButton.trigger('click');
+ await nextTick();
+
+ expect(api.updateMergeRequest).toHaveBeenCalledWith(
+ MOCK_DATA.targetProjectId,
+ MOCK_DATA.iid,
+ { state_event: 'reopen' },
+ );
+ });
+
+ it('shows "Reopening..." while the reopen network request is pending', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ api.updateMergeRequest.mockReturnValue(new Promise(() => {}));
+
+ reopenButton.trigger('click');
+ await nextTick();
+
+ expect(reopenButton.text()).toBe('Reopening...');
+ });
+
+ it('shows "Refreshing..." when the reopen has succeeded', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(reopenButton.text()).toBe('Refreshing...');
+ });
+
+ it('reloads the page when a reopen has succeeded', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(window.location.reload).toHaveBeenCalledTimes(1);
+ });
+
+ it('shows "Reopen" when a reopen request has failed', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ api.updateMergeRequest.mockRejectedValue(false);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(window.location.reload).not.toHaveBeenCalled();
+ expect(reopenButton.text()).toBe('Reopen');
+ });
+
+ it('requests a toast popup when a reopen request has failed', async () => {
+ const reopenButton = findReopenActionButton(wrapper);
+
+ api.updateMergeRequest.mockRejectedValue(false);
+
+ reopenButton.trigger('click');
+ await waitForPromises();
+
+ expect(showGlobalToast).toHaveBeenCalledTimes(1);
+ expect(showGlobalToast).toHaveBeenCalledWith(MR_WIDGET_CLOSED_REOPEN_FAILURE);
+ });
+ });
+ });
});