Commit 4be2bc9f authored by Andrew Fontaine's avatar Andrew Fontaine

Show environment alerts on new environment design

The alerts are nicely self-contained considering they already fetch the
environment alert via GraphQL.

Also update the tests to use the mock apollo provider instead of setting
the data manually, as we can do that now.
parent 9611e4fc
......@@ -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