Commit 26d9e350 authored by Andrew Fontaine's avatar Andrew Fontaine

Make Environment Actions work with GraphQL

The new environments page is built using local GraphQL state management,
and so the ability to actions environments needs to rely on it instead
of the event hub.

To ensure everything still works until I am ready to delete the old
environments page, the new opt-in graphql prop is added to enable this
functionality.
parent 1b6fd3e0
......@@ -3,6 +3,7 @@ import { GlDropdown, GlDropdownItem, GlIcon, GlLoadingIcon, GlTooltipDirective }
import { formatTime } from '~/lib/utils/datetime_utility';
import { __, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
import actionMutation from '../graphql/mutations/action.mutation.graphql';
export default {
directives: {
......@@ -20,6 +21,11 @@ export default {
required: false,
default: () => [],
},
graphql: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
......@@ -49,7 +55,11 @@ export default {
this.isLoading = true;
eventHub.$emit('postAction', { endpoint: action.playPath });
if (this.graphql) {
this.$apollo.mutate({ mutation: actionMutation, variables: { action } });
} else {
eventHub.$emit('postAction', { endpoint: action.playPath });
}
},
isActionDisabled(action) {
......
mutation action($action: LocalAction) {
action(action: $action) @client {
errors
}
}
......@@ -115,6 +115,14 @@ export const resolvers = (endpoint) => ({
data: { environmentToStop: environment },
});
},
action(_, { action: { playPath } }) {
return axios
.post(playPath)
.then(() => buildErrors())
.catch(() =>
buildErrors([s__('Environments|An error occurred while making the request.')]),
);
},
setEnvironmentToDelete(_, { environment }, { client }) {
client.writeQuery({
query: environmentToDeleteQuery,
......
......@@ -81,4 +81,5 @@ extend type Mutation {
setEnvironmentToDelete(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToRollback(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToStop(environment: LocalEnvironmentInput): LocalErrors
action(environment: LocalEnvironmentInput): LocalErrors
}
import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { TEST_HOST } from 'helpers/test_constants';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import EnvironmentActions from '~/environments/components/environment_actions.vue';
import eventHub from '~/environments/event_hub';
import actionMutation from '~/environments/graphql/mutations/action.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
const scheduledJobAction = {
name: 'scheduled action',
......@@ -25,12 +29,13 @@ describe('EnvironmentActions Component', () => {
const findEnvironmentActionsButton = () =>
wrapper.find('[data-testid="environment-actions-button"]');
function createComponent(props, { mountFn = shallowMount } = {}) {
function createComponent(props, { mountFn = shallowMount, options = {} } = {}) {
wrapper = mountFn(EnvironmentActions, {
propsData: { actions: [], ...props },
directives: {
GlTooltip: createMockDirective(),
},
...options,
});
}
......@@ -150,4 +155,32 @@ describe('EnvironmentActions Component', () => {
expect(findDropdownItem(expiredJobAction).text()).toContain('00:00:00');
});
});
describe('graphql', () => {
Vue.use(VueApollo);
const action = {
name: 'bar',
play_path: 'https://gitlab.com/play',
};
let mockApollo;
beforeEach(() => {
mockApollo = createMockApollo();
createComponent(
{ actions: [action], graphql: true },
{ options: { apolloProvider: mockApollo } },
);
});
it('should trigger a graphql mutation on click', () => {
jest.spyOn(mockApollo.defaultClient, 'mutate');
findDropdownItem(action).vm.$emit('click');
expect(mockApollo.defaultClient.mutate).toHaveBeenCalledWith({
mutation: actionMutation,
variables: { action },
});
});
});
});
import MockAdapter from 'axios-mock-adapter';
import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import { resolvers } from '~/environments/graphql/resolvers';
import environmentToRollback from '~/environments/graphql/queries/environment_to_rollback.query.graphql';
......@@ -226,4 +227,21 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
});
});
describe('action', () => {
it('should POST to the given path', async () => {
mock.onPost(ENDPOINT).reply(200);
const errors = await mockResolvers.Mutation.action(null, { action: { playPath: ENDPOINT } });
expect(errors).toEqual({ __typename: 'LocalEnvironmentErrors', errors: [] });
});
it('should return a nice error message on fail', async () => {
mock.onPost(ENDPOINT).reply(500);
const errors = await mockResolvers.Mutation.action(null, { action: { playPath: ENDPOINT } });
expect(errors).toEqual({
__typename: 'LocalEnvironmentErrors',
errors: [s__('Environments|An error occurred while making the request.')],
});
});
});
});
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