Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/security_configuration')
-rw-r--r--spec/frontend/security_configuration/components/redesigned_app_spec.js232
-rw-r--r--spec/frontend/security_configuration/components/section_layout_spec.js49
-rw-r--r--spec/frontend/security_configuration/components/upgrade_banner_spec.js60
-rw-r--r--spec/frontend/security_configuration/utils_spec.js81
4 files changed, 422 insertions, 0 deletions
diff --git a/spec/frontend/security_configuration/components/redesigned_app_spec.js b/spec/frontend/security_configuration/components/redesigned_app_spec.js
new file mode 100644
index 00000000000..7e27a3e1108
--- /dev/null
+++ b/spec/frontend/security_configuration/components/redesigned_app_spec.js
@@ -0,0 +1,232 @@
+import { GlTab } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import {
+ SAST_NAME,
+ SAST_SHORT_NAME,
+ SAST_DESCRIPTION,
+ SAST_HELP_PATH,
+ SAST_CONFIG_HELP_PATH,
+ LICENSE_COMPLIANCE_NAME,
+ LICENSE_COMPLIANCE_DESCRIPTION,
+ LICENSE_COMPLIANCE_HELP_PATH,
+} from '~/security_configuration/components/constants';
+import FeatureCard from '~/security_configuration/components/feature_card.vue';
+import RedesignedSecurityConfigurationApp, {
+ i18n,
+} from '~/security_configuration/components/redesigned_app.vue';
+import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
+import {
+ REPORT_TYPE_LICENSE_COMPLIANCE,
+ REPORT_TYPE_SAST,
+} from '~/vue_shared/security_reports/constants';
+
+const upgradePath = '/upgrade';
+
+describe('redesigned App component', () => {
+ let wrapper;
+ let userCalloutDismissSpy;
+
+ const createComponent = ({ shouldShowCallout = true, ...propsData }) => {
+ userCalloutDismissSpy = jest.fn();
+
+ wrapper = extendedWrapper(
+ mount(RedesignedSecurityConfigurationApp, {
+ propsData,
+ provide: {
+ upgradePath,
+ },
+ stubs: {
+ UserCalloutDismisser: makeMockUserCalloutDismisser({
+ dismiss: userCalloutDismissSpy,
+ shouldShowCallout,
+ }),
+ },
+ }),
+ );
+ };
+
+ const findMainHeading = () => wrapper.find('h1');
+ const findTab = () => wrapper.findComponent(GlTab);
+ const findTabs = () => wrapper.findAllComponents(GlTab);
+ const findByTestId = (id) => wrapper.findByTestId(id);
+ const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
+ const findComplianceViewHistoryLink = () => findByTestId('compliance-view-history-link');
+ const findSecurityViewHistoryLink = () => findByTestId('security-view-history-link');
+ const findUpgradeBanner = () => wrapper.findComponent(UpgradeBanner);
+
+ const securityFeaturesMock = [
+ {
+ name: SAST_NAME,
+ shortName: SAST_SHORT_NAME,
+ description: SAST_DESCRIPTION,
+ helpPath: SAST_HELP_PATH,
+ configurationHelpPath: SAST_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_SAST,
+ available: true,
+ },
+ ];
+
+ const complianceFeaturesMock = [
+ {
+ name: LICENSE_COMPLIANCE_NAME,
+ description: LICENSE_COMPLIANCE_DESCRIPTION,
+ helpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ type: REPORT_TYPE_LICENSE_COMPLIANCE,
+ configurationHelpPath: LICENSE_COMPLIANCE_HELP_PATH,
+ },
+ ];
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('basic structure', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ });
+ });
+
+ it('renders main-heading with correct text', () => {
+ const mainHeading = findMainHeading();
+ expect(mainHeading).toExist();
+ expect(mainHeading.text()).toContain('Security Configuration');
+ });
+
+ it('renders GlTab Component ', () => {
+ expect(findTab()).toExist();
+ });
+
+ it('renders right amount of tabs with correct title ', () => {
+ expect(findTabs()).toHaveLength(2);
+ });
+
+ it('renders security-testing tab', () => {
+ expect(findByTestId('security-testing-tab').exists()).toBe(true);
+ });
+
+ it('renders compliance-testing tab', () => {
+ expect(findByTestId('compliance-testing-tab').exists()).toBe(true);
+ });
+
+ it('renders right amount of feature cards for given props with correct props', () => {
+ const cards = findFeatureCards();
+ expect(cards).toHaveLength(2);
+ expect(cards.at(0).props()).toEqual({ feature: securityFeaturesMock[0] });
+ expect(cards.at(1).props()).toEqual({ feature: complianceFeaturesMock[0] });
+ });
+
+ it('should not show latest pipeline link when latestPipelinePath is not defined', () => {
+ expect(findByTestId('latest-pipeline-info').exists()).toBe(false);
+ });
+
+ it('should not show configuration History Link when gitlabCiPresent & gitlabCiHistoryPath are not defined', () => {
+ expect(findComplianceViewHistoryLink().exists()).toBe(false);
+ expect(findSecurityViewHistoryLink().exists()).toBe(false);
+ });
+ });
+
+ describe('upgrade banner', () => {
+ const makeAvailable = (available) => (feature) => ({ ...feature, available });
+
+ describe('given at least one unavailable feature', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
+ });
+ });
+
+ it('renders the banner', () => {
+ expect(findUpgradeBanner().exists()).toBe(true);
+ });
+
+ it('calls the dismiss callback when closing the banner', () => {
+ expect(userCalloutDismissSpy).not.toHaveBeenCalled();
+
+ findUpgradeBanner().vm.$emit('close');
+
+ expect(userCalloutDismissSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('given at least one unavailable feature, but banner is already dismissed', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
+ shouldShowCallout: false,
+ });
+ });
+
+ it('does not render the banner', () => {
+ expect(findUpgradeBanner().exists()).toBe(false);
+ });
+ });
+
+ describe('given all features are available', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock.map(makeAvailable(true)),
+ augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(true)),
+ });
+ });
+
+ it('does not render the banner', () => {
+ expect(findUpgradeBanner().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('when given latestPipelinePath props', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ latestPipelinePath: 'test/path',
+ });
+ });
+
+ it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => {
+ const latestPipelineInfoSecurity = findByTestId('latest-pipeline-info-security');
+
+ expect(latestPipelineInfoSecurity.exists()).toBe(true);
+ expect(latestPipelineInfoSecurity.text()).toMatchInterpolatedText(
+ i18n.securityTestingDescription,
+ );
+ expect(latestPipelineInfoSecurity.find('a').attributes('href')).toBe('test/path');
+ });
+
+ it('should show latest pipeline info on the compliance tab with correct link when latestPipelinePath is defined', () => {
+ const latestPipelineInfoCompliance = findByTestId('latest-pipeline-info-compliance');
+
+ expect(latestPipelineInfoCompliance.exists()).toBe(true);
+ expect(latestPipelineInfoCompliance.text()).toMatchInterpolatedText(
+ i18n.securityTestingDescription,
+ );
+ expect(latestPipelineInfoCompliance.find('a').attributes('href')).toBe('test/path');
+ });
+ });
+
+ describe('given gitlabCiPresent & gitlabCiHistoryPath props', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ gitlabCiPresent: true,
+ gitlabCiHistoryPath: 'test/historyPath',
+ });
+ });
+
+ it('should show configuration History Link', () => {
+ expect(findComplianceViewHistoryLink().exists()).toBe(true);
+ expect(findSecurityViewHistoryLink().exists()).toBe(true);
+
+ expect(findComplianceViewHistoryLink().attributes('href')).toBe('test/historyPath');
+ expect(findSecurityViewHistoryLink().attributes('href')).toBe('test/historyPath');
+ });
+ });
+});
diff --git a/spec/frontend/security_configuration/components/section_layout_spec.js b/spec/frontend/security_configuration/components/section_layout_spec.js
new file mode 100644
index 00000000000..75da380bbb8
--- /dev/null
+++ b/spec/frontend/security_configuration/components/section_layout_spec.js
@@ -0,0 +1,49 @@
+import { mount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+import SectionLayout from '~/security_configuration/components/section_layout.vue';
+
+describe('Section Layout component', () => {
+ let wrapper;
+
+ const createComponent = (propsData) => {
+ wrapper = extendedWrapper(
+ mount(SectionLayout, {
+ propsData,
+ scopedSlots: {
+ description: '<span>foo</span>',
+ features: '<span>bar</span>',
+ },
+ }),
+ );
+ };
+
+ const findHeading = () => wrapper.find('h2');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('basic structure', () => {
+ beforeEach(() => {
+ createComponent({ heading: 'testheading' });
+ });
+
+ const slots = {
+ description: 'foo',
+ features: 'bar',
+ };
+
+ it('should render heading when passed in as props', () => {
+ expect(findHeading().exists()).toBe(true);
+ expect(findHeading().text()).toBe('testheading');
+ });
+
+ Object.keys(slots).forEach((slot) => {
+ it('renders the slots', () => {
+ const slotContent = slots[slot];
+ createComponent({ heading: '' });
+ expect(wrapper.text()).toContain(slotContent);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/security_configuration/components/upgrade_banner_spec.js b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
new file mode 100644
index 00000000000..cf7945343af
--- /dev/null
+++ b/spec/frontend/security_configuration/components/upgrade_banner_spec.js
@@ -0,0 +1,60 @@
+import { GlBanner } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
+
+const upgradePath = '/upgrade';
+
+describe('UpgradeBanner component', () => {
+ let wrapper;
+ let closeSpy;
+
+ const createComponent = (propsData) => {
+ closeSpy = jest.fn();
+
+ wrapper = shallowMountExtended(UpgradeBanner, {
+ provide: {
+ upgradePath,
+ },
+ propsData,
+ listeners: {
+ close: closeSpy,
+ },
+ });
+ };
+
+ const findGlBanner = () => wrapper.findComponent(GlBanner);
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('passes the expected props to GlBanner', () => {
+ expect(findGlBanner().props()).toMatchObject({
+ title: UpgradeBanner.i18n.title,
+ buttonText: UpgradeBanner.i18n.buttonText,
+ buttonLink: upgradePath,
+ });
+ });
+
+ it('renders the list of benefits', () => {
+ const wrapperText = wrapper.text();
+
+ expect(wrapperText).toContain('GitLab Ultimate checks your application');
+ expect(wrapperText).toContain('statistics in the merge request');
+ expect(wrapperText).toContain('statistics across projects');
+ expect(wrapperText).toContain('Runtime security metrics');
+ expect(wrapperText).toContain('risk analysis and remediation');
+ });
+
+ it(`re-emits GlBanner's close event`, () => {
+ expect(closeSpy).not.toHaveBeenCalled();
+
+ wrapper.findComponent(GlBanner).vm.$emit('close');
+
+ expect(closeSpy).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/spec/frontend/security_configuration/utils_spec.js b/spec/frontend/security_configuration/utils_spec.js
new file mode 100644
index 00000000000..6ad167cadda
--- /dev/null
+++ b/spec/frontend/security_configuration/utils_spec.js
@@ -0,0 +1,81 @@
+import { augmentFeatures } from '~/security_configuration/utils';
+
+const mockSecurityFeatures = [
+ {
+ name: 'SAST',
+ type: 'SAST',
+ },
+];
+
+const mockComplianceFeatures = [
+ {
+ name: 'LICENSE_COMPLIANCE',
+ type: 'LICENSE_COMPLIANCE',
+ },
+];
+
+const mockFeaturesWithSecondary = [
+ {
+ name: 'DAST',
+ type: 'DAST',
+ secondary: {
+ type: 'DAST PROFILES',
+ name: 'DAST PROFILES',
+ },
+ },
+];
+
+const mockInvalidCustomFeature = [
+ {
+ foo: 'bar',
+ },
+];
+
+const mockValidCustomFeature = [
+ {
+ name: 'SAST',
+ type: 'SAST',
+ customfield: 'customvalue',
+ },
+];
+
+const expectedOutputDefault = {
+ augmentedSecurityFeatures: mockSecurityFeatures,
+ augmentedComplianceFeatures: mockComplianceFeatures,
+};
+
+const expectedOutputSecondary = {
+ augmentedSecurityFeatures: mockSecurityFeatures,
+ augmentedComplianceFeatures: mockFeaturesWithSecondary,
+};
+
+const expectedOutputCustomFeature = {
+ augmentedSecurityFeatures: mockValidCustomFeature,
+ augmentedComplianceFeatures: mockComplianceFeatures,
+};
+
+describe('returns an object with augmentedSecurityFeatures and augmentedComplianceFeatures when', () => {
+ it('given an empty array', () => {
+ expect(augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, [])).toEqual(
+ expectedOutputDefault,
+ );
+ });
+
+ it('given an invalid populated array', () => {
+ expect(
+ augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockInvalidCustomFeature),
+ ).toEqual(expectedOutputDefault);
+ });
+
+ it('features have secondary key', () => {
+ expect(augmentFeatures(mockSecurityFeatures, mockFeaturesWithSecondary, [])).toEqual(
+ expectedOutputSecondary,
+ );
+ });
+
+ it('given a valid populated array', () => {
+ expect(
+ augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockValidCustomFeature),
+ ).toEqual(expectedOutputCustomFeature);
+ });
+});