Commit 01205f3d authored by David Pisek's avatar David Pisek Committed by Kushal Pandya

Add DAST on-demand scans site profile app

* Entry point (including apollo provider)
* Main Vue App
* ProfileListings Component
* Specs
parent 0aa28970
<script>
import { GlButton, GlTab, GlTabs } from '@gitlab/ui';
import ProfilesListing from './dast_profiles_listing.vue';
export default {
components: {
GlButton,
GlTab,
GlTabs,
ProfilesListing,
},
props: {
newDastSiteProfilePath: {
type: String,
required: true,
},
},
};
</script>
<template>
<section>
<header>
<div class="gl-display-flex gl-align-items-center gl-pt-6 gl-pb-4">
<h2 class="my-0">
{{ s__('DastProfiles|Manage Profiles') }}
</h2>
<gl-button
:href="newDastSiteProfilePath"
category="primary"
variant="success"
class="gl-ml-auto"
>
{{ s__('DastProfiles|New Site Profile') }}
</gl-button>
</div>
<p>
{{
s__(
'DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan.',
)
}}
</p>
</header>
<gl-tabs>
<gl-tab>
<template #title>
<span>{{ s__('DastProfiles|Site Profiles') }}</span>
</template>
<profiles-listing />
</gl-tab>
</gl-tabs>
</section>
</template>
<template>
<section class="gl-py-3">
<p>{{ s__('DastProfiles|No profiles created yet') }}</p>
</section>
</template>
import Vue from 'vue';
import apolloProvider from './graphql/provider';
import DastProfiles from './components/dast_profiles.vue';
export default () => {
const el = document.querySelector('.js-dast-profiles');
if (!el) {
return undefined;
}
const {
dataset: { newDastSiteProfilePath },
} = el;
const props = {
newDastSiteProfilePath,
};
return new Vue({
el,
apolloProvider,
render(h) {
return h(DastProfiles, {
props,
});
},
});
};
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
export default new VueApollo({
defaultClient: createDefaultClient(),
});
import initDastProfiles from 'ee/dast_profiles/dast_profiles_bundle';
document.addEventListener('DOMContentLoaded', initDastProfiles);
......@@ -2,5 +2,4 @@
- breadcrumb_title s_('DastProfiles|Manage profiles')
- page_title s_('DastProfiles|Manage profiles')
%h1= s_('DastProfiles|Manage profiles')
.js-dast-profiles{ data: { new_dast_site_profile_path: new_namespace_project_dast_site_profile_path(namespace_id: @project.namespace, project_id: @project.path) } }
import { shallowMount } from '@vue/test-utils';
import { within } from '@testing-library/dom';
import DastProfilesListing from 'ee/dast_profiles/components/dast_profiles_listing.vue';
describe('EE - DastProfilesListing', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMount(DastProfilesListing);
};
const withinComponent = () => within(wrapper.element);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
describe('empty state', () => {
it('shows a message to indicate that no profiles exist', () => {
const emptyStateMessage = withinComponent().getByText(/no profiles created yet/i);
expect(emptyStateMessage).not.toBe(null);
});
});
});
import { mount } from '@vue/test-utils';
import { within } from '@testing-library/dom';
import DastProfiles from 'ee/dast_profiles/components/dast_profiles.vue';
const TEST_NEW_DAST_SITE_PROFILE_PATH = '/-/on_demand_scans/site_profiles/new';
describe('EE - DastProfiles', () => {
let wrapper;
const createComponent = () => {
const defaultProps = {
newDastSiteProfilePath: TEST_NEW_DAST_SITE_PROFILE_PATH,
};
wrapper = mount(DastProfiles, {
propsData: defaultProps,
});
};
const withinComponent = () => within(wrapper.element);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
describe('header', () => {
it('shows a heading that describes the purpose of the page', () => {
const heading = withinComponent().getByRole('heading', { name: /manage profiles/i });
expect(heading).not.toBe(null);
});
it(`shows a "New Site Profile" anchor that links to ${TEST_NEW_DAST_SITE_PROFILE_PATH}`, () => {
const newProfileButton = withinComponent().getByRole('link', { name: /new site profile/i });
expect(newProfileButton.getAttribute('href')).toBe(TEST_NEW_DAST_SITE_PROFILE_PATH);
});
});
describe('tabs', () => {
it('shows a tab-list that contains the different profile categories', () => {
const tabList = withinComponent().getByRole('tablist');
expect(tabList).not.toBe(null);
});
it.each`
tabName | shouldBeSelectedByDefault
${'Site Profiles'} | ${true}
`(
'shows a "$tabName" tab which has "selected" set to "$shouldBeSelectedByDefault"',
({ tabName, shouldBeSelectedByDefault }) => {
const tab = withinComponent().getByRole('tab', {
name: tabName,
selected: shouldBeSelectedByDefault,
});
expect(tab).not.toBe(null);
},
);
});
});
......@@ -8,7 +8,11 @@ RSpec.describe "projects/dast_profiles/index", type: :view do
render
end
it 'renders a placeholder title' do
expect(rendered).to have_content('Manage profiles')
it 'renders Vue app root' do
expect(rendered).to have_selector('.js-dast-profiles')
end
it 'passes new dast site profile path' do
expect(rendered).to include '/on_demand_scans/profiles/dast_site_profiles/new'
end
end
......@@ -7456,21 +7456,36 @@ msgstr ""
msgid "DastProfiles|Do you want to discard this site profile?"
msgstr ""
msgid "DastProfiles|Manage Profiles"
msgstr ""
msgid "DastProfiles|Manage profiles"
msgstr ""
msgid "DastProfiles|New Site Profile"
msgstr ""
msgid "DastProfiles|New site profile"
msgstr ""
msgid "DastProfiles|No profiles created yet"
msgstr ""
msgid "DastProfiles|Please enter a valid URL format, ex: http://www.example.com/home"
msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
msgid "DastProfiles|Save commonly used configurations for target sites and scan specifications as profiles. Use these with an on-demand scan."
msgstr ""
msgid "DastProfiles|Save profile"
msgstr ""
msgid "DastProfiles|Site Profiles"
msgstr ""
msgid "DastProfiles|Target URL"
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