Commit 9b046ea8 authored by Daniel Tian's avatar Daniel Tian Committed by Kushal Pandya

Improve security dashboard/vulnerability report empty state messages

Updates the text and standardizes the styling of the "not configured"
empty state messages for the project, group, and instance-level security
dashboard and vulnerability report pages.
parent 2f21b551
......@@ -136,10 +136,6 @@ bar at the top of the page. Under **More**, select **Security**.
![Security Center navigation link](img/security_center_dashboard_link_v12_4.png)
The dashboard and vulnerability report are empty before you add projects.
![Uninitialized Security Center](img/security_center_dashboard_empty_v13_4.png)
### Adding projects to the Security Center
To add projects to the Security Center:
......
<script>
import { GlEmptyState } from '@gitlab/ui';
import { s__ } from '~/locale';
export default {
components: {
GlEmptyState,
},
inject: ['emptyStateSvgPath', 'dashboardDocumentation'],
i18n: {
title: s__('SecurityReports|No vulnerabilities found'),
primaryButtonText: s__('SecurityReports|Learn more about setting up your dashboard'),
description: s__(
`SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly.`,
),
},
};
</script>
<template>
<gl-empty-state
:title="s__(`SecurityReports|No vulnerabilities found`)"
:title="$options.i18n.title"
:svg-path="emptyStateSvgPath"
:primary-button-link="dashboardDocumentation"
:primary-button-text="s__('SecurityReports|Learn more about setting up your dashboard')"
:description="
s__(
`SecurityReports|While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly.`,
)
"
:primary-button-text="$options.i18n.primaryButtonText"
:description="$options.i18n.description"
/>
</template>
<script>
import { GlEmptyState } from '@gitlab/ui';
import { GlEmptyState, GlButton } from '@gitlab/ui';
import { s__, __ } from '~/locale';
export default {
components: {
GlEmptyState,
GlButton,
},
inject: ['dashboardDocumentation', 'emptyStateSvgPath'],
i18n: {
title: s__('SecurityReports|Monitor vulnerabilities in your group'),
description: s__(
'SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured.',
),
secondaryButtonText: __('Learn more'),
},
};
</script>
<template>
<gl-empty-state
:title="s__('SecurityReports|Add projects to your group')"
:description="
s__(
'SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here.',
)
"
:primary-button-link="dashboardDocumentation"
:primary-button-text="s__('SecurityReports|Learn more about setting up your dashboard')"
:title="$options.i18n.title"
:svg-path="emptyStateSvgPath"
/>
:description="$options.i18n.description"
>
<template #actions>
<gl-button :href="dashboardDocumentation">{{ $options.i18n.secondaryButtonText }}</gl-button>
</template>
</gl-empty-state>
</template>
<script>
import { GlButton, GlEmptyState, GlLink } from '@gitlab/ui';
import { GlEmptyState } from '@gitlab/ui';
import { s__, __ } from '~/locale';
export default {
components: {
GlEmptyState,
GlButton,
GlLink,
},
inject: ['dashboardDocumentation', 'emptyStateSvgPath', 'instanceDashboardSettingsPath'],
i18n: {
title: s__('SecurityReports|Monitor vulnerabilities in all of your projects'),
description: s__(
'SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here.',
),
primaryButtonText: s__('Add projects'),
secondaryButtonText: __('Learn more'),
},
};
</script>
<template>
<gl-empty-state
:title="s__('SecurityReports|Add a project to your dashboard')"
:title="$options.i18n.title"
:svg-path="emptyStateSvgPath"
>
<template #description>
{{
s__(
'SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Select "Edit dashboard" to add and remove projects.',
)
}}
<gl-link :href="dashboardDocumentation">{{
s__('SecurityReports|More information')
}}</gl-link>
</template>
<template #actions>
<gl-button variant="success" :href="instanceDashboardSettingsPath">
{{ s__('SecurityReports|Add projects') }}
</gl-button>
</template>
</gl-empty-state>
:description="$options.i18n.description"
:primary-button-text="$options.i18n.primaryButtonText"
:primary-button-link="instanceDashboardSettingsPath"
:secondary-button-text="$options.i18n.secondaryButtonText"
:secondary-button-link="dashboardDocumentation"
/>
</template>
<script>
import { GlEmptyState } from '@gitlab/ui';
import { s__ } from '~/locale';
import { s__, __ } from '~/locale';
export default {
components: {
GlEmptyState,
},
inject: ['emptyStateSvgPath'],
inject: ['emptyStateSvgPath', 'securityConfigurationPath'],
props: {
helpPath: {
type: String,
required: true,
},
},
DESCRIPTION: s__(
`SecurityReports|The security dashboard displays the latest security report. Use it to find and fix vulnerabilities.`,
),
i18n: {
title: s__('SecurityReports|Monitor vulnerabilities in your project'),
description: s__(
'SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured.',
),
primaryButtonText: s__('SecurityReports|Configure security testing'),
secondaryButtonText: __('Learn more'),
},
};
</script>
<template>
<gl-empty-state
:title="s__('SecurityReports|Monitor vulnerabilities in your code')"
:title="$options.i18n.title"
:svg-path="emptyStateSvgPath"
:description="$options.DESCRIPTION"
:primary-button-link="helpPath"
:primary-button-text="__('Learn more')"
:description="$options.i18n.description"
:primary-button-text="$options.i18n.primaryButtonText"
:primary-button-link="securityConfigurationPath"
:secondary-button-text="$options.i18n.secondaryButtonText"
:secondary-button-link="helpPath"
/>
</template>
......@@ -54,7 +54,7 @@ export default {
};
},
computed: {
isNotYetConfigured() {
hasNoProjects() {
return this.projects.length === 0 && this.projectsWereFetched;
},
},
......@@ -70,22 +70,20 @@ export default {
<template>
<div>
<gl-loading-icon v-if="!projectsWereFetched" size="lg" class="gl-mt-6" />
<dashboard-not-configured v-if="isNotYetConfigured" />
<security-dashboard-layout v-else :class="{ 'gl-display-none': !projectsWereFetched }">
<dashboard-not-configured v-else-if="hasNoProjects" />
<security-dashboard-layout v-else>
<template #header>
<div>
<header class="gl-my-6 gl-display-flex gl-align-items-center">
<h2 class="gl-flex-grow-1 gl-my-0">
{{ s__('SecurityReports|Vulnerability Report') }}
</h2>
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
</header>
<vulnerabilities-count-list
:scope="$options.vulnerabilitiesSeverityCountScopes.group"
:full-path="groupFullPath"
:filters="filters"
/>
</div>
<header class="gl-my-6 gl-display-flex gl-align-items-center">
<h2 class="gl-flex-grow-1 gl-my-0">
{{ s__('SecurityReports|Vulnerability Report') }}
</h2>
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
</header>
<vulnerabilities-count-list
:scope="$options.vulnerabilitiesSeverityCountScopes.group"
:full-path="groupFullPath"
:filters="filters"
/>
</template>
<template #sticky>
<filters :projects="projects" @filterChange="handleFilterChange" />
......
......@@ -67,19 +67,17 @@ export default {
<template>
<security-dashboard-layout>
<dashboard-not-configured v-if="shouldShowEmptyState" />
<template #header>
<div>
<header class="gl-my-6 gl-display-flex gl-align-items-center">
<div v-if="shouldShowDashboard">
<header class="gl-my-6 gl-display-flex gl-align-items-center" data-testid="header">
<h2 class="gl-flex-grow-1 gl-my-0">
{{ s__('SecurityReports|Vulnerability Report') }}
</h2>
<csv-export-button
v-if="shouldShowDashboard"
:vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint"
/>
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
</header>
<vulnerabilities-count-list
v-if="shouldShowDashboard"
:scope="$options.vulnerabilitiesSeverityCountScopes.instance"
:filters="filters"
/>
......@@ -93,6 +91,5 @@ export default {
:projects="projects"
:filters="filters"
/>
<dashboard-not-configured v-else-if="shouldShowEmptyState" />
</security-dashboard-layout>
</template>
......@@ -134,7 +134,7 @@ export default {
<template v-if="shouldShowEmptyState" #empty-state>
<dashboard-not-configured :help-path="helpPath" />
</template>
<template v-else-if="shouldShowCharts">
<template v-else-if="shouldShowCharts" #default>
<gl-line-chart
class="gl-mt-6"
:width="chartWidth"
......
......@@ -9,12 +9,16 @@ export default {
</script>
<template>
<div data-testid="security-charts-layout">
<h2>{{ $options.i18n.title }}</h2>
<div>
<slot name="loading"></slot>
<div class="security-charts gl-display-flex gl-flex-wrap">
<slot></slot>
</div>
<template v-if="$slots.default">
<h2 data-testid="title">{{ $options.i18n.title }}</h2>
<div class="security-charts gl-display-flex gl-flex-wrap">
<slot></slot>
</div>
</template>
<slot name="empty-state"></slot>
</div>
</template>
......@@ -38,6 +38,7 @@ export default (el, dashboardType) => {
pipelineSecurityBuildsFailedCount,
pipelineSecurityBuildsFailedPath,
hasJiraVulnerabilitiesIntegrationEnabled,
securityConfigurationPath,
} = el.dataset;
if (isUnavailable) {
......@@ -60,6 +61,7 @@ export default (el, dashboardType) => {
emptyStateSvgPath,
notEnabledScannersHelpPath,
noPipelineRunScannersHelpPath,
securityConfigurationPath,
hasVulnerabilities: parseBoolean(hasVulnerabilities),
scanners: scanners ? JSON.parse(scanners) : [],
hasJiraVulnerabilitiesIntegrationEnabled: parseBoolean(
......
......@@ -32,6 +32,7 @@ export default (el, dashboardType) => {
const provide = {
dashboardDocumentation: el.dataset.dashboardDocumentation,
emptyStateSvgPath: el.dataset.emptyStateSvgPath,
securityConfigurationPath: el.dataset.securityConfigurationPath,
};
let component;
......
......@@ -258,7 +258,8 @@ module EE
empty_state_svg_path: image_path('illustrations/security-dashboard_empty.svg'),
security_dashboard_help_path: help_page_path('user/application_security/security_dashboard/index'),
no_vulnerabilities_svg_path: image_path('illustrations/issues.svg'),
project_full_path: project.full_path
project_full_path: project.full_path,
security_configuration_path: project_security_configuration_path(@project)
}.merge!(security_dashboard_pipeline_data(project))
else
{
......
---
title: Improve security dashboard/vulnerability report empty state messages
merge_request: 55489
author:
type: changed
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`dashboard has no vulnerabilities empty state matches snapshot 1`] = `
"<section class=\\"row empty-state text-center\\">
<div class=\\"col-12\\">
<div class=\\"svg-250 svg-content\\"><img src=\\"/placeholder.svg\\" alt=\\"\\" class=\\"gl-max-w-full\\"></div>
</div>
<div class=\\"col-12\\">
<div class=\\"text-content gl-mx-auto gl-my-0 gl-p-5\\">
<h1 class=\\"h4\\">No vulnerabilities found</h1>
<p>
Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly.
</p>
<div><a href=\\"/path/to/dashboard/documentation\\" class=\\"btn btn-success btn-md gl-button\\">
<!---->
<!----> <span class=\\"gl-button-text\\">Learn more about setting up your dashboard</span></a>
<!---->
</div>
</div>
</div>
</section>"
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`first class group security dashboard empty state matches snapshot 1`] = `
"<gl-empty-state-stub title=\\"Monitor vulnerabilities in your group\\" svgpath=\\"/placeholder.svg\\" description=\\"Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured.\\">
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" href=\\"/path/to/dashboard/documentation\\">Learn more</gl-button-stub>
</gl-empty-state-stub>"
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`first class instance security dashboard empty state matches snapshot 1`] = `"<gl-empty-state-stub title=\\"Monitor vulnerabilities in all of your projects\\" svgpath=\\"/placeholder.svg\\" description=\\"Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here.\\" primarybuttonlink=\\"/path/to/dashboard/settings\\" primarybuttontext=\\"Add projects\\" secondarybuttonlink=\\"/path/to/dashboard/documentation\\" secondarybuttontext=\\"Learn more\\"></gl-empty-state-stub>"`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`reports not configured empty state matches snapshot 1`] = `"<gl-empty-state-stub title=\\"Monitor vulnerabilities in your project\\" svgpath=\\"/placeholder.svg\\" description=\\"Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured.\\" primarybuttonlink=\\"/configuration\\" primarybuttontext=\\"Configure security testing\\" secondarybuttonlink=\\"/help\\" secondarybuttontext=\\"Learn more\\"></gl-empty-state-stub>"`;
import { GlEmptyState, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import DashboardHasNoVulnerabilities from 'ee/security_dashboard/components/empty_states/dashboard_has_no_vulnerabilities.vue';
......@@ -15,10 +14,6 @@ describe('dashboard has no vulnerabilities empty state', () => {
},
});
const findGlEmptyState = () => wrapper.find(GlEmptyState);
const findButton = () => wrapper.find(GlButton);
const findLink = () => wrapper.find('a');
beforeEach(() => {
wrapper = createWrapper();
});
......@@ -27,26 +22,7 @@ describe('dashboard has no vulnerabilities empty state', () => {
wrapper.destroy();
});
it('contains a GlEmptyState', () => {
expect(findGlEmptyState().exists()).toBe(true);
expect(findGlEmptyState().props('svgPath')).toBe(emptyStateSvgPath);
});
it('contains a GlLink with href attribute equal to dashboardDocumentation', () => {
expect(findLink().attributes('href')).toBe(dashboardDocumentation);
});
it('contains a GlButton', () => {
expect(findButton().exists()).toBe(true);
});
it('has the correct message', () => {
expect(findGlEmptyState().text()).toContain(
"While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly.",
);
});
it('has the correct title', () => {
expect(findGlEmptyState().text()).toContain('No vulnerabilities found');
it('matches snapshot', () => {
expect(wrapper.html()).toMatchSnapshot();
});
});
import { GlEmptyState, GlButton } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import DashboardNotConfigured from 'ee/security_dashboard/components/empty_states/group_dashboard_not_configured.vue';
describe('first class group security dashboard empty state', () => {
......@@ -8,17 +7,13 @@ describe('first class group security dashboard empty state', () => {
const emptyStateSvgPath = '/placeholder.svg';
const createWrapper = () =>
mount(DashboardNotConfigured, {
shallowMount(DashboardNotConfigured, {
provide: {
dashboardDocumentation,
emptyStateSvgPath,
},
});
const findGlEmptyState = () => wrapper.find(GlEmptyState);
const findButton = () => wrapper.find(GlButton);
const findLink = () => wrapper.find('a');
beforeEach(() => {
wrapper = createWrapper();
});
......@@ -27,26 +22,7 @@ describe('first class group security dashboard empty state', () => {
wrapper.destroy();
});
it('contains a GlEmptyState', () => {
expect(findGlEmptyState().exists()).toBe(true);
expect(findGlEmptyState().props('svgPath')).toBe(emptyStateSvgPath);
});
it('contains a GlLink with href attribute equal to dashboardDocumentation', () => {
expect(findLink().attributes('href')).toBe(dashboardDocumentation);
});
it('contains a GlButton', () => {
expect(findButton().exists()).toBe(true);
});
it('has the correct message', () => {
expect(findGlEmptyState().text()).toContain(
'The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here.',
);
});
it('has the correct title', () => {
expect(findGlEmptyState().text()).toContain('Add projects to your group');
it('matches snapshot', () => {
expect(wrapper.html()).toMatchSnapshot();
});
});
import { GlEmptyState, GlButton, GlLink } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import DashboardNotConfigured from 'ee/security_dashboard/components/empty_states/instance_dashboard_not_configured.vue';
describe('first class instance security dashboard empty state', () => {
......@@ -9,7 +8,7 @@ describe('first class instance security dashboard empty state', () => {
const emptyStateSvgPath = '/placeholder.svg';
const createWrapper = () =>
mount(DashboardNotConfigured, {
shallowMount(DashboardNotConfigured, {
provide: {
dashboardDocumentation,
emptyStateSvgPath,
......@@ -17,10 +16,6 @@ describe('first class instance security dashboard empty state', () => {
},
});
const findGlEmptyState = () => wrapper.find(GlEmptyState);
const findButton = () => wrapper.find(GlButton);
const findLink = () => wrapper.find(GlLink);
beforeEach(() => {
wrapper = createWrapper();
});
......@@ -29,16 +24,7 @@ describe('first class instance security dashboard empty state', () => {
wrapper.destroy();
});
it('contains a GlEmptyState', () => {
expect(findGlEmptyState().exists()).toBe(true);
expect(findGlEmptyState().props('svgPath')).toBe(emptyStateSvgPath);
});
it('contains a GlLink with href attribute equal to dashboardDocumentation', () => {
expect(findLink().attributes('href')).toBe(dashboardDocumentation);
});
it('contains a GlButton with a link to settings page', () => {
expect(findButton().attributes('href')).toBe(instanceDashboardSettingsPath);
it('matches snapshot', () => {
expect(wrapper.html()).toMatchSnapshot();
});
});
import { GlEmptyState } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import ReportsNotConfigured from 'ee/security_dashboard/components/empty_states/reports_not_configured.vue';
......@@ -6,29 +5,23 @@ describe('reports not configured empty state', () => {
let wrapper;
const helpPath = '/help';
const emptyStateSvgPath = '/placeholder.svg';
const securityConfigurationPath = '/configuration';
const createComponent = () => {
wrapper = shallowMount(ReportsNotConfigured, {
provide: {
emptyStateSvgPath,
securityConfigurationPath,
},
propsData: { helpPath },
});
};
const findEmptyState = () => wrapper.find(GlEmptyState);
beforeEach(() => {
createComponent();
});
it.each`
prop | data
${'title'} | ${'Monitor vulnerabilities in your code'}
${'svgPath'} | ${emptyStateSvgPath}
${'description'} | ${'The security dashboard displays the latest security report. Use it to find and fix vulnerabilities.'}
${'primaryButtonLink'} | ${helpPath}
${'primaryButtonText'} | ${'Learn more'}
`('passes the correct data to the $prop prop', ({ prop, data }) => {
expect(findEmptyState().props(prop)).toBe(data);
it('matches snapshot', () => {
expect(wrapper.html()).toMatchSnapshot();
});
});
......@@ -52,10 +52,6 @@ describe('First Class Group Dashboard Component', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
it('dashboard should have display none because it needs to fetch the projects', () => {
expect(findDashboardLayout().attributes('class')).toEqual('gl-display-none');
});
it('should not display the dashboard not configured component', () => {
expect(findEmptyState().exists()).toBe(false);
});
......@@ -103,10 +99,6 @@ describe('First Class Group Dashboard Component', () => {
expect(findLoadingIcon().exists()).toBe(false);
});
it('dashboard should no more have display none', () => {
expect(findDashboardLayout().attributes('class')).toEqual('');
});
it('should not display the dashboard not configured component', () => {
expect(findEmptyState().exists()).toBe(false);
});
......
import { within } from '@testing-library/dom';
import { shallowMount } from '@vue/test-utils';
import CsvExportButton from 'ee/security_dashboard/components/csv_export_button.vue';
import DashboardNotConfigured from 'ee/security_dashboard/components/empty_states/instance_dashboard_not_configured.vue';
......@@ -22,6 +21,7 @@ describe('First Class Instance Dashboard Component', () => {
const findEmptyState = () => wrapper.find(DashboardNotConfigured);
const findFilters = () => wrapper.find(Filters);
const findVulnerabilitiesCountList = () => wrapper.find(VulnerabilitiesCountList);
const findHeader = () => wrapper.find('[data-testid="header"]');
const createWrapper = ({ data = {}, stubs, mocks = defaultMocks() }) => {
return shallowMount(FirstClassInstanceDashboard, {
......@@ -53,6 +53,10 @@ describe('First Class Instance Dashboard Component', () => {
});
});
it('should show the header', () => {
expect(findHeader().exists()).toBe(true);
});
it('should render the vulnerabilities', () => {
expect(findInstanceVulnerabilities().props()).toEqual({
filters: {},
......@@ -96,12 +100,10 @@ describe('First Class Instance Dashboard Component', () => {
});
});
it('does not render the export button', () => {
it('does not render the export button, vulnerabilities count list, or header', () => {
expect(findCsvExportButton().exists()).toBe(false);
});
it('does not render the vulnerabilities count list', () => {
expect(findVulnerabilitiesCountList().exists()).toBe(false);
expect(findHeader().exists()).toBe(false);
});
});
......@@ -114,36 +116,13 @@ describe('First Class Instance Dashboard Component', () => {
});
});
it('renders the empty state', () => {
expect(findEmptyState().props()).toEqual({});
});
it('does not render the export button', () => {
it('only renders the empty state', () => {
expect(findEmptyState().exists()).toBe(true);
expect(findCsvExportButton().exists()).toBe(false);
});
it('does not render the vulnerability list', () => {
expect(findInstanceVulnerabilities().exists()).toBe(false);
});
it('has no filters', () => {
expect(findFilters().exists()).toBe(false);
});
it('does not render the vulnerabilities count list', () => {
expect(findVulnerabilitiesCountList().exists()).toBe(false);
});
});
describe('always', () => {
beforeEach(() => {
wrapper = createWrapper({});
});
it('has the security dashboard title', () => {
expect(
within(wrapper.element).getByRole('heading', { name: 'Vulnerability Report' }),
).not.toBe(null);
expect(findHeader().exists()).toBe(false);
});
});
});
import { shallowMount } from '@vue/test-utils';
import SecurityChartsLayout from 'ee/security_dashboard/components/security_charts_layout.vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe('Security Charts Layout component', () => {
let wrapper;
const DummyComponent1 = {
const DummyComponent = {
name: 'dummy-component-1',
template: '<p>dummy component 1</p>',
};
const DummyComponent2 = {
name: 'dummy-component-2',
template: '<p>dummy component 2</p>',
};
const findSlot = () => wrapper.find(`[data-testid="security-charts-layout"]`);
const findDummyComponent = () => wrapper.findComponent(DummyComponent);
const findTitle = () => wrapper.findByTestId('title');
const createWrapper = (slots) => {
wrapper = shallowMount(SecurityChartsLayout, { slots });
wrapper = extendedWrapper(shallowMount(SecurityChartsLayout, { slots }));
};
beforeEach(() => {
createWrapper({ default: DummyComponent1, 'empty-state': DummyComponent2 });
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('should render the default slot', () => {
const slot = findSlot();
expect(slot.find(DummyComponent1).exists()).toBe(true);
createWrapper({ default: DummyComponent });
expect(findDummyComponent().exists()).toBe(true);
expect(findTitle().exists()).toBe(true);
});
it('should render the empty-state slot', () => {
const slot = findSlot();
expect(slot.find(DummyComponent2).exists()).toBe(true);
createWrapper({ 'empty-state': DummyComponent });
expect(findDummyComponent().exists()).toBe(true);
expect(findTitle().exists()).toBe(false);
});
it('should render the loading slot', () => {
createWrapper({ loading: DummyComponent });
expect(findDummyComponent().exists()).toBe(true);
expect(findTitle().exists()).toBe(false);
});
});
......@@ -2,12 +2,7 @@
exports[`Security Charts default states sets up group-level 1`] = `
<div>
<div
data-testid="security-charts-layout"
>
<h2>
Security Dashboard
</h2>
<div>
<div
class="gl-spinner-container gl-mt-6"
>
......@@ -16,21 +11,13 @@ exports[`Security Charts default states sets up group-level 1`] = `
class="align-text-bottom gl-spinner gl-spinner-dark gl-spinner-lg"
/>
</div>
<div
class="security-charts gl-display-flex gl-flex-wrap"
/>
</div>
</div>
`;
exports[`Security Charts default states sets up instance-level 1`] = `
<div>
<div
data-testid="security-charts-layout"
>
<h2>
Security Dashboard
</h2>
<div>
<div
class="gl-spinner-container gl-mt-6"
>
......@@ -39,9 +26,6 @@ exports[`Security Charts default states sets up instance-level 1`] = `
class="align-text-bottom gl-spinner gl-spinner-dark gl-spinner-lg"
/>
</div>
<div
class="security-charts gl-display-flex gl-flex-wrap"
/>
</div>
</div>
`;
......
......@@ -137,7 +137,8 @@ RSpec.describe ProjectsHelper do
empty_state_svg_path: start_with('/assets/illustrations/security-dashboard_empty'),
security_dashboard_help_path: '/help/user/application_security/security_dashboard/index',
project_full_path: project.full_path,
no_vulnerabilities_svg_path: start_with('/assets/illustrations/issues-')
no_vulnerabilities_svg_path: start_with('/assets/illustrations/issues-'),
security_configuration_path: end_with('/configuration')
}
end
......
......@@ -1935,6 +1935,9 @@ msgstr ""
msgid "Add previously merged commits"
msgstr ""
msgid "Add projects"
msgstr ""
msgid "Add reaction"
msgstr ""
......@@ -26812,19 +26815,16 @@ msgstr ""
msgid "SecurityReports|%{firstProject}, %{secondProject}, and %{rest}"
msgstr ""
msgid "SecurityReports|Add a project to your dashboard"
msgstr ""
msgid "SecurityReports|Add or remove projects to monitor in the security area. Projects included in this list will have their results displayed in the security dashboard and vulnerability report."
msgstr ""
msgid "SecurityReports|Add projects"
msgstr ""
msgid "SecurityReports|Add projects to your group"
msgid "SecurityReports|All"
msgstr ""
msgid "SecurityReports|All"
msgid "SecurityReports|Although it's rare to have no vulnerabilities, it can happen. Check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|Change status"
......@@ -26839,6 +26839,9 @@ msgstr ""
msgid "SecurityReports|Comment edited on '%{vulnerabilityName}'"
msgstr ""
msgid "SecurityReports|Configure security testing"
msgstr ""
msgid "SecurityReports|Create Jira issue"
msgstr ""
......@@ -26896,16 +26899,28 @@ msgstr ""
msgid "SecurityReports|Learn more about setting up your dashboard"
msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your code"
msgid "SecurityReports|Manage and track vulnerabilities identified in projects within your group. Vulnerabilities in projects are shown here when security testing is configured."
msgstr ""
msgid "SecurityReports|Monitored projects"
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr ""
msgid "SecurityReports|More info"
msgid "SecurityReports|Manage and track vulnerabilities identified in your selected projects. Vulnerabilities for selected projects with security testing configured are shown here."
msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr ""
msgid "SecurityReports|Monitor vulnerabilities in your group"
msgstr ""
msgid "SecurityReports|More information"
msgid "SecurityReports|Monitor vulnerabilities in your project"
msgstr ""
msgid "SecurityReports|Monitored projects"
msgstr ""
msgid "SecurityReports|More info"
msgstr ""
msgid "SecurityReports|No activity"
......@@ -26971,15 +26986,6 @@ msgstr ""
msgid "SecurityReports|Status"
msgstr ""
msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Add projects to your group to view their vulnerabilities here."
msgstr ""
msgid "SecurityReports|The security dashboard displays the latest security findings for projects you wish to monitor. Select \"Edit dashboard\" to add and remove projects."
msgstr ""
msgid "SecurityReports|The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
msgstr ""
msgid "SecurityReports|There was an error adding the comment."
msgstr ""
......@@ -27031,9 +27037,6 @@ msgstr ""
msgid "SecurityReports|While it's rare to have no vulnerabilities for your pipeline, it can happen. In any event, we ask that you double check your settings to make sure all security scanning jobs have passed successfully."
msgstr ""
msgid "SecurityReports|While it's rare to have no vulnerabilities, it can happen. In any event, we ask that you double check your settings to make sure you've set up your dashboard correctly."
msgstr ""
msgid "SecurityReports|With issues"
msgstr ""
......
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