Commit 24abff05 authored by Mark Florian's avatar Mark Florian Committed by Brandon Labuschagne

Add pinning tests for current implementation

This adds a temporary [pinning test][1] to record the current behaviour
of the Ultimate version of the Security Configuration page, so as to
support the refactoring work in the next commit.

Once the work has been done, these tests can be removed, having served
their purpose.

[1]: https://web.archive.org/web/20170826101146/http://wiki.c2.com/?PinningTests
parent 3c0902c7
<script>
import { GlLink, GlSprintf, GlTable, GlAlert } from '@gitlab/ui';
import { GlLink, GlTable, GlAlert } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import {
REPORT_TYPE_SAST,
......@@ -8,10 +8,11 @@ import {
REPORT_TYPE_DEPENDENCY_SCANNING,
REPORT_TYPE_CONTAINER_SCANNING,
REPORT_TYPE_COVERAGE_FUZZING,
REPORT_TYPE_API_FUZZING,
REPORT_TYPE_LICENSE_COMPLIANCE,
} from '~/vue_shared/security_reports/constants';
import { features } from './features_constants';
import ManageSast from './manage_sast.vue';
import { scanners } from './scanners_constants';
import Upgrade from './upgrade.vue';
const borderClasses = 'gl-border-b-1! gl-border-b-solid! gl-border-gray-100!';
......@@ -20,12 +21,10 @@ const thClass = `gl-text-gray-900 gl-bg-transparent! ${borderClasses}`;
export default {
components: {
GlLink,
GlSprintf,
GlTable,
GlAlert,
},
data: () => ({
features,
errorMessage: '',
}),
methods: {
......@@ -45,6 +44,7 @@ export default {
[REPORT_TYPE_DEPENDENCY_SCANNING]: Upgrade,
[REPORT_TYPE_CONTAINER_SCANNING]: Upgrade,
[REPORT_TYPE_COVERAGE_FUZZING]: Upgrade,
[REPORT_TYPE_API_FUZZING]: Upgrade,
[REPORT_TYPE_LICENSE_COMPLIANCE]: Upgrade,
};
......@@ -64,7 +64,7 @@ export default {
thClass,
},
],
items: features,
items: scanners,
},
};
</script>
......
import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
import { __, s__ } from '~/locale';
import {
REPORT_TYPE_SAST,
......@@ -9,58 +9,65 @@ import {
REPORT_TYPE_DEPENDENCY_SCANNING,
REPORT_TYPE_CONTAINER_SCANNING,
REPORT_TYPE_COVERAGE_FUZZING,
REPORT_TYPE_API_FUZZING,
REPORT_TYPE_LICENSE_COMPLIANCE,
} from '~/vue_shared/security_reports/constants';
/**
* Translations & helpPagePaths for Static Security Configuration Page
*/
export const SAST_NAME = s__('Static Application Security Testing (SAST)');
export const SAST_DESCRIPTION = s__('Analyze your source code for known vulnerabilities.');
export const SAST_NAME = __('Static Application Security Testing (SAST)');
export const SAST_DESCRIPTION = __('Analyze your source code for known vulnerabilities.');
export const SAST_HELP_PATH = helpPagePath('user/application_security/sast/index');
export const DAST_NAME = s__('Dynamic Application Security Testing (DAST)');
export const DAST_DESCRIPTION = s__('Analyze a review version of your web application.');
export const DAST_NAME = __('Dynamic Application Security Testing (DAST)');
export const DAST_DESCRIPTION = __('Analyze a review version of your web application.');
export const DAST_HELP_PATH = helpPagePath('user/application_security/dast/index');
export const DAST_PROFILES_NAME = s__('DAST Scans');
export const DAST_PROFILES_DESCRIPTION = s__('Analyze a review version of your web application.');
export const DAST_PROFILES_NAME = __('DAST Scans');
export const DAST_PROFILES_DESCRIPTION = __(
'Saved scan settings and target site settings which are reusable.',
);
export const DAST_PROFILES_HELP_PATH = helpPagePath('user/application_security/dast/index');
export const SECRET_DETECTION_NAME = s__('Secret Detection');
export const SECRET_DETECTION_DESCRIPTION = s__(
export const SECRET_DETECTION_NAME = __('Secret Detection');
export const SECRET_DETECTION_DESCRIPTION = __(
'Analyze your source code and git history for secrets.',
);
export const SECRET_DETECTION_HELP_PATH = helpPagePath(
'user/application_security/secret_detection/index',
);
export const DEPENDENCY_SCANNING_NAME = s__('Dependency Scanning');
export const DEPENDENCY_SCANNING_DESCRIPTION = s__(
export const DEPENDENCY_SCANNING_NAME = __('Dependency Scanning');
export const DEPENDENCY_SCANNING_DESCRIPTION = __(
'Analyze your dependencies for known vulnerabilities.',
);
export const DEPENDENCY_SCANNING_HELP_PATH = helpPagePath(
'user/application_security/dependency_scanning/index',
);
export const CONTAINER_SCANNING_NAME = s__('Container Scanning');
export const CONTAINER_SCANNING_DESCRIPTION = s__(
export const CONTAINER_SCANNING_NAME = __('Container Scanning');
export const CONTAINER_SCANNING_DESCRIPTION = __(
'Check your Docker images for known vulnerabilities.',
);
export const CONTAINER_SCANNING_HELP_PATH = helpPagePath(
'user/application_security/container_scanning/index',
);
export const COVERAGE_FUZZING_NAME = s__('Coverage Fuzzing');
export const COVERAGE_FUZZING_DESCRIPTION = s__(
export const COVERAGE_FUZZING_NAME = __('Coverage Fuzzing');
export const COVERAGE_FUZZING_DESCRIPTION = __(
'Find bugs in your code with coverage-guided fuzzing.',
);
export const COVERAGE_FUZZING_HELP_PATH = helpPagePath(
'user/application_security/coverage_fuzzing/index',
);
export const LICENSE_COMPLIANCE_NAME = s__('License Compliance');
export const LICENSE_COMPLIANCE_DESCRIPTION = s__(
export const API_FUZZING_NAME = __('API Fuzzing');
export const API_FUZZING_DESCRIPTION = __('Find bugs in your code with API fuzzing.');
export const API_FUZZING_HELP_PATH = helpPagePath('user/application_security/api_fuzzing/index');
export const LICENSE_COMPLIANCE_NAME = __('License Compliance');
export const LICENSE_COMPLIANCE_DESCRIPTION = __(
'Search your project dependencies for their licenses and apply policies.',
);
export const LICENSE_COMPLIANCE_HELP_PATH = helpPagePath(
......@@ -71,7 +78,7 @@ export const UPGRADE_CTA = s__(
'SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}',
);
export const features = [
export const scanners = [
{
name: SAST_NAME,
description: SAST_DESCRIPTION,
......@@ -90,12 +97,6 @@ export const features = [
helpPath: DAST_PROFILES_HELP_PATH,
type: REPORT_TYPE_DAST_PROFILES,
},
{
name: SECRET_DETECTION_NAME,
description: SECRET_DETECTION_DESCRIPTION,
helpPath: SECRET_DETECTION_HELP_PATH,
type: REPORT_TYPE_SECRET_DETECTION,
},
{
name: DEPENDENCY_SCANNING_NAME,
description: DEPENDENCY_SCANNING_DESCRIPTION,
......@@ -108,12 +109,24 @@ export const features = [
helpPath: CONTAINER_SCANNING_HELP_PATH,
type: REPORT_TYPE_CONTAINER_SCANNING,
},
{
name: SECRET_DETECTION_NAME,
description: SECRET_DETECTION_DESCRIPTION,
helpPath: SECRET_DETECTION_HELP_PATH,
type: REPORT_TYPE_SECRET_DETECTION,
},
{
name: COVERAGE_FUZZING_NAME,
description: COVERAGE_FUZZING_DESCRIPTION,
helpPath: COVERAGE_FUZZING_HELP_PATH,
type: REPORT_TYPE_COVERAGE_FUZZING,
},
{
name: API_FUZZING_NAME,
description: API_FUZZING_DESCRIPTION,
helpPath: API_FUZZING_HELP_PATH,
type: REPORT_TYPE_API_FUZZING,
},
{
name: LICENSE_COMPLIANCE_NAME,
description: LICENSE_COMPLIANCE_DESCRIPTION,
......
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { UPGRADE_CTA } from './features_constants';
import { UPGRADE_CTA } from './scanners_constants';
export default {
components: {
......
......@@ -23,7 +23,7 @@ export const REPORT_TYPE_SECRET_DETECTION = 'secret_detection';
export const REPORT_TYPE_DEPENDENCY_SCANNING = 'dependency_scanning';
export const REPORT_TYPE_CONTAINER_SCANNING = 'container_scanning';
export const REPORT_TYPE_COVERAGE_FUZZING = 'coverage_fuzzing';
export const REPORT_TYPE_LICENSE_COMPLIANCE = 'license_compliance';
export const REPORT_TYPE_LICENSE_COMPLIANCE = 'license_scanning';
export const REPORT_TYPE_API_FUZZING = 'api_fuzzing';
/**
......
---
title: Add API Fuzzing to Security Configuration page, and re-order scanners
merge_request: 56022
author:
type: changed
<script>
import { GlAlert, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { parseBoolean } from '~/lib/utils/common_utils';
import { sprintf, s__, __ } from '~/locale';
import { s__, __ } from '~/locale';
import { scanners } from '~/security_configuration/components/scanners_constants';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import AutoFixSettings from './auto_fix_settings.vue';
import FeatureStatus from './feature_status.vue';
import ManageFeature from './manage_feature.vue';
import ConfigurationTable from './configuration_table.vue';
export default {
components: {
GlAlert,
GlLink,
GlSprintf,
GlTable,
AutoFixSettings,
LocalStorageSync,
FeatureStatus,
ManageFeature,
ConfigurationTable,
},
mixins: [glFeatureFlagsMixin()],
props: {
......@@ -26,10 +24,6 @@ export default {
required: false,
default: false,
},
helpPagePath: {
type: String,
required: true,
},
autoDevopsHelpPagePath: {
type: String,
required: true,
......@@ -84,28 +78,6 @@ export default {
devopsUrl() {
return this.autoDevopsEnabled ? this.autoDevopsHelpPagePath : this.latestPipelinePath;
},
fields() {
const borderClasses = 'gl-border-b-1! gl-border-b-solid! gl-border-gray-100!';
const thClass = `gl-text-gray-900 gl-bg-transparent! ${borderClasses}`;
return [
{
key: 'feature',
label: s__('SecurityConfiguration|Security Control'),
thClass,
},
{
key: 'status',
label: s__('SecurityConfiguration|Status'),
thClass,
},
{
key: 'manage',
label: s__('SecurityConfiguration|Manage'),
thClass,
},
];
},
shouldShowAutoDevopsAlert() {
return Boolean(
!parseBoolean(this.autoDevopsAlertDismissed) &&
......@@ -114,16 +86,26 @@ export default {
this.canEnableAutoDevops,
);
},
featuresForDisplay() {
const featuresByType = this.features.reduce((acc, feature) => {
acc[feature.type] = feature;
return acc;
}, {});
return scanners.map((scanner) => {
const feature = featuresByType[scanner.type] ?? {};
return {
...feature,
...scanner,
};
});
},
},
methods: {
dismissAutoDevopsAlert() {
this.autoDevopsAlertDismissed = 'true';
},
getFeatureDocumentationLinkLabel(item) {
return sprintf(s__('SecurityConfiguration|Feature documentation for %{featureName}'), {
featureName: item.name,
});
},
},
autoDevopsAlertMessage: s__(`
SecurityConfiguration|You can quickly enable all security scanning tools by
......@@ -166,40 +148,13 @@ export default {
</gl-sprintf>
</gl-alert>
<gl-table
ref="securityControlTable"
:items="features"
:fields="fields"
stacked="md"
:tbody-tr-attr="{ 'data-testid': 'security-scanner-row' }"
>
<template #cell(feature)="{ item }">
<div class="gl-text-gray-900">{{ item.name }}</div>
<div>
{{ item.description }}
<gl-link
target="_blank"
:href="item.link"
:aria-label="getFeatureDocumentationLinkLabel(item)"
data-testid="docsLink"
>
{{ s__('SecurityConfiguration|More information') }}
</gl-link>
</div>
</template>
<template #cell(status)="{ item }">
<feature-status
:feature="item"
:gitlab-ci-present="gitlabCiPresent"
:gitlab-ci-history-path="gitlabCiHistoryPath"
/>
</template>
<configuration-table
:features="featuresForDisplay"
:auto-devops-enabled="autoDevopsEnabled"
:gitlab-ci-present="gitlabCiPresent"
:gitlab-ci-history-path="gitlabCiHistoryPath"
/>
<template #cell(manage)="{ item }">
<manage-feature :feature="item" :auto-devops-enabled="autoDevopsEnabled" />
</template>
</gl-table>
<auto-fix-settings v-if="glFeatures.securityAutoFix" v-bind="autoFixSettingsProps" />
</article>
</template>
<script>
import { GlLink, GlTable } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import FeatureStatus from './feature_status.vue';
import ManageFeature from './manage_feature.vue';
const borderClasses = 'gl-border-b-1! gl-border-b-solid! gl-border-gray-100!';
const thClass = `gl-text-gray-900 gl-bg-transparent! ${borderClasses}`;
export default {
components: {
GlLink,
GlTable,
FeatureStatus,
ManageFeature,
},
props: {
features: {
type: Array,
required: true,
},
autoDevopsEnabled: {
type: Boolean,
required: false,
default: false,
},
gitlabCiPresent: {
type: Boolean,
required: false,
default: false,
},
gitlabCiHistoryPath: {
type: String,
required: false,
default: '',
},
},
methods: {
getFeatureDocumentationLinkLabel(item) {
return sprintf(s__('SecurityConfiguration|Feature documentation for %{featureName}'), {
featureName: item.name,
});
},
},
fields: [
{
key: 'description',
label: s__('SecurityConfiguration|Security Control'),
thClass,
},
{
key: 'status',
label: s__('SecurityConfiguration|Status'),
thClass,
},
{
key: 'manage',
label: s__('SecurityConfiguration|Manage'),
thClass,
},
],
};
</script>
<template>
<gl-table
:items="features"
:fields="$options.fields"
stacked="md"
:tbody-tr-attr="{ 'data-testid': 'security-scanner-row' }"
>
<template #cell(description)="{ item }">
<div class="gl-text-gray-900">{{ item.name }}</div>
<div>
{{ item.description }}
<gl-link
target="_blank"
:href="item.helpPath"
:aria-label="getFeatureDocumentationLinkLabel(item)"
>
{{ s__('SecurityConfiguration|More information') }}
</gl-link>
</div>
</template>
<template #cell(status)="{ item }">
<feature-status
:feature="item"
:gitlab-ci-present="gitlabCiPresent"
:gitlab-ci-history-path="gitlabCiHistoryPath"
/>
</template>
<template #cell(manage)="{ item }">
<manage-feature :feature="item" :auto-devops-enabled="autoDevopsEnabled" />
</template>
</gl-table>
</template>
......@@ -11,7 +11,6 @@ export const initSecurityConfiguration = (el) => {
autoDevopsHelpPagePath,
autoDevopsPath,
features,
helpPagePath,
latestPipelinePath,
autoFixEnabled,
autoFixHelpPath,
......@@ -33,7 +32,6 @@ export const initSecurityConfiguration = (el) => {
autoDevopsHelpPagePath,
autoDevopsPath,
features: JSON.parse(features),
helpPagePath,
latestPipelinePath,
...parseBooleanDataAttributes(el, [
'autoDevopsEnabled',
......
......@@ -9,46 +9,6 @@ module Projects
presents :project
SCAN_DOCS = {
container_scanning: 'user/application_security/container_scanning/index',
dast: 'user/application_security/dast/index',
dast_profiles: 'user/application_security/dast/index',
dependency_scanning: 'user/application_security/dependency_scanning/index',
license_scanning: 'user/compliance/license_compliance/index',
sast: 'user/application_security/sast/index',
secret_detection: 'user/application_security/secret_detection/index',
coverage_fuzzing: 'user/application_security/coverage_fuzzing/index',
api_fuzzing: 'user/application_security/api_fuzzing/index'
}.freeze
def self.localized_scan_descriptions
{
container_scanning: _('Check your Docker images for known vulnerabilities.'),
dast: _('Analyze a review version of your web application.'),
dast_profiles: _('Saved scan settings and target site settings which are reusable.'),
dependency_scanning: _('Analyze your dependencies for known vulnerabilities.'),
license_scanning: _('Search your project dependencies for their licenses and apply policies.'),
sast: _('Analyze your source code for known vulnerabilities.'),
secret_detection: _('Analyze your source code and git history for secrets.'),
coverage_fuzzing: _('Find bugs in your code with coverage-guided fuzzing.'),
api_fuzzing: _('Find bugs in your code with API fuzzing.')
}.freeze
end
def self.localized_scan_names
{
container_scanning: _('Container Scanning'),
dast: _('Dynamic Application Security Testing (DAST)'),
dast_profiles: _('DAST Scans'),
dependency_scanning: _('Dependency Scanning'),
license_scanning: _('License Compliance'),
sast: _('Static Application Security Testing (SAST)'),
secret_detection: _('Secret Detection'),
coverage_fuzzing: _('Coverage Fuzzing'),
api_fuzzing: _('API Fuzzing')
}.freeze
end
def to_h
{
auto_devops_enabled: auto_devops_source?,
......@@ -115,8 +75,9 @@ module Projects
end
# DAST On-demand scans is a static (non job) entry. Add it manually following DAST
# TODO: remove as part of https://gitlab.com/gitlab-org/gitlab/-/issues/323375
def dast_profiles_insert(scans)
index = scans.index { |scan| scan[:name] == localized_scan_names[:dast] }
index = scans.index { |scan| scan[:type] == :dast }
unless index.nil?
scans.insert(index + 1, scan(:dast_profiles, configured: true, status: s_('SecurityConfiguration|Available for on-demand DAST')))
......@@ -130,10 +91,7 @@ module Projects
type: type,
configured: configured,
status: status,
description: self.class.localized_scan_descriptions[type],
link: help_page_path(SCAN_DOCS[type]),
configuration_path: configuration_path(type),
name: localized_scan_names[type]
configuration_path: configuration_path(type)
}
end
......@@ -141,10 +99,6 @@ module Projects
::Security::SecurityJobsFinder.allowed_job_types + ::Security::LicenseComplianceJobsFinder.allowed_job_types
end
def localized_scan_names
@localized_scan_names ||= self.class.localized_scan_names
end
def project_settings
project.security_setting
end
......
......@@ -2,10 +2,10 @@ import { GlAlert, GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { merge } from 'lodash';
import SecurityConfigurationApp from 'ee/security_configuration/components/app.vue';
import FeatureStatus from 'ee/security_configuration/components/feature_status.vue';
import ManageFeature from 'ee/security_configuration/components/manage_feature.vue';
import ConfigurationTable from 'ee/security_configuration/components/configuration_table.vue';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import stubChildren from 'helpers/stub_children';
import { scanners } from '~/security_configuration/components/scanners_constants';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { generateFeatures } from './helpers';
......@@ -31,7 +31,6 @@ describe('Security Configuration App', () => {
{
stubs: {
...stubChildren(SecurityConfigurationApp),
GlTable: false,
GlSprintf: false,
},
propsData,
......@@ -51,13 +50,8 @@ describe('Security Configuration App', () => {
});
const getPipelinesLink = () => wrapper.find({ ref: 'pipelinesLink' });
const getFeaturesTable = () => wrapper.find({ ref: 'securityControlTable' });
const getFeaturesRows = () => getFeaturesTable().findAll('tbody tr');
const getConfigurationTable = () => wrapper.find(ConfigurationTable);
const getAlert = () => wrapper.find(GlAlert);
const getRowCells = (row) => {
const [feature, status, manage] = row.findAll('td').wrappers;
return { feature, status, manage };
};
describe('header', () => {
it.each`
......@@ -161,30 +155,31 @@ describe('Security Configuration App', () => {
});
describe('features table', () => {
it('passes the expected data to the GlTable', () => {
const features = generateFeatures(5);
it('passes the expected features to the configuration table', () => {
const features = generateFeatures(scanners.length);
createComponent({ propsData: { features } });
expect(getFeaturesTable().classes('b-table-stacked-md')).toBeTruthy();
const rows = getFeaturesRows();
expect(rows).toHaveLength(5);
for (let i = 0; i < features.length; i += 1) {
const { feature, status, manage } = getRowCells(rows.at(i));
expect(feature.text()).toMatch(features[i].name);
expect(feature.text()).toMatch(features[i].description);
expect(status.find(FeatureStatus).props()).toEqual({
feature: features[i],
gitlabCiPresent: propsData.gitlabCiPresent,
gitlabCiHistoryPath: propsData.gitlabCiHistoryPath,
const table = getConfigurationTable();
const receivedFeatures = table.props('features');
scanners.forEach((scanner, i) => {
expect(receivedFeatures[i]).toMatchObject({
...features[i],
name: scanner.name,
description: scanner.description,
helpPath: scanner.helpPath,
});
expect(manage.find(ManageFeature).props()).toEqual({
feature: features[i],
autoDevopsEnabled: propsData.autoDevopsEnabled,
});
expect(feature.find(GlLink).props('href')).toBe(features[i].href);
}
});
});
it('passes the expected props data to the configuration table', () => {
createComponent();
expect(getConfigurationTable().props()).toMatchObject({
autoDevopsEnabled: propsData.autoDevopsEnabled,
gitlabCiPresent: propsData.gitlabCiPresent,
gitlabCiHistoryPath: propsData.gitlabCiHistoryPath,
});
});
});
});
import { GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import ConfigurationTable from 'ee/security_configuration/components/configuration_table.vue';
import FeatureStatus from 'ee/security_configuration/components/feature_status.vue';
import ManageFeature from 'ee/security_configuration/components/manage_feature.vue';
import stubChildren from 'helpers/stub_children';
import { generateFeatures } from './helpers';
const propsData = {
features: [],
autoDevopsEnabled: false,
gitlabCiPresent: false,
gitlabCiHistoryPath: '/ci/history',
};
describe('ConfigurationTable component', () => {
let wrapper;
const mockFeatures = [
...generateFeatures(1, {
name: 'foo',
description: 'Foo description',
helpPath: '/help/foo',
}),
...generateFeatures(1, {
name: 'bar',
description: 'Bar description',
helpPath: '/help/bar',
}),
];
const createComponent = (props) => {
wrapper = mount(ConfigurationTable, {
stubs: {
...stubChildren(ConfigurationTable),
GlTable: false,
},
propsData: {
...propsData,
...props,
},
});
};
const getRows = () => wrapper.findAll('tbody tr');
const getRowCells = (row) => {
const [description, status, manage] = row.findAll('td').wrappers;
return { description, status, manage };
};
afterEach(() => {
wrapper.destroy();
});
it.each(mockFeatures)('renders the feature %p correctly', (feature) => {
createComponent({ features: [feature] });
expect(wrapper.classes('b-table-stacked-md')).toBeTruthy();
const rows = getRows();
expect(rows).toHaveLength(1);
const { description, status, manage } = getRowCells(rows.at(0));
expect(description.text()).toMatch(feature.name);
expect(description.text()).toMatch(feature.description);
expect(status.find(FeatureStatus).props()).toEqual({
feature,
gitlabCiPresent: propsData.gitlabCiPresent,
gitlabCiHistoryPath: propsData.gitlabCiHistoryPath,
});
expect(manage.find(ManageFeature).props()).toEqual({
feature,
autoDevopsEnabled: propsData.autoDevopsEnabled,
});
expect(description.find(GlLink).attributes('href')).toBe(feature.helpPath);
});
});
import { scanners } from '~/security_configuration/components/scanners_constants';
export const generateFeatures = (n, overrides = {}) => {
return [...Array(n).keys()].map((i) => ({
type: `scan-type-${i}`,
name: `name-feature-${i}`,
description: `description-feature-${i}`,
link: `link-feature-${i}`,
type: scanners[i % scanners.length].type,
configuration_path: i % 2 ? `configuration_path-${i}` : null,
configured: i % 2 === 0,
status: i % 2 === 0 ? 'Enabled' : 'Not enabled',
......
......@@ -263,10 +263,7 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
"type" => type.to_s,
"configured" => configured,
"status" => status_str,
"description" => described_class.localized_scan_descriptions[type],
"link" => help_page_path(described_class::SCAN_DOCS[type]),
"configuration_path" => configuration_path,
"name" => described_class.localized_scan_names[type]
"configuration_path" => configuration_path
}
end
......
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ConfigurationTable from '~/security_configuration/components/configuration_table.vue';
import { features, UPGRADE_CTA } from '~/security_configuration/components/features_constants';
import { scanners, UPGRADE_CTA } from '~/security_configuration/components/scanners_constants';
import {
REPORT_TYPE_SAST,
......@@ -25,20 +25,20 @@ describe('Configuration Table Component', () => {
createComponent();
});
describe.each(features.map((feature, i) => [feature, i]))('given feature %s', (feature, i) => {
describe.each(scanners.map((scanner, i) => [scanner, i]))('given scanner %s', (scanner, i) => {
it('should match strings', () => {
expect(wrapper.text()).toContain(feature.name);
expect(wrapper.text()).toContain(feature.description);
if (feature.type === REPORT_TYPE_SAST) {
expect(wrapper.findByTestId(feature.type).text()).toBe('Configure via Merge Request');
} else if (feature.type !== REPORT_TYPE_SECRET_DETECTION) {
expect(wrapper.findByTestId(feature.type).text()).toMatchInterpolatedText(UPGRADE_CTA);
expect(wrapper.text()).toContain(scanner.name);
expect(wrapper.text()).toContain(scanner.description);
if (scanner.type === REPORT_TYPE_SAST) {
expect(wrapper.findByTestId(scanner.type).text()).toBe('Configure via Merge Request');
} else if (scanner.type !== REPORT_TYPE_SECRET_DETECTION) {
expect(wrapper.findByTestId(scanner.type).text()).toMatchInterpolatedText(UPGRADE_CTA);
}
});
it('should show expected help link', () => {
const helpLink = findHelpLinks().at(i);
expect(helpLink.attributes('href')).toBe(feature.helpPath);
expect(helpLink.attributes('href')).toBe(scanner.helpPath);
});
});
});
import { mount } from '@vue/test-utils';
import { UPGRADE_CTA } from '~/security_configuration/components/features_constants';
import { UPGRADE_CTA } from '~/security_configuration/components/scanners_constants';
import Upgrade from '~/security_configuration/components/upgrade.vue';
const TEST_URL = 'http://www.example.test';
......
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