Commit 4c938b8c authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Merge branch 'afontaine/environments-graphql-stop' into 'master'

Make Environment Stop work with GraphQL

See merge request gitlab-org/gitlab!76886
parents 4044ef15 aced918d
......@@ -8,6 +8,8 @@ import { GlTooltipDirective, GlButton, GlModalDirective } from '@gitlab/ui';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
import setEnvironmentToStopMutation from '../graphql/mutations/set_environment_to_stop.mutation.graphql';
import isEnvironmentStoppingQuery from '../graphql/queries/is_environment_stopping.query.graphql';
export default {
components: {
......@@ -22,6 +24,19 @@ export default {
type: Object,
required: true,
},
graphql: {
type: Boolean,
required: false,
default: false,
},
},
apollo: {
isEnvironmentStopping: {
query: isEnvironmentStoppingQuery,
variables() {
return { environment: this.environment };
},
},
},
i18n: {
title: s__('Environments|Stop environment'),
......@@ -30,6 +45,7 @@ export default {
data() {
return {
isLoading: false,
isEnvironmentStopping: false,
};
},
mounted() {
......@@ -41,7 +57,14 @@ export default {
methods: {
onClick() {
this.$root.$emit(BV_HIDE_TOOLTIP, this.$options.stopEnvironmentTooltipId);
eventHub.$emit('requestStopEnvironment', this.environment);
if (this.graphql) {
this.$apollo.mutate({
mutation: setEnvironmentToStopMutation,
variables: { environment: this.environment },
});
} else {
eventHub.$emit('requestStopEnvironment', this.environment);
}
},
onStopEnvironment(environment) {
if (this.environment.id === environment.id) {
......@@ -56,7 +79,7 @@ export default {
<gl-button
v-gl-tooltip="{ id: $options.stopEnvironmentTooltipId }"
v-gl-modal-directive="'stop-environment-modal'"
:loading="isLoading"
:loading="isLoading || isEnvironmentStopping"
:title="$options.i18n.title"
:aria-label="$options.i18n.title"
icon="stop"
......
......@@ -5,8 +5,10 @@ import { updateHistory, setUrlParams, queryToObject } from '~/lib/utils/url_util
import environmentAppQuery from '../graphql/queries/environment_app.query.graphql';
import pollIntervalQuery from '../graphql/queries/poll_interval.query.graphql';
import pageInfoQuery from '../graphql/queries/page_info.query.graphql';
import environmentToStopQuery from '../graphql/queries/environment_to_stop.query.graphql';
import EnvironmentFolder from './new_environment_folder.vue';
import EnableReviewAppModal from './enable_review_app_modal.vue';
import StopEnvironmentModal from './stop_environment_modal.vue';
export default {
components: {
......@@ -16,6 +18,7 @@ export default {
GlPagination,
GlTab,
GlTabs,
StopEnvironmentModal,
},
apollo: {
environmentApp: {
......@@ -36,6 +39,9 @@ export default {
pageInfo: {
query: pageInfoQuery,
},
environmentToStop: {
query: environmentToStopQuery,
},
},
inject: ['newEnvironmentPath', 'canCreateEnvironment'],
i18n: {
......@@ -57,6 +63,7 @@ export default {
isReviewAppModalVisible: false,
page: parseInt(page, 10),
scope,
environmentToStop: {},
};
},
computed: {
......@@ -157,6 +164,7 @@ export default {
:modal-id="$options.modalId"
data-testid="enable-review-app-modal"
/>
<stop-environment-modal :environment="environmentToStop" graphql />
<gl-tabs
:action-secondary="addEnvironment"
:action-primary="openReviewAppModal"
......
......@@ -2,6 +2,7 @@
import { GlSprintf, GlTooltipDirective, GlModal } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import eventHub from '../event_hub';
import stopEnvironmentMutation from '../graphql/mutations/stop_environment.mutation.graphql';
export default {
id: 'stop-environment-modal',
......@@ -21,6 +22,11 @@ export default {
type: Object,
required: true,
},
graphql: {
type: Boolean,
required: false,
default: false,
},
},
computed: {
......@@ -39,7 +45,14 @@ export default {
methods: {
onSubmit() {
eventHub.$emit('stopEnvironment', this.environment);
if (this.graphql) {
this.$apollo.mutate({
mutation: stopEnvironmentMutation,
variables: { environment: this.environment },
});
} else {
eventHub.$emit('stopEnvironment', this.environment);
}
},
},
};
......
mutation SetEnvironmentToStop($environment: LocalEnvironmentInput) {
setEnvironmentToStop(environment: $environment) @client
}
query isEnvironmentStopping($environment: LocalEnvironment) {
isEnvironmentStopping(environment: $environment) @client
}
......@@ -8,6 +8,7 @@ import {
import pollIntervalQuery from './queries/poll_interval.query.graphql';
import environmentToRollbackQuery from './queries/environment_to_rollback.query.graphql';
import environmentToStopQuery from './queries/environment_to_stop.query.graphql';
import environmentToDeleteQuery from './queries/environment_to_delete.query.graphql';
import pageInfoQuery from './queries/page_info.query.graphql';
......@@ -108,6 +109,12 @@ export const resolvers = (endpoint) => ({
]);
});
},
setEnvironmentToStop(_, { environment }, { client }) {
client.writeQuery({
query: environmentToStopQuery,
data: { environmentToStop: environment },
});
},
setEnvironmentToDelete(_, { environment }, { client }) {
client.writeQuery({
query: environmentToDeleteQuery,
......
......@@ -68,6 +68,8 @@ extend type Query {
environmentToDelete: LocalEnvironment
pageInfo: LocalPageInfo
environmentToRollback: LocalEnvironment
environmentToStop: LocalEnvironment
isEnvironmentStopping(environment: LocalEnvironmentInput): Boolean
isLastDeployment: Boolean
}
......@@ -78,4 +80,5 @@ extend type Mutation {
cancelAutoStop(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToDelete(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToRollback(environment: LocalEnvironmentInput): LocalErrors
setEnvironmentToStop(environment: LocalEnvironmentInput): LocalErrors
}
import { GlButton } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import $ from 'jquery';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import setEnvironmentToStopMutation from '~/environments/graphql/mutations/set_environment_to_stop.mutation.graphql';
import isEnvironmentStoppingQuery from '~/environments/graphql/queries/is_environment_stopping.query.graphql';
import StopComponent from '~/environments/components/environment_stop.vue';
import eventHub from '~/environments/event_hub';
$.fn.tooltip = () => {};
import createMockApollo from 'helpers/mock_apollo_helper';
import { resolvedEnvironment } from './graphql/mock_data';
describe('Stop Component', () => {
let wrapper;
const createWrapper = () => {
const createWrapper = (props = {}, options = {}) => {
wrapper = shallowMount(StopComponent, {
propsData: {
environment: {},
...props,
},
...options,
});
};
const findButton = () => wrapper.find(GlButton);
beforeEach(() => {
jest.spyOn(window, 'confirm');
describe('eventHub', () => {
beforeEach(() => {
createWrapper();
});
createWrapper();
});
it('should render a button to stop the environment', () => {
expect(findButton().exists()).toBe(true);
expect(wrapper.attributes('title')).toEqual('Stop environment');
});
it('should render a button to stop the environment', () => {
expect(findButton().exists()).toBe(true);
expect(wrapper.attributes('title')).toEqual('Stop environment');
it('emits requestStopEnvironment in the event hub when button is clicked', () => {
jest.spyOn(eventHub, '$emit');
findButton().vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('requestStopEnvironment', wrapper.vm.environment);
});
});
it('emits requestStopEnvironment in the event hub when button is clicked', () => {
jest.spyOn(eventHub, '$emit');
findButton().vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('requestStopEnvironment', wrapper.vm.environment);
describe('graphql', () => {
Vue.use(VueApollo);
let mockApollo;
beforeEach(() => {
mockApollo = createMockApollo();
mockApollo.clients.defaultClient.writeQuery({
query: isEnvironmentStoppingQuery,
variables: { environment: resolvedEnvironment },
data: { isEnvironmentStopping: true },
});
createWrapper(
{ graphql: true, environment: resolvedEnvironment },
{ apolloProvider: mockApollo },
);
});
it('should render a button to stop the environment', () => {
expect(findButton().exists()).toBe(true);
expect(wrapper.attributes('title')).toEqual('Stop environment');
});
it('sets the environment to stop on click', () => {
jest.spyOn(mockApollo.defaultClient, 'mutate');
findButton().vm.$emit('click');
expect(mockApollo.defaultClient.mutate).toHaveBeenCalledWith({
mutation: setEnvironmentToStopMutation,
variables: { environment: resolvedEnvironment },
});
});
it('should show a loading icon if the environment is currently stopping', async () => {
expect(findButton().props('loading')).toBe(true);
});
});
});
......@@ -3,6 +3,7 @@ import axios from '~/lib/utils/axios_utils';
import { resolvers } from '~/environments/graphql/resolvers';
import environmentToRollback from '~/environments/graphql/queries/environment_to_rollback.query.graphql';
import environmentToDelete from '~/environments/graphql/queries/environment_to_delete.query.graphql';
import environmentToStopQuery from '~/environments/graphql/queries/environment_to_stop.query.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
import pollIntervalQuery from '~/environments/graphql/queries/poll_interval.query.graphql';
import pageInfoQuery from '~/environments/graphql/queries/page_info.query.graphql';
......@@ -210,4 +211,19 @@ describe('~/frontend/environments/graphql/resolvers', () => {
});
});
});
describe('setEnvironmentToStop', () => {
it('should write the given environment to the cache', () => {
localState.client.writeQuery = jest.fn();
mockResolvers.Mutation.setEnvironmentToStop(
null,
{ environment: resolvedEnvironment },
localState,
);
expect(localState.client.writeQuery).toHaveBeenCalledWith({
query: environmentToStopQuery,
data: { environmentToStop: resolvedEnvironment },
});
});
});
});
......@@ -8,7 +8,8 @@ import setWindowLocation from 'helpers/set_window_location_helper';
import { sprintf, __, s__ } from '~/locale';
import EnvironmentsApp from '~/environments/components/new_environments_app.vue';
import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
import { resolvedEnvironmentsApp, resolvedFolder } from './graphql/mock_data';
import StopEnvironmentModal from '~/environments/components/stop_environment_modal.vue';
import { resolvedEnvironmentsApp, resolvedFolder, resolvedEnvironment } from './graphql/mock_data';
Vue.use(VueApollo);
......@@ -17,6 +18,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
let environmentAppMock;
let environmentFolderMock;
let paginationMock;
let environmentToStopMock;
const createApolloProvider = () => {
const mockResolvers = {
......@@ -24,6 +26,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentApp: environmentAppMock,
folder: environmentFolderMock,
pageInfo: paginationMock,
environmentToStop: environmentToStopMock,
},
};
......@@ -45,6 +48,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
provide = {},
environmentsApp,
folder,
environmentToStop = {},
pageInfo = {
total: 20,
perPage: 5,
......@@ -58,6 +62,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentAppMock.mockReturnValue(environmentsApp);
environmentFolderMock.mockReturnValue(folder);
paginationMock.mockReturnValue(pageInfo);
environmentToStopMock.mockReturnValue(environmentToStop);
const apolloProvider = createApolloProvider();
wrapper = createWrapper({ apolloProvider, provide });
......@@ -68,6 +73,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
beforeEach(() => {
environmentAppMock = jest.fn();
environmentFolderMock = jest.fn();
environmentToStopMock = jest.fn();
paginationMock = jest.fn();
});
......@@ -175,6 +181,20 @@ describe('~/environments/components/new_environments_app.vue', () => {
});
});
describe('modals', () => {
it('should pass the environment to stop to the stop environment modal', async () => {
await createWrapperWithMocked({
environmentsApp: resolvedEnvironmentsApp,
folder: resolvedFolder,
environmentToStop: resolvedEnvironment,
});
const modal = wrapper.findComponent(StopEnvironmentModal);
expect(modal.props('environment')).toMatchObject(resolvedEnvironment);
});
});
describe('pagination', () => {
it('should sync page from query params on load', async () => {
await createWrapperWithMocked({
......
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