Commit b381e7ce authored by Kushal Pandya's avatar Kushal Pandya

Merge branch...

Merge branch '233453-dast-scanner-profile-library-implementation-iteration-1-add-scanner-profiles-to-library-view-link-to-tab' into 'master'

Add locationHash support to DAST scanner-profile library

See merge request gitlab-org/gitlab!41532
parents b03e4224 99348ebe
<script> <script>
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { GlDropdown, GlDropdownItem, GlTab, GlTabs } from '@gitlab/ui'; import { GlDropdown, GlDropdownItem, GlTab, GlTabs } from '@gitlab/ui';
import { camelCase, kebabCase } from 'lodash';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { getLocationHash } from '~/lib/utils/url_utility';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ProfilesList from './dast_profiles_list.vue'; import ProfilesList from './dast_profiles_list.vue';
import * as cacheUtils from '../graphql/cache_utils'; import * as cacheUtils from '../graphql/cache_utils';
...@@ -46,11 +48,23 @@ export default { ...@@ -46,11 +48,23 @@ export default {
glFeatures, glFeatures,
); );
}, },
tabIndex: {
get() {
const activeTabIndex = Object.keys(this.profileSettings).indexOf(
camelCase(getLocationHash()),
);
return Math.max(0, activeTabIndex);
},
},
}, },
created() { created() {
this.addSmartQueriesForEnabledProfileTypes(); this.addSmartQueriesForEnabledProfileTypes();
}, },
methods: { methods: {
setLocationHash(profileType) {
window.location.hash = kebabCase(profileType);
},
addSmartQueriesForEnabledProfileTypes() { addSmartQueriesForEnabledProfileTypes() {
Object.values(this.profileSettings).forEach(({ profileType, graphQL: { query } }) => { Object.values(this.profileSettings).forEach(({ profileType, graphQL: { query } }) => {
this.makeProfileTypeReactive(profileType); this.makeProfileTypeReactive(profileType);
...@@ -227,10 +241,14 @@ export default { ...@@ -227,10 +241,14 @@ export default {
</p> </p>
</header> </header>
<gl-tabs> <gl-tabs v-model="tabIndex">
<gl-tab v-for="(data, profileType) in profileSettings" :key="profileType"> <gl-tab
v-for="(settings, profileType) in profileSettings"
:key="profileType"
@click="setLocationHash(profileType)"
>
<template #title> <template #title>
<span>{{ profileSettings[profileType].i18n.tabName }}</span> <span>{{ settings.i18n.tabName }}</span>
</template> </template>
<profiles-list <profiles-list
...@@ -241,7 +259,7 @@ export default { ...@@ -241,7 +259,7 @@ export default {
:is-loading="isLoadingProfiles(profileType)" :is-loading="isLoadingProfiles(profileType)"
:profiles-per-page="$options.profilesPerPage" :profiles-per-page="$options.profilesPerPage"
:profiles="profileTypes[profileType].profiles" :profiles="profileTypes[profileType].profiles"
:fields="profileSettings[profileType].tableFields" :fields="settings.tableFields"
@load-more-profiles="fetchMoreProfiles(profileType)" @load-more-profiles="fetchMoreProfiles(profileType)"
@delete-profile="deleteProfile(profileType, $event)" @delete-profile="deleteProfile(profileType, $event)"
/> />
......
import { mount, shallowMount } from '@vue/test-utils'; import { mount, shallowMount, createWrapper } from '@vue/test-utils';
import { within } from '@testing-library/dom'; import { within } from '@testing-library/dom';
import { merge } from 'lodash'; import { merge } from 'lodash';
import { GlDropdown } from '@gitlab/ui'; import { GlDropdown } from '@gitlab/ui';
import setWindowLocation from 'helpers/set_window_location_helper';
import DastProfiles from 'ee/dast_profiles/components/dast_profiles.vue'; import DastProfiles from 'ee/dast_profiles/components/dast_profiles.vue';
const TEST_NEW_DAST_SCANNER_PROFILE_PATH = '/-/on_demand_scans/scanner_profiles/new'; const TEST_NEW_DAST_SCANNER_PROFILE_PATH = '/-/on_demand_scans/scanner_profiles/new';
...@@ -81,6 +82,11 @@ describe('EE - DastProfiles', () => { ...@@ -81,6 +82,11 @@ describe('EE - DastProfiles', () => {
const getDropdownComponent = () => wrapper.find(GlDropdown); const getDropdownComponent = () => wrapper.find(GlDropdown);
const getSiteProfilesDropdownItem = text => const getSiteProfilesDropdownItem = text =>
within(getDropdownComponent().element).queryByText(text); within(getDropdownComponent().element).queryByText(text);
const getTab = ({ tabName, selected }) =>
withinComponent().getByRole('tab', {
name: tabName,
selected,
});
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
...@@ -124,31 +130,69 @@ describe('EE - DastProfiles', () => { ...@@ -124,31 +130,69 @@ describe('EE - DastProfiles', () => {
}); });
describe('tabs', () => { describe('tabs', () => {
beforeEach(() => { const originalLocation = window.location;
createFullComponent();
}); describe('without location hash set', () => {
beforeEach(() => {
createFullComponent();
});
it('shows a tab-list that contains the different profile categories', () => { it('shows a tab-list that contains the different profile categories', () => {
const tabList = withinComponent().getByRole('tablist'); const tabList = withinComponent().getByRole('tablist');
expect(tabList).not.toBe(null); expect(tabList).not.toBe(null);
});
it.each`
tabName | shouldBeSelectedByDefault
${'Site Profiles'} | ${true}
${'Scanner Profiles'} | ${false}
`(
'shows a "$tabName" tab which has "selected" set to "$shouldBeSelectedByDefault"',
({ tabName, shouldBeSelectedByDefault }) => {
const tab = getTab({
tabName,
selected: shouldBeSelectedByDefault,
});
expect(tab).not.toBe(null);
},
);
}); });
it.each` describe.each`
tabName | shouldBeSelectedByDefault tabName | givenLocationHash
${'Site Profiles'} | ${true} ${'Site Profiles'} | ${'site-profiles'}
${'Scanner Profiles'} | ${false} ${'Scanner Profiles'} | ${'scanner-profiles'}
`( `('with location hash set to "$givenLocationHash"', ({ tabName, givenLocationHash }) => {
'shows a "$tabName" tab which has "selected" set to "$shouldBeSelectedByDefault"', beforeEach(() => {
({ tabName, shouldBeSelectedByDefault }) => { setWindowLocation(`http://foo.com/index#${givenLocationHash}`);
const tab = withinComponent().getByRole('tab', { createFullComponent();
name: tabName, });
selected: shouldBeSelectedByDefault,
afterEach(() => {
window.location = originalLocation;
});
it(`has "${tabName}" selected`, () => {
const tab = getTab({
tabName,
selected: true,
}); });
expect(tab).not.toBe(null); expect(tab).not.toBe(null);
}, });
);
it('updates the browsers URL to contain the selected tab', () => {
window.location.hash = '';
const tab = getTab({ tabName });
createWrapper(tab).trigger('click');
expect(window.location.hash).toBe(givenLocationHash);
});
});
}); });
describe.each` describe.each`
......
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