Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
87b94d7c
Commit
87b94d7c
authored
Sep 22, 2020
by
Paul Gascou-Vaillancourt
Committed by
Paul Slaughter
Sep 22, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create profile selector component
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41922
parent
6e876f29
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1346 additions
and
0 deletions
+1346
-0
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/profile_selector.vue
...nd_scans/components/profile_selector/profile_selector.vue
+109
-0
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/scanner_profile_selector.vue
.../components/profile_selector/scanner_profile_selector.vue
+61
-0
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/site_profile_selector.vue
...ans/components/profile_selector/site_profile_selector.vue
+56
-0
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/summary_cell.vue
...demand_scans/components/profile_selector/summary_cell.vue
+26
-0
ee/app/assets/javascripts/on_demand_scans/settings.js
ee/app/assets/javascripts/on_demand_scans/settings.js
+31
-0
ee/spec/frontend/on_demand_scans/components/profile_selector/__snapshots__/scanner_profile_selector_spec.js.snap
...ector/__snapshots__/scanner_profile_selector_spec.js.snap
+355
-0
ee/spec/frontend/on_demand_scans/components/profile_selector/__snapshots__/site_profile_selector_spec.js.snap
...selector/__snapshots__/site_profile_selector_spec.js.snap
+307
-0
ee/spec/frontend/on_demand_scans/components/profile_selector/__snapshots__/summary_cell_spec.js.snap
.../profile_selector/__snapshots__/summary_cell_spec.js.snap
+10
-0
ee/spec/frontend/on_demand_scans/components/profile_selector/profile_selector_spec.js
...cans/components/profile_selector/profile_selector_spec.js
+154
-0
ee/spec/frontend/on_demand_scans/components/profile_selector/scanner_profile_selector_spec.js
...ponents/profile_selector/scanner_profile_selector_spec.js
+88
-0
ee/spec/frontend/on_demand_scans/components/profile_selector/site_profile_selector_spec.js
...components/profile_selector/site_profile_selector_spec.js
+91
-0
ee/spec/frontend/on_demand_scans/components/profile_selector/summary_cell_spec.js
...nd_scans/components/profile_selector/summary_cell_spec.js
+25
-0
ee/spec/frontend/on_demand_scans/mock_data.js
ee/spec/frontend/on_demand_scans/mock_data.js
+27
-0
locale/gitlab.pot
locale/gitlab.pot
+6
-0
No files found.
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/profile_selector.vue
0 → 100644
View file @
87b94d7c
<
script
>
import
{
GlButton
,
GlCard
,
GlFormGroup
,
GlDropdown
,
GlDropdownItem
}
from
'
@gitlab/ui
'
;
export
default
{
name
:
'
OnDemandScansProfileSelector
'
,
components
:
{
GlButton
,
GlCard
,
GlFormGroup
,
GlDropdown
,
GlDropdownItem
,
},
props
:
{
libraryPath
:
{
type
:
String
,
required
:
true
,
},
newProfilePath
:
{
type
:
String
,
required
:
true
,
},
profiles
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
value
:
{
type
:
String
,
required
:
false
,
default
:
null
,
},
},
computed
:
{
selectedProfile
()
{
return
this
.
value
?
this
.
profiles
.
find
(({
id
})
=>
this
.
value
===
id
)
:
null
;
},
},
};
</
script
>
<
template
>
<gl-card>
<template
#header
>
<div
class=
"row"
>
<div
class=
"col-7"
>
<h3
class=
"gl-font-lg gl-display-inline"
>
<slot
name=
"title"
></slot>
</h3>
</div>
<div
class=
"col-5 gl-text-right"
>
<gl-button
:href=
"profiles.length ? libraryPath : null"
:disabled=
"!profiles.length"
variant=
"success"
category=
"secondary"
size=
"small"
data-testid=
"manage-profiles-link"
>
{{
s__
(
'
OnDemandScans|Manage profiles
'
)
}}
</gl-button>
</div>
</div>
</
template
>
<gl-form-group
v-if=
"profiles.length"
>
<
template
#label
>
<slot
name=
"label"
></slot>
</
template
>
<gl-dropdown
:text=
"
selectedProfile
? selectedProfile.dropdownLabel
: s__('OnDemandScans|Select one of the existing profiles')
"
class=
"mw-460"
data-testid=
"profiles-dropdown"
>
<gl-dropdown-item
v-for=
"profile in profiles"
:key=
"profile.id"
:is-checked=
"value === profile.id"
is-check-item
@
click=
"$emit('input', profile.id)"
>
{{ profile.profileName }}
</gl-dropdown-item>
</gl-dropdown>
<div
v-if=
"selectedProfile && $scopedSlots.summary"
data-testid=
"selected-profile-summary"
class=
"gl-mt-6 gl-pt-6 gl-border-t-solid gl-border-gray-100 gl-border-t-1"
>
<slot
name=
"summary"
:profile=
"selectedProfile"
></slot>
</div>
</gl-form-group>
<
template
v-else
>
<p
class=
"gl-text-gray-700"
>
<slot
name=
"no-profiles"
></slot>
</p>
<gl-button
:href=
"newProfilePath"
variant=
"success"
category=
"secondary"
data-testid=
"create-profile-link"
>
<slot
name=
"new-profile"
></slot>
</gl-button>
</
template
>
</gl-card>
</template>
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/scanner_profile_selector.vue
0 → 100644
View file @
87b94d7c
<
script
>
import
ProfileSelector
from
'
./profile_selector.vue
'
;
import
SummaryCell
from
'
./summary_cell.vue
'
;
export
default
{
name
:
'
OnDemandScansScannerProfileSelector
'
,
components
:
{
ProfileSelector
,
SummaryCell
,
},
props
:
{
profiles
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
},
inject
:
{
scannerProfilesLibraryPath
:
{
default
:
''
,
},
newScannerProfilePath
:
{
default
:
''
,
},
},
};
</
script
>
<
template
>
<profile-selector
:library-path=
"scannerProfilesLibraryPath"
:new-profile-path=
"newScannerProfilePath"
:profiles=
"profiles.map(profile => (
{ ...profile, dropdownLabel: profile.profileName }))"
v-bind="$attrs"
v-on="$listeners"
>
<template
#title
>
{{
s__
(
'
OnDemandScans|Scanner profile
'
)
}}
</
template
>
<
template
#label
>
{{
s__
(
'
OnDemandScans|Use existing scanner profile
'
)
}}
</
template
>
<
template
#no-profiles
>
{{
s__
(
'
OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed scanner profile.
'
,
)
}}
</
template
>
<
template
#new-profile
>
{{
s__
(
'
OnDemandScans|Create a new scanner profile
'
)
}}
</
template
>
<
template
#summary=
"{ profile }"
>
<div
class=
"row"
>
<summary-cell
:label=
"s__('DastProfiles|Scan mode')"
:value=
"s__('DastProfiles|Passive')"
/>
</div>
<div
class=
"row"
>
<summary-cell
:label=
"s__('DastProfiles|Spider timeout')"
:value=
"n__('%d minute', '%d minutes', profile.spiderTimeout)"
/>
<summary-cell
:label=
"s__('DastProfiles|Target timeout')"
:value=
"n__('%d second', '%d seconds', profile.targetTimeout)"
/>
</div>
</
template
>
</profile-selector>
</template>
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/site_profile_selector.vue
0 → 100644
View file @
87b94d7c
<
script
>
import
ProfileSelector
from
'
./profile_selector.vue
'
;
import
SummaryCell
from
'
./summary_cell.vue
'
;
export
default
{
name
:
'
OnDemandScansSiteProfileSelector
'
,
components
:
{
ProfileSelector
,
SummaryCell
,
},
props
:
{
profiles
:
{
type
:
Array
,
required
:
false
,
default
:
()
=>
[],
},
},
inject
:
{
siteProfilesLibraryPath
:
{
default
:
''
,
},
newSiteProfilePath
:
{
default
:
''
,
},
},
};
</
script
>
<
template
>
<profile-selector
:library-path=
"siteProfilesLibraryPath"
:new-profile-path=
"newSiteProfilePath"
:profiles=
"
profiles.map(profile => (
{
...profile,
dropdownLabel: `${profile.profileName}: ${profile.targetUrl}`,
}))
"
v-bind="$attrs"
v-on="$listeners"
>
<template
#title
>
{{
s__
(
'
OnDemandScans|Site profile
'
)
}}
</
template
>
<
template
#label
>
{{
s__
(
'
OnDemandScans|Use existing site profile
'
)
}}
</
template
>
<
template
#no-profiles
>
{{
s__
(
'
OnDemandScans|No profile yet. In order to create a new scan, you need to have at least one completed site profile.
'
,
)
}}
</
template
>
<
template
#new-profile
>
{{
s__
(
'
OnDemandScans|Create a new site profile
'
)
}}
</
template
>
<
template
#summary=
"{ profile }"
>
<div
class=
"row"
>
<summary-cell
:label=
"s__('DastProfiles|Target URL')"
:value=
"profile.targetUrl"
/>
</div>
</
template
>
</profile-selector>
</template>
ee/app/assets/javascripts/on_demand_scans/components/profile_selector/summary_cell.vue
0 → 100644
View file @
87b94d7c
<
script
>
export
default
{
name
:
'
OnDemandScansProfileSummaryCell
'
,
props
:
{
label
:
{
type
:
String
,
required
:
true
,
},
value
:
{
type
:
String
,
required
:
true
,
},
},
};
</
script
>
<
template
>
<div
class=
"col-md-6"
>
<div
class=
"row"
>
<div
class=
"col-md-3"
>
{{
label
}}
:
</div>
<div
class=
"col-md-9"
>
<strong>
{{
value
}}
</strong>
</div>
</div>
</div>
</
template
>
ee/app/assets/javascripts/on_demand_scans/settings.js
0 → 100644
View file @
87b94d7c
import
dastScannerProfilesQuery
from
'
ee/dast_profiles/graphql/dast_scanner_profiles.query.graphql
'
;
import
dastSiteProfilesQuery
from
'
ee/dast_profiles/graphql/dast_site_profiles.query.graphql
'
;
import
{
s__
}
from
'
~/locale
'
;
export
const
ERROR_RUN_SCAN
=
'
ERROR_RUN_SCAN
'
;
export
const
ERROR_FETCH_SCANNER_PROFILES
=
'
ERROR_FETCH_SCANNER_PROFILES
'
;
export
const
ERROR_FETCH_SITE_PROFILES
=
'
ERROR_FETCH_SITE_PROFILES
'
;
export
const
ERROR_MESSAGES
=
{
[
ERROR_RUN_SCAN
]:
s__
(
'
OnDemandScans|Could not run the scan. Please try again.
'
),
[
ERROR_FETCH_SCANNER_PROFILES
]:
s__
(
'
OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later.
'
,
),
[
ERROR_FETCH_SITE_PROFILES
]:
s__
(
'
OnDemandScans|Could not fetch site profiles. Please refresh the page, or try again later.
'
,
),
};
export
const
SCANNER_PROFILES_QUERY
=
{
field
:
'
dastScannerProfileId
'
,
fetchQuery
:
dastScannerProfilesQuery
,
fetchError
:
ERROR_FETCH_SCANNER_PROFILES
,
queryKind
:
'
scannerProfiles
'
,
};
export
const
SITE_PROFILES_QUERY
=
{
field
:
'
dastSiteProfileId
'
,
fetchQuery
:
dastSiteProfilesQuery
,
fetchError
:
ERROR_FETCH_SITE_PROFILES
,
queryKind
:
'
siteProfiles
'
,
};
ee/spec/frontend/on_demand_scans/components/profile_selector/__snapshots__/scanner_profile_selector_spec.js.snap
0 → 100644
View file @
87b94d7c
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`OnDemandScansScannerProfileSelector renders properly with profiles 1`] = `
<div
class="card"
data-foo="bar"
value="gid://gitlab/DastScannerProfile/1"
>
<!---->
<div
class="card-header"
>
<div
class="row"
>
<div
class="col-7"
>
<h3
class="gl-font-lg gl-display-inline"
>
Scanner profile
</h3>
</div>
<div
class="col-5 gl-text-right"
>
<a
class="btn btn-success btn-sm gl-button btn-success-secondary"
data-testid="manage-profiles-link"
href="/test/scanner/profiles/library/path"
>
<!---->
<!---->
<span
class="gl-button-text"
>
Manage profiles
</span>
</a>
</div>
</div>
</div>
<div
class="card-body"
>
<!---->
<!---->
<fieldset
class="form-group gl-form-group"
>
<legend
class="bv-no-focus-ring col-form-label pt-0 col-form-label"
tabindex="-1"
>
Use existing scanner profile
</legend>
<div
class="bv-no-focus-ring"
role="group"
tabindex="-1"
>
<div
class="dropdown b-dropdown gl-new-dropdown mw-460 btn-group"
data-testid="profiles-dropdown"
>
<!---->
<button
aria-expanded="false"
aria-haspopup="true"
class="btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle"
type="button"
>
<!---->
<span
class="gl-new-dropdown-button-text"
>
Scanner profile #1
</span>
<svg
class="dropdown-chevron gl-icon s16"
data-testid="chevron-down-icon"
>
<use
href="#chevron-down"
/>
</svg>
</button>
<ul
class="dropdown-menu"
role="menu"
tabindex="-1"
>
<!---->
<li
class="gl-new-dropdown-item"
role="presentation"
>
<button
class="dropdown-item"
role="menuitem"
type="button"
>
<svg
class="gl-icon s16 gl-new-dropdown-item-check-icon"
data-testid="mobile-issue-close-icon"
>
<use
href="#mobile-issue-close"
/>
</svg>
<!---->
<!---->
<div
class="gl-new-dropdown-item-text-wrapper"
>
<p
class="gl-new-dropdown-item-text-primary"
>
Scanner profile #1
</p>
<!---->
</div>
<!---->
</button>
</li>
<li
class="gl-new-dropdown-item"
role="presentation"
>
<button
class="dropdown-item"
role="menuitem"
type="button"
>
<svg
class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden"
data-testid="mobile-issue-close-icon"
>
<use
href="#mobile-issue-close"
/>
</svg>
<!---->
<!---->
<div
class="gl-new-dropdown-item-text-wrapper"
>
<p
class="gl-new-dropdown-item-text-primary"
>
Scanner profile #2
</p>
<!---->
</div>
<!---->
</button>
</li>
</ul>
</div>
<div
class="gl-mt-6 gl-pt-6 gl-border-t-solid gl-border-gray-100 gl-border-t-1"
data-testid="selected-profile-summary"
>
<div
class="row"
>
<div
class="col-md-6"
>
<div
class="row"
>
<div
class="col-md-3"
>
Scan mode:
</div>
<div
class="col-md-9"
>
<strong>
Passive
</strong>
</div>
</div>
</div>
</div>
<div
class="row"
>
<div
class="col-md-6"
>
<div
class="row"
>
<div
class="col-md-3"
>
Spider timeout:
</div>
<div
class="col-md-9"
>
<strong>
5 minutes
</strong>
</div>
</div>
</div>
<div
class="col-md-6"
>
<div
class="row"
>
<div
class="col-md-3"
>
Target timeout:
</div>
<div
class="col-md-9"
>
<strong>
10 seconds
</strong>
</div>
</div>
</div>
</div>
</div>
<!---->
<!---->
<!---->
</div>
</fieldset>
</div>
<!---->
<!---->
</div>
`;
exports[`OnDemandScansScannerProfileSelector renders properly without profiles 1`] = `
<div
class="card"
data-foo="bar"
>
<!---->
<div
class="card-header"
>
<div
class="row"
>
<div
class="col-7"
>
<h3
class="gl-font-lg gl-display-inline"
>
Scanner profile
</h3>
</div>
<div
class="col-5 gl-text-right"
>
<button
class="btn btn-success btn-sm disabled gl-button btn-success-secondary"
data-testid="manage-profiles-link"
disabled="disabled"
type="button"
>
<!---->
<!---->
<span
class="gl-button-text"
>
Manage profiles
</span>
</button>
</div>
</div>
</div>
<div
class="card-body"
>
<!---->
<!---->
<p
class="gl-text-gray-700"
>
No profile yet. In order to create a new scan, you need to have at least one completed scanner profile.
</p>
<a
class="btn btn-success btn-md gl-button btn-success-secondary"
data-testid="create-profile-link"
href="/test/new/scanner/profile/path"
>
<!---->
<!---->
<span
class="gl-button-text"
>
Create a new scanner profile
</span>
</a>
</div>
<!---->
<!---->
</div>
`;
ee/spec/frontend/on_demand_scans/components/profile_selector/__snapshots__/site_profile_selector_spec.js.snap
0 → 100644
View file @
87b94d7c
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`OnDemandScansSiteProfileSelector renders properly with profiles 1`] = `
<div
class="card"
data-foo="bar"
value="gid://gitlab/DastSiteProfile/1"
>
<!---->
<div
class="card-header"
>
<div
class="row"
>
<div
class="col-7"
>
<h3
class="gl-font-lg gl-display-inline"
>
Site profile
</h3>
</div>
<div
class="col-5 gl-text-right"
>
<a
class="btn btn-success btn-sm gl-button btn-success-secondary"
data-testid="manage-profiles-link"
href="/test/site/profiles/library/path"
>
<!---->
<!---->
<span
class="gl-button-text"
>
Manage profiles
</span>
</a>
</div>
</div>
</div>
<div
class="card-body"
>
<!---->
<!---->
<fieldset
class="form-group gl-form-group"
>
<legend
class="bv-no-focus-ring col-form-label pt-0 col-form-label"
tabindex="-1"
>
Use existing site profile
</legend>
<div
class="bv-no-focus-ring"
role="group"
tabindex="-1"
>
<div
class="dropdown b-dropdown gl-new-dropdown mw-460 btn-group"
data-testid="profiles-dropdown"
>
<!---->
<button
aria-expanded="false"
aria-haspopup="true"
class="btn dropdown-toggle btn-default btn-md gl-button gl-dropdown-toggle"
type="button"
>
<!---->
<span
class="gl-new-dropdown-button-text"
>
Site profile #1: https://foo.com
</span>
<svg
class="dropdown-chevron gl-icon s16"
data-testid="chevron-down-icon"
>
<use
href="#chevron-down"
/>
</svg>
</button>
<ul
class="dropdown-menu"
role="menu"
tabindex="-1"
>
<!---->
<li
class="gl-new-dropdown-item"
role="presentation"
>
<button
class="dropdown-item"
role="menuitem"
type="button"
>
<svg
class="gl-icon s16 gl-new-dropdown-item-check-icon"
data-testid="mobile-issue-close-icon"
>
<use
href="#mobile-issue-close"
/>
</svg>
<!---->
<!---->
<div
class="gl-new-dropdown-item-text-wrapper"
>
<p
class="gl-new-dropdown-item-text-primary"
>
Site profile #1
</p>
<!---->
</div>
<!---->
</button>
</li>
<li
class="gl-new-dropdown-item"
role="presentation"
>
<button
class="dropdown-item"
role="menuitem"
type="button"
>
<svg
class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden"
data-testid="mobile-issue-close-icon"
>
<use
href="#mobile-issue-close"
/>
</svg>
<!---->
<!---->
<div
class="gl-new-dropdown-item-text-wrapper"
>
<p
class="gl-new-dropdown-item-text-primary"
>
Site profile #2
</p>
<!---->
</div>
<!---->
</button>
</li>
</ul>
</div>
<div
class="gl-mt-6 gl-pt-6 gl-border-t-solid gl-border-gray-100 gl-border-t-1"
data-testid="selected-profile-summary"
>
<div
class="row"
>
<div
class="col-md-6"
>
<div
class="row"
>
<div
class="col-md-3"
>
Target URL:
</div>
<div
class="col-md-9"
>
<strong>
https://foo.com
</strong>
</div>
</div>
</div>
</div>
</div>
<!---->
<!---->
<!---->
</div>
</fieldset>
</div>
<!---->
<!---->
</div>
`;
exports[`OnDemandScansSiteProfileSelector renders properly without profiles 1`] = `
<div
class="card"
data-foo="bar"
>
<!---->
<div
class="card-header"
>
<div
class="row"
>
<div
class="col-7"
>
<h3
class="gl-font-lg gl-display-inline"
>
Site profile
</h3>
</div>
<div
class="col-5 gl-text-right"
>
<button
class="btn btn-success btn-sm disabled gl-button btn-success-secondary"
data-testid="manage-profiles-link"
disabled="disabled"
type="button"
>
<!---->
<!---->
<span
class="gl-button-text"
>
Manage profiles
</span>
</button>
</div>
</div>
</div>
<div
class="card-body"
>
<!---->
<!---->
<p
class="gl-text-gray-700"
>
No profile yet. In order to create a new scan, you need to have at least one completed site profile.
</p>
<a
class="btn btn-success btn-md gl-button btn-success-secondary"
data-testid="create-profile-link"
href="/test/new/site/profile/path"
>
<!---->
<!---->
<span
class="gl-button-text"
>
Create a new site profile
</span>
</a>
</div>
<!---->
<!---->
</div>
`;
ee/spec/frontend/on_demand_scans/components/profile_selector/__snapshots__/summary_cell_spec.js.snap
0 → 100644
View file @
87b94d7c
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`OnDemandScansProfileSummaryCell renders properly 1`] = `
"<div class=\\"col-md-6\\">
<div class=\\"row\\">
<div class=\\"col-md-3\\">Row Label:</div>
<div class=\\"col-md-9\\"><strong>Row Value</strong></div>
</div>
</div>"
`;
ee/spec/frontend/on_demand_scans/components/profile_selector/profile_selector_spec.js
0 → 100644
View file @
87b94d7c
import
{
merge
}
from
'
lodash
'
;
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
OnDemandScansProfileSelector
from
'
ee/on_demand_scans/components/profile_selector/profile_selector.vue
'
;
import
{
scannerProfiles
}
from
'
../../mock_data
'
;
describe
(
'
OnDemandScansProfileSelector
'
,
()
=>
{
let
wrapper
;
const
defaultProps
=
{
libraryPath
:
'
/path/to/profiles/library
'
,
newProfilePath
:
'
/path/to/new/profile/form
'
,
profiles
:
[],
};
const
findByTestId
=
testId
=>
wrapper
.
find
(
`[data-testid="
${
testId
}
"]`
);
const
findProfilesLibraryPathLink
=
()
=>
findByTestId
(
'
manage-profiles-link
'
);
const
findProfilesDropdown
=
()
=>
findByTestId
(
'
profiles-dropdown
'
);
const
findCreateNewProfileLink
=
()
=>
findByTestId
(
'
create-profile-link
'
);
const
findSelectedProfileSummary
=
()
=>
findByTestId
(
'
selected-profile-summary
'
);
const
parseDropdownItems
=
()
=>
findProfilesDropdown
()
.
findAll
(
GlDropdownItem
)
.
wrappers
.
map
(
x
=>
({
text
:
x
.
text
(),
isChecked
:
x
.
props
(
'
isChecked
'
),
}));
const
selectFirstProfile
=
()
=>
{
return
findProfilesDropdown
()
.
find
(
GlDropdownItem
)
.
vm
.
$emit
(
'
click
'
);
};
const
createFullComponent
=
(
options
=
{})
=>
{
wrapper
=
mount
(
OnDemandScansProfileSelector
,
merge
(
{
propsData
:
defaultProps
,
slots
:
{
title
:
'
Section title
'
,
label
:
'
Use existing scanner profile
'
,
'
no-profiles
'
:
'
No profile yet
'
,
'
new-profile
'
:
'
Create a new profile
'
,
},
scopedSlots
:
{
summary
:
"
<div>{{ props.profile.profileName }}'s summary</div>
"
,
},
},
options
,
),
);
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
shows section title and link to profiles library
'
,
()
=>
{
createFullComponent
();
expect
(
wrapper
.
text
()).
toContain
(
'
Section title
'
);
});
describe
(
'
when there are no profiles yet
'
,
()
=>
{
beforeEach
(()
=>
{
createFullComponent
();
});
it
(
'
disables the link to profiles library
'
,
()
=>
{
expect
(
findProfilesLibraryPathLink
().
props
(
'
disabled
'
)).
toBe
(
true
);
});
it
(
'
shows a help text and a link to create a new profile
'
,
()
=>
{
const
link
=
findCreateNewProfileLink
();
expect
(
wrapper
.
text
()).
toContain
(
'
No profile yet
'
);
expect
(
link
.
exists
()).
toBe
(
true
);
expect
(
link
.
attributes
(
'
href
'
)).
toBe
(
'
/path/to/new/profile/form
'
);
expect
(
link
.
text
()).
toBe
(
'
Create a new profile
'
);
});
});
describe
(
'
when there are profiles
'
,
()
=>
{
beforeEach
(()
=>
{
createFullComponent
({
propsData
:
{
profiles
:
scannerProfiles
},
});
});
it
(
'
enables link to profiles management
'
,
()
=>
{
expect
(
findProfilesLibraryPathLink
().
props
(
'
disabled
'
)).
toBe
(
false
);
expect
(
findProfilesLibraryPathLink
().
attributes
(
'
href
'
)).
toBe
(
'
/path/to/profiles/library
'
);
});
it
(
'
shows a dropdown containing the profiles
'
,
()
=>
{
const
dropdown
=
findProfilesDropdown
();
expect
(
wrapper
.
text
()).
toContain
(
'
Use existing scanner profile
'
);
expect
(
dropdown
.
exists
()).
toBe
(
true
);
expect
(
dropdown
.
element
.
children
).
toHaveLength
(
scannerProfiles
.
length
);
});
it
(
'
when a profile is selected, input event is emitted
'
,
async
()
=>
{
await
selectFirstProfile
();
expect
(
wrapper
.
emitted
(
'
input
'
)).
toEqual
([[
scannerProfiles
[
0
].
id
]]);
});
it
(
'
shows dropdown items for each profile
'
,
()
=>
{
expect
(
parseDropdownItems
()).
toEqual
(
scannerProfiles
.
map
(
x
=>
({
text
:
x
.
profileName
,
isChecked
:
false
,
})),
);
});
it
(
'
does not show summary
'
,
()
=>
{
expect
(
findSelectedProfileSummary
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
when profile is selected
'
,
()
=>
{
let
selectedProfile
;
beforeEach
(()
=>
{
[
selectedProfile
]
=
scannerProfiles
;
createFullComponent
({
propsData
:
{
profiles
:
scannerProfiles
,
value
:
selectedProfile
.
id
,
},
});
});
it
(
'
displays summary below dropdown
'
,
()
=>
{
const
summary
=
findSelectedProfileSummary
();
expect
(
summary
.
exists
()).
toBe
(
true
);
expect
(
summary
.
text
()).
toContain
(
`
${
scannerProfiles
[
0
].
profileName
}
's summary`
);
});
it
(
'
displays item as checked
'
,
()
=>
{
expect
(
parseDropdownItems
()).
toEqual
(
scannerProfiles
.
map
((
x
,
i
)
=>
({
text
:
x
.
profileName
,
isChecked
:
i
===
0
,
})),
);
});
});
});
ee/spec/frontend/on_demand_scans/components/profile_selector/scanner_profile_selector_spec.js
0 → 100644
View file @
87b94d7c
import
{
merge
}
from
'
lodash
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
OnDemandScansScannerProfileSelector
from
'
ee/on_demand_scans/components/profile_selector/scanner_profile_selector.vue
'
;
import
ProfileSelector
from
'
ee/on_demand_scans/components/profile_selector/profile_selector.vue
'
;
import
{
scannerProfiles
}
from
'
../../mock_data
'
;
const
TEST_LIBRARY_PATH
=
'
/test/scanner/profiles/library/path
'
;
const
TEST_NEW_PATH
=
'
/test/new/scanner/profile/path
'
;
const
TEST_ATTRS
=
{
'
data-foo
'
:
'
bar
'
,
};
describe
(
'
OnDemandScansScannerProfileSelector
'
,
()
=>
{
let
wrapper
;
const
wrapperFactory
=
(
mountFn
=
shallowMount
)
=>
(
options
=
{})
=>
{
wrapper
=
mountFn
(
OnDemandScansScannerProfileSelector
,
merge
(
{
propsData
:
{
profiles
:
[],
},
attrs
:
TEST_ATTRS
,
provide
:
{
scannerProfilesLibraryPath
:
TEST_LIBRARY_PATH
,
newScannerProfilePath
:
TEST_NEW_PATH
,
},
},
options
,
),
);
};
const
createComponent
=
wrapperFactory
();
const
createFullComponent
=
wrapperFactory
(
mount
);
const
findProfileSelector
=
()
=>
wrapper
.
find
(
ProfileSelector
);
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
renders properly with profiles
'
,
()
=>
{
createFullComponent
({
propsData
:
{
profiles
:
scannerProfiles
,
value
:
scannerProfiles
[
0
].
id
},
});
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
it
(
'
renders properly without profiles
'
,
()
=>
{
createFullComponent
();
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
it
(
'
sets listeners on profile selector component
'
,
()
=>
{
const
inputHandler
=
jest
.
fn
();
createComponent
({
listeners
:
{
input
:
inputHandler
,
},
});
findProfileSelector
().
vm
.
$emit
(
'
input
'
);
expect
(
inputHandler
).
toHaveBeenCalled
();
});
describe
(
'
with profiles
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
propsData
:
{
profiles
:
scannerProfiles
},
});
});
it
(
'
renders profile selector
'
,
()
=>
{
const
sel
=
findProfileSelector
();
expect
(
sel
.
props
()).
toEqual
({
libraryPath
:
TEST_LIBRARY_PATH
,
newProfilePath
:
TEST_NEW_PATH
,
profiles
:
scannerProfiles
.
map
(
x
=>
({
...
x
,
dropdownLabel
:
x
.
profileName
})),
value
:
null
,
});
expect
(
sel
.
attributes
()).
toMatchObject
(
TEST_ATTRS
);
});
});
});
ee/spec/frontend/on_demand_scans/components/profile_selector/site_profile_selector_spec.js
0 → 100644
View file @
87b94d7c
import
{
merge
}
from
'
lodash
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
OnDemandScansSiteProfileSelector
from
'
ee/on_demand_scans/components/profile_selector/site_profile_selector.vue
'
;
import
ProfileSelector
from
'
ee/on_demand_scans/components/profile_selector/profile_selector.vue
'
;
import
{
siteProfiles
}
from
'
../../mock_data
'
;
const
TEST_LIBRARY_PATH
=
'
/test/site/profiles/library/path
'
;
const
TEST_NEW_PATH
=
'
/test/new/site/profile/path
'
;
const
TEST_ATTRS
=
{
'
data-foo
'
:
'
bar
'
,
};
describe
(
'
OnDemandScansSiteProfileSelector
'
,
()
=>
{
let
wrapper
;
const
wrapperFactory
=
(
mountFn
=
shallowMount
)
=>
(
options
=
{})
=>
{
wrapper
=
mountFn
(
OnDemandScansSiteProfileSelector
,
merge
(
{
propsData
:
{
profiles
:
[],
},
attrs
:
TEST_ATTRS
,
provide
:
{
siteProfilesLibraryPath
:
TEST_LIBRARY_PATH
,
newSiteProfilePath
:
TEST_NEW_PATH
,
},
},
options
,
),
);
};
const
createComponent
=
wrapperFactory
();
const
createFullComponent
=
wrapperFactory
(
mount
);
const
findProfileSelector
=
()
=>
wrapper
.
find
(
ProfileSelector
);
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
renders properly with profiles
'
,
()
=>
{
createFullComponent
({
propsData
:
{
profiles
:
siteProfiles
,
value
:
siteProfiles
[
0
].
id
},
});
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
it
(
'
renders properly without profiles
'
,
()
=>
{
createFullComponent
();
expect
(
wrapper
.
element
).
toMatchSnapshot
();
});
it
(
'
sets listeners on profile selector component
'
,
()
=>
{
const
inputHandler
=
jest
.
fn
();
createComponent
({
listeners
:
{
input
:
inputHandler
,
},
});
findProfileSelector
().
vm
.
$emit
(
'
input
'
);
expect
(
inputHandler
).
toHaveBeenCalled
();
});
describe
(
'
with profiles
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
propsData
:
{
profiles
:
siteProfiles
},
});
});
it
(
'
renders profile selector
'
,
()
=>
{
const
sel
=
findProfileSelector
();
expect
(
sel
.
props
()).
toEqual
({
libraryPath
:
TEST_LIBRARY_PATH
,
newProfilePath
:
TEST_NEW_PATH
,
profiles
:
siteProfiles
.
map
(
x
=>
({
...
x
,
dropdownLabel
:
`
${
x
.
profileName
}
:
${
x
.
targetUrl
}
`
,
})),
value
:
null
,
});
expect
(
sel
.
attributes
()).
toMatchObject
(
TEST_ATTRS
);
});
});
});
ee/spec/frontend/on_demand_scans/components/profile_selector/summary_cell_spec.js
0 → 100644
View file @
87b94d7c
import
{
mount
}
from
'
@vue/test-utils
'
;
import
OnDemandScansProfileSummaryCell
from
'
ee/on_demand_scans/components/profile_selector/summary_cell.vue
'
;
describe
(
'
OnDemandScansProfileSummaryCell
'
,
()
=>
{
let
wrapper
;
const
createFullComponent
=
()
=>
{
wrapper
=
mount
(
OnDemandScansProfileSummaryCell
,
{
propsData
:
{
label
:
'
Row Label
'
,
value
:
'
Row Value
'
,
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
(
'
renders properly
'
,
()
=>
{
createFullComponent
();
expect
(
wrapper
.
html
()).
toMatchSnapshot
();
});
});
ee/spec/frontend/on_demand_scans/mock_data.js
0 → 100644
View file @
87b94d7c
export
const
scannerProfiles
=
[
{
id
:
'
gid://gitlab/DastScannerProfile/1
'
,
profileName
:
'
Scanner profile #1
'
,
spiderTimeout
:
5
,
targetTimeout
:
10
,
},
{
id
:
'
gid://gitlab/DastScannerProfile/2
'
,
profileName
:
'
Scanner profile #2
'
,
spiderTimeout
:
20
,
targetTimeout
:
150
,
},
];
export
const
siteProfiles
=
[
{
id
:
'
gid://gitlab/DastSiteProfile/1
'
,
profileName
:
'
Site profile #1
'
,
targetUrl
:
'
https://foo.com
'
,
},
{
id
:
'
gid://gitlab/DastSiteProfile/2
'
,
profileName
:
'
Site profile #2
'
,
targetUrl
:
'
https://bar.com
'
,
},
];
locale/gitlab.pot
View file @
87b94d7c
...
@@ -17687,6 +17687,9 @@ msgstr ""
...
@@ -17687,6 +17687,9 @@ msgstr ""
msgid "OnDemandScans|Scan mode"
msgid "OnDemandScans|Scan mode"
msgstr ""
msgstr ""
msgid "OnDemandScans|Scanner profile"
msgstr ""
msgid "OnDemandScans|Scanner settings"
msgid "OnDemandScans|Scanner settings"
msgstr ""
msgstr ""
...
@@ -17696,6 +17699,9 @@ msgstr ""
...
@@ -17696,6 +17699,9 @@ msgstr ""
msgid "OnDemandScans|Select one of the existing profiles"
msgid "OnDemandScans|Select one of the existing profiles"
msgstr ""
msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
msgid "OnDemandScans|Site profiles"
msgid "OnDemandScans|Site profiles"
msgstr ""
msgstr ""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment