Commit ae064a78 authored by Dheeraj Joshi's avatar Dheeraj Joshi

Refactor Security Configuration layout components

  * Add ConfigurationPageLayout component
  * Migrate SAST, Fuzzing to use new component

This is done to improve maintainability across
security configuration pages
parent 26d063b7
<script>
import { GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import ConfigurationPageLayout from '../../components/configuration_page_layout.vue';
import apiFuzzingCiConfigurationQuery from '../graphql/api_fuzzing_ci_configuration.query.graphql';
import ConfigurationForm from './configuration_form.vue';
......@@ -10,6 +11,7 @@ export default {
GlLoadingIcon,
GlSprintf,
ConfigurationForm,
ConfigurationPageLayout,
},
inject: {
fullPath: {
......@@ -42,22 +44,18 @@ export default {
</script>
<template>
<article>
<header class="gl-my-5 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid">
<h4>
{{ s__('APIFuzzing|API Fuzzing Configuration') }}
</h4>
<p>
<configuration-page-layout>
<template #heading> {{ s__('APIFuzzing|API Fuzzing Configuration') }} </template>
<template #description>
<gl-sprintf :message="$options.i18n.helpText">
<template #docsLink="{ content }">
<gl-link :href="apiFuzzingDocumentationPath" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
</header>
</template>
<gl-loading-icon v-if="$apollo.loading" size="lg" />
<configuration-form v-else :api-fuzzing-ci-configuration="apiFuzzingCiConfiguration" />
</article>
</configuration-page-layout>
</template>
<script>
import { GlAlert } from '@gitlab/ui';
export default {
components: {
GlAlert,
},
data() {
return { isAlertDismissed: false };
},
computed: {
showPageAlert() {
return Boolean(this.$slots.alert) && !this.isAlertDismissed;
},
},
};
</script>
<template>
<article>
<gl-alert
v-if="showPageAlert"
data-testid="configuration-page-alert"
class="gl-mt-4"
@dismiss="isAlertDismissed = true"
>
<slot name="alert"></slot
></gl-alert>
<header class="gl-my-5 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid">
<h4>
<slot name="heading"></slot>
</h4>
<p>
<slot name="description"></slot>
</p>
</header>
<slot></slot>
</article>
</template>
......@@ -2,12 +2,14 @@
import { GlAlert, GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ConfigurationPageLayout from '../../components/configuration_page_layout.vue';
import sastCiConfigurationQuery from '../graphql/sast_ci_configuration.query.graphql';
import ConfigurationForm from './configuration_form.vue';
export default {
components: {
ConfigurationForm,
ConfigurationPageLayout,
GlAlert,
GlLink,
GlLoadingIcon,
......@@ -49,13 +51,9 @@ export default {
return {
sastCiConfiguration: null,
hasLoadingError: false,
showFeedbackAlert: true,
};
},
methods: {
dismissFeedbackAlert() {
this.showFeedbackAlert = false;
},
onError() {
this.hasLoadingError = true;
},
......@@ -80,32 +78,23 @@ export default {
</script>
<template>
<article>
<gl-alert
v-if="showFeedbackAlert"
data-testid="feedback-alert"
class="gl-mt-4"
@dismiss="dismissFeedbackAlert"
>
<configuration-page-layout>
<template #alert>
<gl-sprintf :message="$options.i18n.feedbackAlertMessage">
<template #link="{ content }">
<gl-link :href="$options.feedbackIssue" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</template>
<header class="gl-my-5 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid">
<h4>
{{ s__('SecurityConfiguration|SAST Configuration') }}
</h4>
<p>
<template #heading> {{ s__('SecurityConfiguration|SAST Configuration') }} </template>
<template #description>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
<gl-link :href="sastDocumentationPath" target="_blank" v-text="content" />
</template>
</gl-sprintf>
</p>
</header>
</template>
<gl-loading-icon v-if="$apollo.loading" size="lg" />
......@@ -118,5 +107,5 @@ export default {
>
<configuration-form v-else :sast-ci-configuration="sastCiConfiguration" />
</article>
</configuration-page-layout>
</template>
......@@ -6,6 +6,7 @@ import VueApollo from 'vue-apollo';
import App from 'ee/security_configuration/api_fuzzing/components/app.vue';
import ConfigurationForm from 'ee/security_configuration/api_fuzzing/components/configuration_form.vue';
import apiFuzzingCiConfigurationQuery from 'ee/security_configuration/api_fuzzing/graphql/api_fuzzing_ci_configuration.query.graphql';
import ConfigurationPageLayout from 'ee/security_configuration/components/configuration_page_layout.vue';
import { stripTypenames } from 'helpers/graphql_helpers';
import createMockApollo from 'helpers/mock_apollo_helper';
import { apiFuzzingConfigurationQueryResponse } from '../mock_data';
......@@ -31,6 +32,7 @@ describe('EE - ApiFuzzingConfigurationApp', () => {
apolloProvider: () => createMockApolloProvider(successHandler),
stubs: {
GlSprintf,
ConfigurationPageLayout,
},
provide: {
fullPath: projectFullPath,
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Security Configuration Page Layout component matches the snapshot 1`] = `
<article>
<gl-alert-stub
class="gl-mt-4"
data-testid="configuration-page-alert"
dismissible="true"
dismisslabel="Dismiss"
primarybuttonlink=""
primarybuttontext=""
secondarybuttonlink=""
secondarybuttontext=""
title=""
variant="info"
>
Page alert
</gl-alert-stub>
<header
class="gl-my-5 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid"
>
<h4>
Page title
</h4>
<p>
Scanner description
</p>
</header>
<div>
form
</div>
</article>
`;
import ConfigurationPageLayout from 'ee/security_configuration/components/configuration_page_layout.vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
describe('Security Configuration Page Layout component', () => {
let wrapper;
const createComponent = (options = {}) => {
const { slots = {} } = options;
wrapper = shallowMountExtended(ConfigurationPageLayout, {
slots: {
alert: 'Page alert',
heading: 'Page title',
description: 'Scanner description',
default: '<div>form</div>',
...slots,
},
...options,
});
};
const findPageAlert = () => wrapper.findByTestId('configuration-page-alert');
afterEach(() => {
wrapper.destroy();
});
it('matches the snapshot', () => {
createComponent();
expect(wrapper.element).toMatchSnapshot();
});
describe('page level alert', () => {
it('should render correctly', () => {
createComponent();
expect(findPageAlert().exists()).toBe(true);
});
it('should be disabled when slot is not present', () => {
createComponent({
slots: {
alert: '',
},
});
expect(findPageAlert().exists()).toBe(false);
});
it('should be disabled after dismissal', async () => {
createComponent();
findPageAlert().vm.$emit('dismiss');
await wrapper.vm.$nextTick();
expect(findPageAlert().exists()).toBe(false);
});
});
});
import { GlLink, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { merge } from 'lodash';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import ConfigurationPageLayout from 'ee/security_configuration/components/configuration_page_layout.vue';
import SASTConfigurationApp from 'ee/security_configuration/sast/components/app.vue';
import ConfigurationForm from 'ee/security_configuration/sast/components/configuration_form.vue';
import sastCiConfigurationQuery from 'ee/security_configuration/sast/graphql/sast_ci_configuration.query.graphql';
import { stripTypenames } from 'helpers/graphql_helpers';
import createMockApollo from 'helpers/mock_apollo_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { sastCiConfigurationQueryResponse } from '../mock_data';
Vue.use(VueApollo);
......@@ -25,7 +26,7 @@ describe('SAST Configuration App', () => {
createMockApollo([[sastCiConfigurationQuery, handler]]);
const createComponent = (options) => {
wrapper = shallowMount(
wrapper = shallowMountExtended(
SASTConfigurationApp,
merge(
{
......@@ -46,10 +47,10 @@ describe('SAST Configuration App', () => {
const findHeader = () => wrapper.find('header');
const findSubHeading = () => findHeader().find('p');
const findLink = (container = wrapper) => container.find(GlLink);
const findConfigurationForm = () => wrapper.find(ConfigurationForm);
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findErrorAlert = () => wrapper.find('[data-testid="error-alert"]');
const findFeedbackAlert = () => wrapper.find('[data-testid="feedback-alert"]');
const findConfigurationForm = () => wrapper.findComponent(ConfigurationForm);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findErrorAlert = () => wrapper.findByTestId('error-alert');
const findFeedbackAlert = () => wrapper.findByTestId('configuration-page-alert');
afterEach(() => {
wrapper.destroy();
......@@ -59,7 +60,7 @@ describe('SAST Configuration App', () => {
describe('feedback alert', () => {
beforeEach(() => {
createComponent({
stubs: { GlSprintf },
stubs: { GlSprintf, ConfigurationPageLayout },
});
});
......@@ -90,7 +91,7 @@ describe('SAST Configuration App', () => {
describe('header', () => {
beforeEach(() => {
createComponent({
stubs: { GlSprintf },
stubs: { GlSprintf, ConfigurationPageLayout },
});
});
......
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