Commit 47c121a5 authored by Mike Greiling's avatar Mike Greiling

Merge branch '288337-dast-site-profile-mocks' into 'master'

Replace site profile mocks in dast_profiles

See merge request gitlab-org/gitlab!75191
parents f9bb6c04 cb31e169
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'DAST profiles (GraphQL fixtures)' do
describe GraphQL::Query, type: :request do
include ApiHelpers
include GraphqlHelpers
include JavaScriptFixturesHelpers
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :public) }
# DAST site validations
let_it_be(:dast_site_validation_pending) do
create(
:dast_site_validation,
state: :pending,
dast_site_token: create(
:dast_site_token,
project: project
)
)
end
let_it_be(:dast_site_validation_inprogress) do
create(
:dast_site_validation,
state: :inprogress,
dast_site_token: create(
:dast_site_token,
project: project
)
)
end
let_it_be(:dast_site_validation_passed) do
create(
:dast_site_validation,
state: :passed,
dast_site_token: create(
:dast_site_token,
project: project
)
)
end
let_it_be(:dast_site_validation_failed) do
create(
:dast_site_validation,
state: :failed,
dast_site_token: create(
:dast_site_token,
project: project
)
)
end
# DAST sites
let_it_be(:dast_site_pending) do
create(
:dast_site,
project: project,
url: 'http://pending.test',
dast_site_validation: dast_site_validation_pending
)
end
let_it_be(:dast_site_inprogress) do
create(
:dast_site,
project: project,
url: 'http://inprogress.test',
dast_site_validation: dast_site_validation_inprogress
)
end
let_it_be(:dast_site_passed) do
create(
:dast_site,
project: project,
url: 'http://passed.test',
dast_site_validation: dast_site_validation_passed
)
end
let_it_be(:dast_site_failed) do
create(
:dast_site,
project: project,
url: 'http://failed.test',
dast_site_validation: dast_site_validation_failed
)
end
let_it_be(:dast_site_none) do
create(
:dast_site,
project: project,
url: 'http://none.test',
dast_site_validation: nil
)
end
before do
stub_licensed_features(security_on_demand_scans: true)
project.add_developer(current_user)
end
describe 'dast_site_profiles' do
path = 'security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql'
context 'basic site profiles' do
# DAST site profiles
let_it_be(:dast_site_profiles) do
[
create(
:dast_site_profile,
name: "Non-validated",
auth_username: "non-validated@example.com",
project: project, dast_site: dast_site_none
),
create(
:dast_site_profile,
name: "Validation failed",
auth_username: "validation-failed@example.com",
project: project, dast_site: dast_site_failed
),
create(
:dast_site_profile,
name: "Validation passed",
auth_username: "validation-passed@example.com",
project: project, dast_site: dast_site_passed
),
create(
:dast_site_profile,
name: "Validation in progress",
auth_username: "validation-in-progress@example.com",
project: project, dast_site: dast_site_inprogress
),
create(
:dast_site_profile,
name: "Validation pending",
auth_username: "validation-pending@example.com",
project: project, dast_site: dast_site_pending
)
]
end
it "graphql/#{path}.basic.json" do
query = get_graphql_query_as_string(path, ee: true)
post_graphql(query, current_user: current_user, variables: {
fullPath: project.full_path,
first: 20
})
expect_graphql_errors_to_be_empty
expect(graphql_data_at(:project, :siteProfiles, :edges)).to have_attributes(size: 5)
end
end
end
end
end
......@@ -18,8 +18,14 @@ import waitForPromises from 'helpers/wait_for_promises';
import { redirectTo } from '~/lib/utils/url_utility';
import RefSelector from '~/ref/components/ref_selector.vue';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import {
siteProfiles,
nonValidatedSiteProfile,
validatedSiteProfile,
} from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
import * as responses from '../mocks/apollo_mocks';
import { scannerProfiles, siteProfiles } from '../mocks/mock_data';
import { scannerProfiles } from '../mocks/mock_data';
const dastSiteValidationDocsPath = '/application_security/dast/index#dast-site-validation';
const projectPath = 'group/project';
......@@ -33,7 +39,6 @@ const newSiteProfilePath = `/${projectPath}/-/security/configuration/dast_scans`
const pipelineUrl = `/${projectPath}/pipelines/123`;
const editPath = `/${projectPath}/on_demand_scans_form/1/edit`;
const [passiveScannerProfile, activeScannerProfile] = scannerProfiles;
const [nonValidatedSiteProfile, validatedSiteProfile] = siteProfiles;
const dastScan = {
id: 1,
branch: { name: 'dev' },
......@@ -301,7 +306,7 @@ describe('OnDemandScansForm', () => {
JSON.stringify({
name: 'My daily scan',
selectedScannerProfileId: 'gid://gitlab/DastScannerProfile/1',
selectedSiteProfileId: 'gid://gitlab/DastSiteProfile/1',
selectedSiteProfileId: nonValidatedSiteProfile.id,
selectedBranch,
}),
],
......@@ -620,14 +625,16 @@ describe('OnDemandScansForm', () => {
});
it('site profile', () => {
setWindowLocation('?site_profile_id=1');
setWindowLocation(`?site_profile_id=${getIdFromGraphQLId(siteProfile.id)}`);
createShallowComponent();
expect(wrapper.find(SiteProfileSelector).attributes('value')).toBe(siteProfile.id);
});
it('both scanner & site profile', () => {
setWindowLocation('?site_profile_id=1&scanner_profile_id=1');
setWindowLocation(
`?site_profile_id=${getIdFromGraphQLId(siteProfile.id)}&scanner_profile_id=1`,
);
createShallowComponent();
expect(wrapper.find(SiteProfileSelector).attributes('value')).toBe(siteProfile.id);
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`OnDemandScansSiteProfileSelector renders properly with profiles 1`] = `
<div
class="gl-card"
data-foo="bar"
value="gid://gitlab/DastSiteProfile/1"
>
<div
class="gl-card-header"
>
<div
class="row"
>
<div
class="col-7 gl-display-flex gl-align-items-center"
>
<h3
class="gl-font-lg gl-my-0"
>
Site profile
</h3>
</div>
</div>
</div>
<div
class="gl-card-body"
>
<fieldset
aria-describedby=""
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
aria-hidden="true"
class="gl-button-icon dropdown-chevron gl-icon s16"
data-testid="chevron-down-icon"
role="img"
>
<use
href="#chevron-down"
/>
</svg>
</button>
<ul
class="dropdown-menu"
role="menu"
tabindex="-1"
>
<div
class="gl-new-dropdown-inner"
>
<div
class="gl-new-dropdown-header gl-border-b-0!"
>
<!---->
<div
class="gl-search-box-by-type"
>
<svg
aria-hidden="true"
class="gl-search-box-by-type-search-icon gl-icon s16"
data-testid="search-icon"
role="img"
>
<use
href="#search"
/>
</svg>
<input
aria-label="Search"
class="gl-form-input gl-search-box-by-type-input form-control"
placeholder="Search"
type="text"
/>
<div
class="gl-search-box-by-type-right-icons"
>
<!---->
<!---->
</div>
</div>
</div>
<!---->
<div
class="gl-new-dropdown-contents"
>
<!---->
<li
class="gl-new-dropdown-item"
role="presentation"
>
<button
class="dropdown-item"
role="menuitem"
type="button"
>
<svg
aria-hidden="true"
class="gl-icon s16 gl-new-dropdown-item-check-icon gl-mt-3 gl-align-self-start"
data-testid="dropdown-item-checkbox"
role="img"
>
<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
aria-hidden="true"
class="gl-icon s16 gl-new-dropdown-item-check-icon gl-visibility-hidden gl-mt-3 gl-align-self-start"
data-testid="dropdown-item-checkbox"
role="img"
>
<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>
<div
class="gl-p-3 gl-text-center"
style="display: none;"
>
No matching results...
</div>
</div>
<div
class="gl-new-dropdown-footer"
>
<li
class="gl-new-dropdown-item"
role="presentation"
>
<a
class="dropdown-item"
data-testid="create-profile-option"
href="/test/new/site/profile/path"
role="menuitem"
target="_self"
>
<!---->
<!---->
<!---->
<div
class="gl-new-dropdown-item-text-wrapper"
>
<p
class="gl-new-dropdown-item-text-primary"
>
Create new site profile
</p>
<!---->
</div>
<!---->
</a>
</li>
<li
class="gl-new-dropdown-item"
role="presentation"
>
<a
class="dropdown-item"
data-testid="manage-profiles-option"
href="/test/site/profiles/library/path"
role="menuitem"
target="_self"
>
<!---->
<!---->
<!---->
<div
class="gl-new-dropdown-item-text-wrapper"
>
<p
class="gl-new-dropdown-item-text-primary"
>
Manage site profiles
</p>
<!---->
</div>
<!---->
</a>
</li>
</div>
</div>
</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"
>
<a
aria-label="Edit profile"
class="btn gl-absolute gl-right-7 gl-z-index-1 btn-default btn-md gl-button btn-icon"
href="/site_profiles/edit/1"
title="Edit profile"
>
<!---->
<svg
aria-hidden="true"
class="gl-button-icon gl-icon s16"
data-testid="pencil-icon"
role="img"
>
<use
href="#pencil"
/>
</svg>
<!---->
</a>
</div>
<!---->
<!---->
<!---->
</div>
</fieldset>
</div>
<!---->
</div>
`;
exports[`OnDemandScansSiteProfileSelector renders properly without profiles 1`] = `
<div
class="gl-card"
......
......@@ -8,7 +8,7 @@ exports[`DastSiteProfileSummary renders properly profile 0 1`] = `
<profile-selector-summary-cell-stub
class=""
label="Target URL"
value="https://foo.com"
value="http://pending.test"
/>
<profile-selector-summary-cell-stub
......@@ -22,7 +22,7 @@ exports[`DastSiteProfileSummary renders properly profile 0 1`] = `
>
<profile-selector-summary-cell-stub
label="Authentication URL"
value="https://foo.com/login"
value="http://pending.test/sign-in"
/>
</div>
......@@ -31,7 +31,7 @@ exports[`DastSiteProfileSummary renders properly profile 0 1`] = `
>
<profile-selector-summary-cell-stub
label="Username"
value="admin"
value="validation-pending@example.com"
/>
<profile-selector-summary-cell-stub
......@@ -45,12 +45,12 @@ exports[`DastSiteProfileSummary renders properly profile 0 1`] = `
>
<profile-selector-summary-cell-stub
label="Username form field"
value="username"
value="session[username]"
/>
<profile-selector-summary-cell-stub
label="Password form field"
value="password"
value="session[password]"
/>
</div>
......@@ -59,12 +59,12 @@ exports[`DastSiteProfileSummary renders properly profile 0 1`] = `
>
<profile-selector-summary-cell-stub
label="Excluded URLs"
value="https://foo.com/logout,https://foo.com/send_mail"
value="http://pending.test/sign-out,http://pending.test/hidden"
/>
<profile-selector-summary-cell-stub
label="Request headers"
value="[Redacted]"
value="None"
/>
</div>
......@@ -87,28 +87,142 @@ exports[`DastSiteProfileSummary renders properly profile 1 1`] = `
<profile-selector-summary-cell-stub
class=""
label="Target URL"
value="https://bar.com"
value="http://inprogress.test"
/>
<profile-selector-summary-cell-stub
label="Site type"
value="Rest API"
value="Website"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Authentication URL"
value="http://inprogress.test/sign-in"
/>
</div>
<!---->
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username"
value="validation-in-progress@example.com"
/>
<profile-selector-summary-cell-stub
label="Password"
value="••••••••"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username form field"
value="session[username]"
/>
<profile-selector-summary-cell-stub
label="Password form field"
value="session[password]"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Excluded URLs"
value="https://bar.com/logout"
value="http://inprogress.test/sign-out,http://inprogress.test/hidden"
/>
<profile-selector-summary-cell-stub
label="Request headers"
value="[Redacted]"
value="None"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Validation status"
value="Not Validated"
/>
</div>
</div>
`;
exports[`DastSiteProfileSummary renders properly profile 2 1`] = `
<div>
<div
class="row"
>
<profile-selector-summary-cell-stub
class=""
label="Target URL"
value="http://passed.test"
/>
<profile-selector-summary-cell-stub
label="Site type"
value="Website"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Authentication URL"
value="http://passed.test/sign-in"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username"
value="validation-passed@example.com"
/>
<profile-selector-summary-cell-stub
label="Password"
value="••••••••"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username form field"
value="session[username]"
/>
<profile-selector-summary-cell-stub
label="Password form field"
value="session[password]"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Excluded URLs"
value="http://passed.test/sign-out,http://passed.test/hidden"
/>
<profile-selector-summary-cell-stub
label="Request headers"
value="None"
/>
</div>
......@@ -122,3 +236,161 @@ exports[`DastSiteProfileSummary renders properly profile 1 1`] = `
</div>
</div>
`;
exports[`DastSiteProfileSummary renders properly profile 3 1`] = `
<div>
<div
class="row"
>
<profile-selector-summary-cell-stub
class=""
label="Target URL"
value="http://failed.test"
/>
<profile-selector-summary-cell-stub
label="Site type"
value="Website"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Authentication URL"
value="http://failed.test/sign-in"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username"
value="validation-failed@example.com"
/>
<profile-selector-summary-cell-stub
label="Password"
value="••••••••"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username form field"
value="session[username]"
/>
<profile-selector-summary-cell-stub
label="Password form field"
value="session[password]"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Excluded URLs"
value="http://failed.test/sign-out,http://failed.test/hidden"
/>
<profile-selector-summary-cell-stub
label="Request headers"
value="None"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Validation status"
value="Not Validated"
/>
</div>
</div>
`;
exports[`DastSiteProfileSummary renders properly profile 4 1`] = `
<div>
<div
class="row"
>
<profile-selector-summary-cell-stub
class=""
label="Target URL"
value="http://none.test"
/>
<profile-selector-summary-cell-stub
label="Site type"
value="Website"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Authentication URL"
value="http://none.test/sign-in"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username"
value="non-validated@example.com"
/>
<profile-selector-summary-cell-stub
label="Password"
value="••••••••"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Username form field"
value="session[username]"
/>
<profile-selector-summary-cell-stub
label="Password form field"
value="session[password]"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Excluded URLs"
value="http://none.test/sign-out,http://none.test/hidden"
/>
<profile-selector-summary-cell-stub
label="Request headers"
value="None"
/>
</div>
<div
class="row"
>
<profile-selector-summary-cell-stub
label="Validation status"
value="Not Validated"
/>
</div>
</div>
`;
......@@ -11,15 +11,20 @@ import createApolloProvider from 'helpers/mock_apollo_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import {
siteProfiles,
nonValidatedSiteProfile,
validatedSiteProfile,
} from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
import * as responses from '../../mocks/apollo_mocks';
import { scannerProfiles, siteProfiles } from '../../mocks/mock_data';
import { scannerProfiles } from '../../mocks/mock_data';
const URL_HOST = 'https://localhost/';
const fullPath = '/project/path';
const [passiveScannerProfile, activeScannerProfile] = scannerProfiles;
const [nonValidatedSiteProfile, validatedSiteProfile] = siteProfiles;
beforeEach(() => {
setWindowLocation(URL_HOST);
......@@ -190,14 +195,16 @@ describe('EE - DAST Profiles Selector', () => {
});
it('site profile', () => {
setWindowLocation(`?site_profile_id=1`);
setWindowLocation(`?site_profile_id=${getIdFromGraphQLId(siteProfile.id)}`);
createComponent();
expect(findSiteProfilesSelector().attributes('value')).toBe(siteProfile.id);
});
it('both scanner & site profile', () => {
setWindowLocation(`?site_profile_id=1&scanner_profile_id=1`);
setWindowLocation(
`?site_profile_id=${getIdFromGraphQLId(siteProfile.id)}&scanner_profile_id=1`,
);
createComponent();
expect(wrapper.find(SiteProfileSelector).attributes('value')).toBe(siteProfile.id);
......
import { mount, shallowMount } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import { merge } from 'lodash';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import ProfileSelector from 'ee/on_demand_scans_form/components/profile_selector/profile_selector.vue';
import OnDemandScansSiteProfileSelector from 'ee/on_demand_scans_form/components/profile_selector/site_profile_selector.vue';
import SiteProfileSummary from 'ee/on_demand_scans_form/components/profile_selector/site_profile_summary.vue';
import { siteProfiles } from '../../mocks/mock_data';
import { siteProfiles } from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
const TEST_LIBRARY_PATH = '/test/site/profiles/library/path';
const TEST_NEW_PATH = '/test/new/site/profile/path';
......@@ -42,20 +43,26 @@ describe('OnDemandScansSiteProfileSelector', () => {
);
};
const createComponent = wrapperFactory();
const createFullComponent = wrapperFactory(mount);
const createFullComponent = wrapperFactory(mountExtended);
const findProfileSelector = () => wrapper.find(ProfileSelector);
const findProfileSelector = () => wrapper.findComponent(ProfileSelector);
const findSelectorOptions = () => wrapper.findAll('li');
const findProfileSummary = () => wrapper.findByTestId('selected-profile-summary');
afterEach(() => {
wrapper.destroy();
});
it('renders properly with profiles', () => {
const [selectedProfile] = profiles;
createFullComponent({
propsData: { profiles, value: profiles[0].id },
propsData: { profiles, value: selectedProfile.id },
});
expect(wrapper.element).toMatchSnapshot();
expect(findProfileSummary().html()).toContain(selectedProfile.editPath);
profiles.forEach((profile, index) => {
expect(findSelectorOptions().at(index).text()).toContain(profile.profileName);
});
});
it('renders properly without profiles', () => {
......
import { shallowMount } from '@vue/test-utils';
import App from 'ee/on_demand_scans_form/components/profile_selector/site_profile_summary.vue';
import { siteProfiles } from 'ee_jest/on_demand_scans_form/mocks/mock_data';
import { siteProfiles } from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
describe('DastSiteProfileSummary', () => {
let wrapper;
......
import { scannerProfiles, siteProfiles } from './mock_data';
import { siteProfiles } from 'ee_jest/security_configuration/dast_profiles/mocks/mock_data';
import { scannerProfiles } from './mock_data';
const defaults = {
pageInfo: {
......
export const siteProfiles = [
{
id: 'gid://gitlab/DastSiteProfile/1',
profileName: 'Profile 1',
targetUrl: 'http://example-1.com',
normalizedTargetUrl: 'http://example-1.com',
editPath: '/1/edit',
validationStatus: 'PENDING_VALIDATION',
referencedInSecurityPolicies: [],
},
{
id: 'gid://gitlab/DastSiteProfile/2',
profileName: 'Profile 2',
targetUrl: 'http://example-2.com',
normalizedTargetUrl: 'http://example-2.com',
editPath: '/2/edit',
validationStatus: 'INPROGRESS_VALIDATION',
referencedInSecurityPolicies: [],
},
{
id: 'gid://gitlab/DastSiteProfile/3',
profileName: 'Profile 3',
targetUrl: 'http://example-2.com',
normalizedTargetUrl: 'http://example-2.com',
editPath: '/3/edit',
validationStatus: 'PASSED_VALIDATION',
referencedInSecurityPolicies: [],
},
{
id: 'gid://gitlab/DastSiteProfile/4',
profileName: 'Profile 4',
targetUrl: 'http://example-3.com',
normalizedTargetUrl: 'http://example-3.com',
editPath: '/3/edit',
validationStatus: 'FAILED_VALIDATION',
referencedInSecurityPolicies: [],
},
{
id: 'gid://gitlab/DastSiteProfile/5',
profileName: 'Profile 5',
targetUrl: 'http://example-5.com',
normalizedTargetUrl: 'http://example-5.com',
editPath: '/5/edit',
validationStatus: 'NONE',
referencedInSecurityPolicies: [],
},
];
import siteProfilesFixture from 'test_fixtures/graphql/security_configuration/dast_profiles/graphql/dast_site_profiles.query.graphql.basic.json';
export const siteProfiles = siteProfilesFixture.data.project.siteProfiles.edges.map(
({ node }) => node,
);
export const nonValidatedSiteProfile = siteProfiles.find(
({ validationStatus }) => validationStatus === 'NONE',
);
export const validatedSiteProfile = siteProfiles.find(
({ validationStatus }) => validationStatus === 'PASSED_VALIDATION',
);
export const policySiteProfile = [
{
......
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