Commit 36a6d04a authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch 'jnnkl-update-profile-information-summary' into 'master'

Update profile information summary for on-demand scans

See merge request gitlab-org/gitlab!64520
parents 336e847d 50307154
<script> <script>
import { SCAN_TYPE_LABEL } from 'ee/security_configuration/dast_scanner_profiles/constants';
import ProfileSelector from './profile_selector.vue'; import ProfileSelector from './profile_selector.vue';
import ScannerProfileSummary from './scanner_profile_summary.vue'; import ScannerProfileSummary from './scanner_profile_summary.vue';
...@@ -37,10 +36,9 @@ export default { ...@@ -37,10 +36,9 @@ export default {
computed: { computed: {
formattedProfiles() { formattedProfiles() {
return this.profiles.map((profile) => { return this.profiles.map((profile) => {
const addSuffix = (str) => `${str} (${SCAN_TYPE_LABEL[profile.scanType]})`;
return { return {
...profile, ...profile,
dropdownLabel: addSuffix(profile.profileName), dropdownLabel: profile.profileName,
}; };
}); });
}, },
......
<script> <script>
import { DAST_SITE_VALIDATION_STATUS } from 'ee/security_configuration/dast_site_validation/constants';
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ProfileSelector from './profile_selector.vue'; import ProfileSelector from './profile_selector.vue';
import SiteProfileSummary from './site_profile_summary.vue'; import SiteProfileSummary from './site_profile_summary.vue';
...@@ -40,14 +38,9 @@ export default { ...@@ -40,14 +38,9 @@ export default {
computed: { computed: {
formattedProfiles() { formattedProfiles() {
return this.profiles.map((profile) => { return this.profiles.map((profile) => {
const isValidated = profile.validationStatus === DAST_SITE_VALIDATION_STATUS.PASSED;
const suffix = isValidated
? s__('DastProfiles|Validated')
: s__('DastProfiles|Not Validated');
const addSuffix = (str) => `${str} (${suffix})`;
return { return {
...profile, ...profile,
dropdownLabel: addSuffix(`${profile.profileName}: ${profile.targetUrl}`), dropdownLabel: `${profile.profileName}: ${profile.targetUrl}`,
}; };
}); });
}, },
......
...@@ -3,6 +3,7 @@ import { ...@@ -3,6 +3,7 @@ import {
EXCLUDED_URLS_SEPARATOR, EXCLUDED_URLS_SEPARATOR,
TARGET_TYPES, TARGET_TYPES,
} from 'ee/security_configuration/dast_site_profiles_form/constants'; } from 'ee/security_configuration/dast_site_profiles_form/constants';
import { DAST_SITE_VALIDATION_STATUS } from 'ee/security_configuration/dast_site_validation/constants';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import ProfileSelectorSummaryCell from './summary_cell.vue'; import ProfileSelectorSummaryCell from './summary_cell.vue';
...@@ -37,9 +38,19 @@ export default { ...@@ -37,9 +38,19 @@ export default {
hasExcludedUrls() { hasExcludedUrls() {
return this.profile.excludedUrls?.length > 0; return this.profile.excludedUrls?.length > 0;
}, },
displayExcludedUrls() {
return this.hasExcludedUrls
? this.profile.excludedUrls.join(this.$options.EXCLUDED_URLS_SEPARATOR)
: undefined;
},
targetTypeValue() { targetTypeValue() {
return TARGET_TYPES[this.profile.targetType].text; return TARGET_TYPES[this.profile.targetType].text;
}, },
isProfileValidated() {
return this.profile.validationStatus === DAST_SITE_VALIDATION_STATUS.PASSED
? s__('DastProfiles|Validated')
: s__('DastProfiles|Not Validated');
},
}, },
EXCLUDED_URLS_SEPARATOR, EXCLUDED_URLS_SEPARATOR,
}; };
...@@ -79,14 +90,19 @@ export default { ...@@ -79,14 +90,19 @@ export default {
</template> </template>
<div class="row"> <div class="row">
<profile-selector-summary-cell <profile-selector-summary-cell
v-if="hasExcludedUrls"
:label="$options.i18n.excludedUrls" :label="$options.i18n.excludedUrls"
:value="profile.excludedUrls.join($options.EXCLUDED_URLS_SEPARATOR)" :value="displayExcludedUrls"
/> />
<profile-selector-summary-cell <profile-selector-summary-cell
v-if="profile.requestHeaders"
:label="$options.i18n.requestHeaders" :label="$options.i18n.requestHeaders"
:value="__('[Redacted]')" :value="profile.requestHeaders ? __('[Redacted]') : undefined"
/>
</div>
<div class="row">
<profile-selector-summary-cell
:label="s__('DastProfiles|Validation status')"
:value="isProfileValidated"
/> />
</div> </div>
</div> </div>
......
<script> <script>
import { __ } from '~/locale';
export default { export default {
name: 'OnDemandScansProfileSummaryCell', name: 'OnDemandScansProfileSummaryCell',
props: { props: {
...@@ -8,7 +10,8 @@ export default { ...@@ -8,7 +10,8 @@ export default {
}, },
value: { value: {
type: String, type: String,
required: true, required: false,
default: __('None'),
}, },
}, },
}; };
...@@ -19,7 +22,7 @@ export default { ...@@ -19,7 +22,7 @@ export default {
<div class="row gl-my-2"> <div class="row gl-my-2">
<div class="col-md-4">{{ label }}:</div> <div class="col-md-4">{{ label }}:</div>
<div class="col-md-8"> <div class="col-md-8">
<strong>{{ value }}</strong> <strong data-testid="summary-value">{{ value }}</strong>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -62,7 +62,7 @@ exports[`OnDemandScansScannerProfileSelector renders properly with profiles 1`] ...@@ -62,7 +62,7 @@ exports[`OnDemandScansScannerProfileSelector renders properly with profiles 1`]
<span <span
class="gl-new-dropdown-button-text" class="gl-new-dropdown-button-text"
> >
Scanner profile #1 (Passive) Scanner profile #1
</span> </span>
<svg <svg
......
...@@ -62,7 +62,7 @@ exports[`OnDemandScansSiteProfileSelector renders properly with profiles 1`] = ` ...@@ -62,7 +62,7 @@ exports[`OnDemandScansSiteProfileSelector renders properly with profiles 1`] = `
<span <span
class="gl-new-dropdown-button-text" class="gl-new-dropdown-button-text"
> >
Site profile #1: https://foo.com (Not Validated) Site profile #1: https://foo.com
</span> </span>
<svg <svg
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DastSiteProfileSummary renders properly 1`] = ` exports[`DastSiteProfileSummary renders properly profile 0 1`] = `
<div> <div>
<div <div
class="row" class="row"
...@@ -67,5 +67,58 @@ exports[`DastSiteProfileSummary renders properly 1`] = ` ...@@ -67,5 +67,58 @@ exports[`DastSiteProfileSummary renders properly 1`] = `
value="[Redacted]" value="[Redacted]"
/> />
</div> </div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Validation status"
value="Not Validated"
/>
</div>
</div>
`;
exports[`DastSiteProfileSummary renders properly profile 1 1`] = `
<div>
<div
class="row"
>
<profile-selector-summary-cell-stub
class=""
label="Target URL"
value="https://bar.com"
/>
<profile-selector-summary-cell-stub
label="Site type"
value="Rest API"
/>
</div>
<!---->
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Excluded URLs"
value="https://bar.com/logout"
/>
<profile-selector-summary-cell-stub
label="Request headers"
value="[Redacted]"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Validation status"
value="Validated"
/>
</div>
</div> </div>
`; `;
...@@ -16,7 +16,9 @@ exports[`OnDemandScansProfileSummaryCell renders properly 1`] = ` ...@@ -16,7 +16,9 @@ exports[`OnDemandScansProfileSummaryCell renders properly 1`] = `
<div <div
class="col-md-8" class="col-md-8"
> >
<strong> <strong
data-testid="summary-value"
>
Row Value Row Value
</strong> </strong>
</div> </div>
......
...@@ -11,8 +11,7 @@ const TEST_ATTRS = { ...@@ -11,8 +11,7 @@ const TEST_ATTRS = {
'data-foo': 'bar', 'data-foo': 'bar',
}; };
const profiles = scannerProfiles.map((x) => { const profiles = scannerProfiles.map((x) => {
const suffix = x.scanType === 'ACTIVE' ? 'Active' : 'Passive'; return { ...x, dropdownLabel: x.profileName };
return { ...x, dropdownLabel: `${x.profileName} (${suffix})` };
}); });
describe('OnDemandScansScannerProfileSelector', () => { describe('OnDemandScansScannerProfileSelector', () => {
...@@ -90,7 +89,6 @@ describe('OnDemandScansScannerProfileSelector', () => { ...@@ -90,7 +89,6 @@ describe('OnDemandScansScannerProfileSelector', () => {
propsData: { profiles }, propsData: { profiles },
}); });
const sel = findProfileSelector(); const sel = findProfileSelector();
expect(sel.props()).toEqual({ expect(sel.props()).toEqual({
libraryPath: TEST_LIBRARY_PATH, libraryPath: TEST_LIBRARY_PATH,
newProfilePath: TEST_NEW_PATH, newProfilePath: TEST_NEW_PATH,
......
...@@ -11,10 +11,9 @@ const TEST_ATTRS = { ...@@ -11,10 +11,9 @@ const TEST_ATTRS = {
'data-foo': 'bar', 'data-foo': 'bar',
}; };
const profiles = siteProfiles.map((x) => { const profiles = siteProfiles.map((x) => {
const suffix = x.validationStatus === 'PASSED_VALIDATION' ? 'Validated' : 'Not Validated';
return { return {
...x, ...x,
dropdownLabel: `${x.profileName}: ${x.targetUrl} (${suffix})`, dropdownLabel: `${x.profileName}: ${x.targetUrl}`,
}; };
}); });
......
...@@ -2,16 +2,13 @@ import { shallowMount } from '@vue/test-utils'; ...@@ -2,16 +2,13 @@ import { shallowMount } from '@vue/test-utils';
import App from 'ee/on_demand_scans/components/profile_selector/site_profile_summary'; import App from 'ee/on_demand_scans/components/profile_selector/site_profile_summary';
import { siteProfiles } from 'ee_jest/on_demand_scans/mocks/mock_data'; import { siteProfiles } from 'ee_jest/on_demand_scans/mocks/mock_data';
const [profile] = siteProfiles;
describe('DastSiteProfileSummary', () => { describe('DastSiteProfileSummary', () => {
let wrapper; let wrapper;
const createWrapper = (props = {}) => { const createWrapper = (profile = {}) => {
wrapper = shallowMount(App, { wrapper = shallowMount(App, {
propsData: { propsData: {
profile, profile,
...props,
}, },
}); });
}; };
...@@ -20,9 +17,11 @@ describe('DastSiteProfileSummary', () => { ...@@ -20,9 +17,11 @@ describe('DastSiteProfileSummary', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders properly', () => { describe('renders properly', () => {
createWrapper(); it.each(siteProfiles)('profile %#', (profile) => {
createWrapper(profile);
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
});
}); });
}); });
import { mount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import OnDemandScansProfileSummaryCell from 'ee/on_demand_scans/components/profile_selector/summary_cell.vue'; import OnDemandScansProfileSummaryCell from 'ee/on_demand_scans/components/profile_selector/summary_cell.vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
describe('OnDemandScansProfileSummaryCell', () => { describe('OnDemandScansProfileSummaryCell', () => {
let wrapper; let wrapper;
const createFullComponent = () => { const createFullComponent = (propsData) => {
wrapper = mount(OnDemandScansProfileSummaryCell, { wrapper = extendedWrapper(
propsData: { shallowMount(OnDemandScansProfileSummaryCell, {
label: 'Row Label', propsData,
value: 'Row Value', }),
}, );
});
}; };
const findValue = () => wrapper.findByTestId('summary-value');
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders properly', () => { it('renders properly', () => {
createFullComponent(); createFullComponent({
label: 'Row Label',
value: 'Row Value',
});
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('renders default when value prop is undefined', () => {
createFullComponent({
label: 'Row Label',
value: undefined,
});
expect(findValue().text()).toContain('None');
});
}); });
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