Commit 980423ff authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '341380-dast-view-scans-edit-view-actions' into 'master'

Add edit and view results links to on-demand scans list

See merge request gitlab-org/gitlab!76532
parents 3505fd98 54d39e51
......@@ -980,6 +980,14 @@ on-demand scans list.
To retry a scan that failed or succeeded with warnings, select **Retry** (**{retry}**) in the
on-demand scans list.
#### View an on-demand scan's results
To view a finished scan's results, select **View results** in the on-demand scans list.
#### Edit an on-demand scan
To edit an on-demand scan's settings, select **Edit** (**{pencil}**) in the **Scheduled** tab.
### Run an on-demand DAST scan
Prerequisites:
......
......@@ -39,10 +39,12 @@ export default {
<template>
<span>
<gl-button
v-bind="$attrs"
:id="buttonId"
:aria-label="label"
:loading="isLoading"
:icon="actionType"
size="small"
@click="onClick"
/>
<gl-tooltip ref="tooltip" :target="buttonId" placement="top" triggers="hover" noninteractive>
......
<script>
import { GlButton } from '@gitlab/ui';
import pipelineCancelMutation from '~/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql';
import pipelineRetryMutation from '~/pipelines/graphql/mutations/retry_pipeline.mutation.graphql';
import { __, s__ } from '~/locale';
......@@ -7,6 +8,7 @@ import {
PIPELINES_GROUP_PENDING,
PIPELINES_GROUP_SUCCESS_WITH_WARNINGS,
PIPELINES_GROUP_FAILED,
PIPELINES_GROUP_SUCCESS,
} from '../constants';
import ActionButton from './action_button.vue';
......@@ -18,6 +20,7 @@ export const retryError = s__('OnDemandScans|The scan could not be retried.');
export default {
components: {
GlButton,
ActionButton,
},
props: {
......@@ -43,6 +46,12 @@ export default {
this.scan?.detailedStatus?.group,
);
},
isEditable() {
return Boolean(this.scan.editPath);
},
hasResults() {
return this.isRetryable || this.scan?.detailedStatus?.group === PIPELINES_GROUP_SUCCESS;
},
},
watch: {
'scan.detailedStatus.group': function detailedStatusGroupWatcher() {
......@@ -98,12 +107,22 @@ export default {
cancelError,
retry: __('Retry'),
retryError,
edit: __('Edit'),
viewResults: s__('OnDemandScans|View results'),
},
};
</script>
<template>
<div class="gl-text-right">
<div class="gl-display-flex gl-justify-content-end">
<gl-button
v-if="hasResults"
data-testid="view-scan-results-button"
size="small"
:href="scan.path"
>
{{ $options.i18n.viewResults }}
</gl-button>
<ActionButton
v-if="isCancellable"
data-testid="cancel-scan-button"
......@@ -114,11 +133,19 @@ export default {
/>
<ActionButton
v-if="isRetryable"
class="gl-ml-3"
data-testid="retry-scan-button"
action-type="retry"
:label="$options.i18n.retry"
:is-loading="isRetrying"
@click="retryPipeline"
/>
<ActionButton
v-if="isEditable"
data-testid="edit-scan-button"
action-type="pencil"
:label="$options.i18n.edit"
:href="scan.editPath"
/>
</div>
</template>
......@@ -146,7 +146,7 @@ export default {
{
label: '',
key: 'actions',
columnClass: 'gl-w-13',
columnClass: 'gl-w-15',
},
].map((field) => ({
...field,
......
......@@ -23,6 +23,7 @@ export const PIPELINES_GROUP_RUNNING = 'running';
export const PIPELINES_GROUP_PENDING = 'pending';
export const PIPELINES_GROUP_SUCCESS_WITH_WARNINGS = 'success-with-warnings';
export const PIPELINES_GROUP_FAILED = 'success-with-warnings';
export const PIPELINES_GROUP_SUCCESS = 'success';
const STATUS_COLUMN = {
label: __('Status'),
......
......@@ -2,10 +2,14 @@
exports[`Actions doesn't render anything if the scan status is not supported 1`] = `
<div
class="gl-text-right"
class="gl-display-flex gl-justify-content-end"
>
<!---->
<!---->
<!---->
<!---->
</div>
`;
......@@ -39,6 +39,7 @@ describe('ActionButton', () => {
it('sets the label on the button and in the tooltip', () => {
createComponent();
expect(findButton().attributes('aria-label')).toBe(label);
expect(findTooltip().text()).toBe(label);
});
......@@ -63,4 +64,13 @@ describe('ActionButton', () => {
expect(findButton().props('loading')).toBe(true);
});
it('passes attributes down to the button', () => {
const href = '/edit/path';
createComponent({
href,
});
expect(findButton().attributes('href')).toBe(href);
});
});
......@@ -6,6 +6,7 @@ import {
PIPELINES_GROUP_PENDING,
PIPELINES_GROUP_SUCCESS_WITH_WARNINGS,
PIPELINES_GROUP_FAILED,
PIPELINES_GROUP_SUCCESS,
} from 'ee/on_demand_scans/constants';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import pipelineCancelMutation from '~/pipelines/graphql/mutations/cancel_pipeline.mutation.graphql';
......@@ -22,11 +23,17 @@ const scanFactory = (group) => ({
detailedStatus: {
group,
},
path: '/pipelines/1',
});
const runningScan = scanFactory(PIPELINES_GROUP_RUNNING);
const pendingScan = scanFactory(PIPELINES_GROUP_PENDING);
const successWithWarningsScan = scanFactory(PIPELINES_GROUP_SUCCESS_WITH_WARNINGS);
const failedScan = scanFactory(PIPELINES_GROUP_FAILED);
const succeededScan = scanFactory(PIPELINES_GROUP_SUCCESS);
const scheduledScan = {
id: mockPipelineId,
editPath: '/edit/1',
};
// Error messages
const errorAsDataMessage = 'Error as data';
......@@ -39,6 +46,8 @@ describe('Actions', () => {
// Finders
const findCancelScanButton = () => wrapper.findByTestId('cancel-scan-button');
const findRetryScanButton = () => wrapper.findByTestId('retry-scan-button');
const findEditScanButton = () => wrapper.findByTestId('edit-scan-button');
const findViewScanResultsButton = () => wrapper.findByTestId('view-scan-results-button');
// Helpers
const createMockApolloProvider = (mutation, handler) => {
......@@ -139,4 +148,25 @@ describe('Actions', () => {
});
});
});
it('renders an edit link for scheduled scans', () => {
createComponent(scheduledScan);
const editButton = findEditScanButton();
expect(editButton.exists()).toBe(true);
expect(editButton.attributes('href')).toBe(scheduledScan.editPath);
});
it.each`
scanStatus | scan
${'success with warnings'} | ${successWithWarningsScan}
${'failed'} | ${failedScan}
${'succeeded'} | ${succeededScan}
`('renders a "View results" button for $scanStatus scans', ({ scan }) => {
createComponent(scan);
const viewScanResultsButton = findViewScanResultsButton();
expect(viewScanResultsButton.exists()).toBe(true);
expect(viewScanResultsButton.attributes('href')).toBe(scan.path);
});
});
......@@ -24508,6 +24508,9 @@ msgstr ""
msgid "OnDemandScans|Use existing site profile"
msgstr ""
msgid "OnDemandScans|View results"
msgstr ""
msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
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