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 { ...@@ -40,6 +40,7 @@ export default {
Terminal, Terminal,
TimeAgoTooltip, TimeAgoTooltip,
Delete, Delete,
EnvironmentAlert: () => import('ee_component/environments/components/environment_alert.vue'),
}, },
directives: { directives: {
GlTooltip, GlTooltip,
...@@ -97,6 +98,9 @@ export default { ...@@ -97,6 +98,9 @@ export default {
hasDeployment() { hasDeployment() {
return Boolean(this.environment?.upcomingDeployment || this.environment?.lastDeployment); return Boolean(this.environment?.upcomingDeployment || this.environment?.lastDeployment);
}, },
hasOpenedAlert() {
return this.environment?.hasOpenedAlert;
},
actions() { actions() {
if (!this.lastDeployment) { if (!this.lastDeployment) {
return []; return [];
...@@ -319,6 +323,9 @@ export default { ...@@ -319,6 +323,9 @@ export default {
class="gl-pl-4" class="gl-pl-4"
/> />
</div> </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> </gl-collapse>
</div> </div>
</template> </template>
...@@ -2,6 +2,9 @@ import VueApollo from 'vue-apollo'; ...@@ -2,6 +2,9 @@ import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
import environmentApp from './queries/environment_app.query.graphql'; import environmentApp from './queries/environment_app.query.graphql';
import pageInfoQuery from './queries/page_info.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 { resolvers } from './resolvers';
import typeDefs from './typedefs.graphql'; import typeDefs from './typedefs.graphql';
...@@ -33,6 +36,52 @@ export const apolloProvider = (endpoint) => { ...@@ -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({ return new VueApollo({
defaultClient, defaultClient,
}); });
......
import { mount } from '@vue/test-utils'; 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 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 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', () => { describe('Environment Alert', () => {
let wrapper; let wrapper;
let alertResolver;
const DEFAULT_PROVIDE = { projectPath: 'test-org/test' }; const DEFAULT_PROVIDE = { projectPath: 'test-org/test' };
const DEFAULT_PROPS = { environment: { name: 'staging' } }; 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, { wrapper = mount(EnvironmentAlert, {
apolloProvider,
propsData: { propsData: {
...DEFAULT_PROPS, ...DEFAULT_PROPS,
...props, ...props,
...@@ -18,12 +31,14 @@ describe('Environment Alert', () => { ...@@ -18,12 +31,14 @@ describe('Environment Alert', () => {
...provide, ...provide,
}, },
}); });
await waitForPromises();
}; };
const findSeverityBadge = () => wrapper.findComponent(SeverityBadge); const findSeverityBadge = () => wrapper.findComponent(SeverityBadge);
beforeEach(() => { beforeEach(() => {
factory(); alertResolver = jest.fn();
}); });
afterEach(() => { afterEach(() => {
...@@ -32,21 +47,29 @@ describe('Environment Alert', () => { ...@@ -32,21 +47,29 @@ describe('Environment Alert', () => {
}); });
describe('has alert', () => { describe('has alert', () => {
beforeEach(() => { beforeEach(async () => {
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details alertResolver.mockResolvedValue({
// eslint-disable-next-line no-restricted-syntax data: {
wrapper.setData({ project: {
alert: { id: '1',
severity: 'CRITICAL', environment: {
title: 'alert title', id: '2',
prometheusAlert: { humanizedText: '>0.1% jest' }, latestOpenedMostSevereAlert: {
detailsUrl: '/alert/details', severity: 'CRITICAL',
startedAt: new Date(), 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(); const text = wrapper.text();
expect(text).toContain('Critical'); expect(text).toContain('Critical');
expect(text).toContain('alert title >0.1% jest.'); expect(text).toContain('alert title >0.1% jest.');
...@@ -68,6 +91,21 @@ describe('Environment Alert', () => { ...@@ -68,6 +91,21 @@ describe('Environment Alert', () => {
}); });
describe('has no alert', () => { describe('has no alert', () => {
beforeEach(async () => {
alertResolver.mockResolvedValue({
data: {
project: {
id: '1',
environment: {
id: '2',
latestOpenedMostSevereAlert: null,
},
},
},
});
await factory();
});
it('should display nothing', () => { it('should display nothing', () => {
expect(wrapper.find('[data-testid="alert"]').exists()).toBe(false); expect(wrapper.find('[data-testid="alert"]').exists()).toBe(false);
expect(findSeverityBadge().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