Commit b3eb65a8 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'afontaine/new-environment-alert' into 'master'

Show environment alerts on new environment design

See merge request gitlab-org/gitlab!79886
parents e70939b2 4be2bc9f
......@@ -40,6 +40,7 @@ export default {
Terminal,
TimeAgoTooltip,
Delete,
EnvironmentAlert: () => import('ee_component/environments/components/environment_alert.vue'),
},
directives: {
GlTooltip,
......@@ -97,6 +98,9 @@ export default {
hasDeployment() {
return Boolean(this.environment?.upcomingDeployment || this.environment?.lastDeployment);
},
hasOpenedAlert() {
return this.environment?.hasOpenedAlert;
},
actions() {
if (!this.lastDeployment) {
return [];
......@@ -319,6 +323,9 @@ export default {
class="gl-pl-4"
/>
</div>
<div v-if="hasOpenedAlert" class="gl-bg-gray-10 gl-md-px-7">
<environment-alert :environment="environment" class="gl-pl-4 gl-py-5" />
</div>
</gl-collapse>
</div>
</template>
......@@ -2,6 +2,9 @@ import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import environmentApp from './queries/environment_app.query.graphql';
import pageInfoQuery from './queries/page_info.query.graphql';
import environmentToDeleteQuery from './queries/environment_to_delete.query.graphql';
import environmentToRollbackQuery from './queries/environment_to_rollback.query.graphql';
import environmentToStopQuery from './queries/environment_to_stop.query.graphql';
import { resolvers } from './resolvers';
import typeDefs from './typedefs.graphql';
......@@ -33,6 +36,52 @@ export const apolloProvider = (endpoint) => {
},
},
});
cache.writeQuery({
query: environmentToDeleteQuery,
data: {
environmentToDelete: {
name: 'null',
__typename: 'LocalEnvironment',
id: '0',
deletePath: null,
folderPath: null,
retryUrl: null,
autoStopPath: null,
lastDeployment: null,
},
},
});
cache.writeQuery({
query: environmentToStopQuery,
data: {
environmentToStop: {
name: 'null',
__typename: 'LocalEnvironment',
id: '0',
deletePath: null,
folderPath: null,
retryUrl: null,
autoStopPath: null,
lastDeployment: null,
},
},
});
cache.writeQuery({
query: environmentToRollbackQuery,
data: {
environmentToRollback: {
name: 'null',
__typename: 'LocalEnvironment',
id: '0',
deletePath: null,
folderPath: null,
retryUrl: null,
autoStopPath: null,
lastDeployment: null,
},
},
});
return new VueApollo({
defaultClient,
});
......
import { mount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import EnvironmentAlert from 'ee/environments/components/environment_alert.vue';
import alertQuery from 'ee/environments/graphql/queries/environment.query.graphql';
import SeverityBadge from 'ee/vue_shared/security_reports/components/severity_badge.vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
Vue.use(VueApollo);
describe('Environment Alert', () => {
let wrapper;
let alertResolver;
const DEFAULT_PROVIDE = { projectPath: 'test-org/test' };
const DEFAULT_PROPS = { environment: { name: 'staging' } };
const factory = (props = {}, provide = {}) => {
const createApolloProvider = () => createMockApollo([[alertQuery, alertResolver]]);
const factory = async (props = {}, provide = {}) => {
const apolloProvider = createApolloProvider();
wrapper = mount(EnvironmentAlert, {
apolloProvider,
propsData: {
...DEFAULT_PROPS,
...props,
......@@ -18,12 +31,14 @@ describe('Environment Alert', () => {
...provide,
},
});
await waitForPromises();
};
const findSeverityBadge = () => wrapper.findComponent(SeverityBadge);
beforeEach(() => {
factory();
alertResolver = jest.fn();
});
afterEach(() => {
......@@ -32,21 +47,29 @@ describe('Environment Alert', () => {
});
describe('has alert', () => {
beforeEach(() => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
// eslint-disable-next-line no-restricted-syntax
wrapper.setData({
alert: {
severity: 'CRITICAL',
title: 'alert title',
prometheusAlert: { humanizedText: '>0.1% jest' },
detailsUrl: '/alert/details',
startedAt: new Date(),
beforeEach(async () => {
alertResolver.mockResolvedValue({
data: {
project: {
id: '1',
environment: {
id: '2',
latestOpenedMostSevereAlert: {
severity: 'CRITICAL',
title: 'alert title',
prometheusAlert: { id: '3', humanizedText: '>0.1% jest' },
detailsUrl: '/alert/details',
startedAt: new Date(),
},
},
},
},
});
await factory();
});
it('should display the alert details', () => {
it('should display the alert details', async () => {
const text = wrapper.text();
expect(text).toContain('Critical');
expect(text).toContain('alert title >0.1% jest.');
......@@ -68,6 +91,21 @@ describe('Environment Alert', () => {
});
describe('has no alert', () => {
beforeEach(async () => {
alertResolver.mockResolvedValue({
data: {
project: {
id: '1',
environment: {
id: '2',
latestOpenedMostSevereAlert: null,
},
},
},
});
await factory();
});
it('should display nothing', () => {
expect(wrapper.find('[data-testid="alert"]').exists()).toBe(false);
expect(findSeverityBadge().exists()).toBe(false);
......
import VueApollo from 'vue-apollo';
import Vue, { nextTick } from 'vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import { stubTransition } from 'helpers/stub_transition';
import EnvironmentItem from '~/environments/components/new_environment_item.vue';
import EnvironmentAlert from 'ee/environments/components/environment_alert.vue';
import alertQuery from 'ee/environments/graphql/queries/environment.query.graphql';
import { resolvedEnvironment } from 'jest/environments/graphql/mock_data';
Vue.use(VueApollo);
describe('~/environments/components/new_environment_item.vue', () => {
let wrapper;
let alert;
const createApolloProvider = () => {
return createMockApollo([
[
alertQuery,
jest.fn().mockResolvedValue({
data: {
project: {
id: '1',
environment: {
id: '2',
latestOpenedMostSevereAlert: {
severity: 'CRITICAL',
title: 'alert title',
prometheusAlert: { id: '3', humanizedText: '>0.1% jest' },
detailsUrl: '/alert/details',
startedAt: new Date(),
},
},
},
},
}),
],
]);
};
const createWrapper = async ({ propsData = {}, apolloProvider } = {}) => {
wrapper = mountExtended(EnvironmentItem, {
apolloProvider,
propsData: { environment: resolvedEnvironment, ...propsData },
provide: { helpPagePath: '/help' },
stubs: { transition: stubTransition() },
});
await nextTick();
alert = wrapper.findComponent(EnvironmentAlert);
};
it('shows an alert if one is opened', async () => {
const environment = { ...resolvedEnvironment, hasOpenedAlert: true };
await createWrapper({ propsData: { environment }, apolloProvider: createApolloProvider() });
expect(alert.exists()).toBe(true);
expect(alert.props('environment')).toBe(environment);
});
it('does not show an alert if one is opened', async () => {
await createWrapper({ apolloProvider: createApolloProvider() });
alert = wrapper.findComponent(EnvironmentAlert);
expect(alert.exists()).toBe(false);
});
});
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