Commit 7096ea8d authored by Brandon Labuschagne's avatar Brandon Labuschagne

Merge branch '323376-security-configuration-ui-strings-ssot' into 'master'

Move Security Configuration UI strings to frontend

See merge request gitlab-org/gitlab!56022
parents 02fc8956 24abff05
<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"
<configuration-table
:features="featuresForDisplay"
:auto-devops-enabled="autoDevopsEnabled"
: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>
<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 } });
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(getFeaturesTable().classes('b-table-stacked-md')).toBeTruthy();
const rows = getFeaturesRows();
expect(rows).toHaveLength(5);
it('passes the expected props data to the configuration table', () => {
createComponent();
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],
expect(getConfigurationTable().props()).toMatchObject({
autoDevopsEnabled: propsData.autoDevopsEnabled,
gitlabCiPresent: propsData.gitlabCiPresent,
gitlabCiHistoryPath: propsData.gitlabCiHistoryPath,
});
expect(manage.find(ManageFeature).props()).toEqual({
feature: features[i],
autoDevopsEnabled: propsData.autoDevopsEnabled,
});
expect(feature.find(GlLink).props('href')).toBe(features[i].href);
}
});
});
});
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