Commit 5e3b7d04 authored by Mark Florian's avatar Mark Florian Committed by Jan Provaznik

Remove feature flag

This removes the `dependency_list_vulnerabilities` feature flag and all
code/template/spec branches associated with the missing/disabled feature
flag case.

This completes the feature[1] for adding dependency scanning results to
the Dependency List.

[1]: https://gitlab.com/gitlab-org/gitlab-ee/issues/10077
parent 9171ae07
...@@ -20,12 +20,6 @@ export default { ...@@ -20,12 +20,6 @@ export default {
DependencyListJobFailedAlert, DependencyListJobFailedAlert,
PaginatedDependenciesTable, PaginatedDependenciesTable,
}, },
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: { props: {
endpoint: { endpoint: {
type: String, type: String,
...@@ -115,44 +109,27 @@ export default { ...@@ -115,44 +109,27 @@ export default {
@close="dismissJobFailedAlert" @close="dismissJobFailedAlert"
/> />
<template v-if="dependencyListVulnerabilities"> <h3 class="h5">{{ __('Dependencies') }}</h3>
<h3 class="h5">{{ __('Dependencies') }}</h3>
<gl-tabs v-model="currentListIndex" content-class="pt-0">
<gl-tab
v-for="listType in listTypes"
:key="listType.namespace"
:disabled="isTabDisabled(listType.namespace)"
>
<template v-slot:title>
{{ listType.label }}
<gl-badge pill :data-qa-selector="qaCountSelector(listType.label)">{{
totals[listType.namespace]
}}</gl-badge>
</template>
<paginated-dependencies-table :namespace="listType.namespace" />
</gl-tab>
<template v-slot:tabs>
<li class="d-flex align-items-center ml-sm-auto">
<dependencies-actions :namespace="currentList" class="my-2 my-sm-0" />
</li>
</template>
</gl-tabs>
</template>
<template v-else> <gl-tabs v-model="currentListIndex" content-class="pt-0">
<div class="d-sm-flex justify-content-between align-items-baseline my-2"> <gl-tab
<h3 class="h5"> v-for="listType in listTypes"
{{ __('Dependencies') }} :key="listType.namespace"
<gl-badge v-if="pageInfo.total" pill data-qa-selector="dependency_list_total_count">{{ :disabled="isTabDisabled(listType.namespace)"
pageInfo.total >
<template #title>
{{ listType.label }}
<gl-badge pill :data-qa-selector="qaCountSelector(listType.label)">{{
totals[listType.namespace]
}}</gl-badge> }}</gl-badge>
</h3> </template>
<paginated-dependencies-table :namespace="listType.namespace" />
<dependencies-actions :namespace="currentList" /> </gl-tab>
</div> <template #tabs>
<li class="d-flex align-items-center ml-sm-auto">
<paginated-dependencies-table :namespace="currentList" /> <dependencies-actions :namespace="currentList" class="my-2 my-sm-0" />
</template> </li>
</template>
</gl-tabs>
</div> </div>
</template> </template>
...@@ -3,11 +3,7 @@ import { mapActions, mapState } from 'vuex'; ...@@ -3,11 +3,7 @@ import { mapActions, mapState } from 'vuex';
import { GlButton, GlDropdown, GlDropdownItem, GlTooltipDirective } from '@gitlab/ui'; import { GlButton, GlDropdown, GlDropdownItem, GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { DEPENDENCY_LIST_TYPES } from '../store/constants'; import { DEPENDENCY_LIST_TYPES } from '../store/constants';
import { import { SORT_FIELDS, SORT_ORDER } from '../store/modules/list/constants';
SORT_FIELDS,
SORT_FIELDS_WITH_SEVERITY,
SORT_ORDER,
} from '../store/modules/list/constants';
export default { export default {
name: 'DependenciesActions', name: 'DependenciesActions',
...@@ -20,12 +16,6 @@ export default { ...@@ -20,12 +16,6 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: { props: {
namespace: { namespace: {
type: String, type: String,
...@@ -36,7 +26,7 @@ export default { ...@@ -36,7 +26,7 @@ export default {
}, },
data() { data() {
return { return {
sortFields: this.dependencyListVulnerabilities ? SORT_FIELDS_WITH_SEVERITY : SORT_FIELDS, sortFields: SORT_FIELDS,
}; };
}, },
computed: { computed: {
......
...@@ -7,12 +7,6 @@ export default { ...@@ -7,12 +7,6 @@ export default {
components: { components: {
DependenciesTableRow, DependenciesTableRow,
}, },
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: { props: {
dependencies: { dependencies: {
type: Array, type: Array,
...@@ -25,6 +19,7 @@ export default { ...@@ -25,6 +19,7 @@ export default {
}, },
data() { data() {
const tableSections = [ const tableSections = [
{ className: 'section-20', label: s__('Dependencies|Status') },
{ className: 'section-20', label: s__('Dependencies|Component') }, { className: 'section-20', label: s__('Dependencies|Component') },
{ className: 'section-10', label: s__('Dependencies|Version') }, { className: 'section-10', label: s__('Dependencies|Version') },
{ className: 'section-20', label: s__('Dependencies|Packager') }, { className: 'section-20', label: s__('Dependencies|Packager') },
...@@ -32,10 +27,6 @@ export default { ...@@ -32,10 +27,6 @@ export default {
{ className: 'section-15', label: s__('Dependencies|License') }, { className: 'section-15', label: s__('Dependencies|License') },
]; ];
if (this.dependencyListVulnerabilities) {
tableSections.unshift({ className: 'section-20', label: s__('Dependencies|Status') });
}
return { tableSections }; return { tableSections };
}, },
}; };
......
...@@ -14,12 +14,6 @@ export default { ...@@ -14,12 +14,6 @@ export default {
GlSkeletonLoading, GlSkeletonLoading,
Icon, Icon,
}, },
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: { props: {
dependency: { dependency: {
type: Object, type: Object,
...@@ -74,10 +68,7 @@ export default { ...@@ -74,10 +68,7 @@ export default {
</script> </script>
<template> <template>
<div <div class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2">
v-if="dependencyListVulnerabilities"
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
>
<gl-skeleton-loading <gl-skeleton-loading
v-if="isLoading" v-if="isLoading"
:lines="1" :lines="1"
...@@ -161,47 +152,4 @@ export default { ...@@ -161,47 +152,4 @@ export default {
</li> </li>
</ul> </ul>
</div> </div>
<div v-else class="gl-responsive-table-row p-2">
<gl-skeleton-loading
v-if="isLoading"
:lines="1"
class="d-flex flex-column justify-content-center"
/>
<template v-else>
<!-- name-->
<div class="table-section section-20 section-wrap pr-md-3">
<div class="table-mobile-header" role="rowheader">{{ s__('Dependencies|Component') }}</div>
<div class="table-mobile-content">{{ dependency.name }}</div>
</div>
<!-- version -->
<div class="table-section section-10 pr-md-3">
<div class="table-mobile-header" role="rowheader">{{ s__('Dependencies|Version') }}</div>
<div class="table-mobile-content">{{ dependency.version }}</div>
</div>
<!-- packager -->
<div class="table-section section-20 section-wrap pr-md-3">
<div class="table-mobile-header" role="rowheader">{{ s__('Dependencies|Packager') }}</div>
<div class="table-mobile-content">{{ dependency.packager }}</div>
</div>
<!-- location -->
<div class="table-section section-15 section-wrap pr-md-3">
<div class="table-mobile-header" role="rowheader">{{ s__('Dependencies|Location') }}</div>
<div class="table-mobile-content">
<a :href="dependency.location.blob_path">{{ dependency.location.path }}</a>
</div>
</div>
<!-- license -->
<div class="table-section section-15">
<div class="table-mobile-header" role="rowheader">{{ s__('Dependencies|License') }}</div>
<div class="table-mobile-content">
<dependency-license-links :licenses="dependency.licenses" :title="dependency.name" />
</div>
</div>
</template>
</div>
</template> </template>
...@@ -7,13 +7,9 @@ import { addListType } from './store/utils'; ...@@ -7,13 +7,9 @@ import { addListType } from './store/utils';
export default () => { export default () => {
const el = document.querySelector('#js-dependencies-app'); const el = document.querySelector('#js-dependencies-app');
const { endpoint, emptyStateSvgPath, documentationPath } = el.dataset; const { endpoint, emptyStateSvgPath, documentationPath } = el.dataset;
const { dependencyListVulnerabilities = false } = gon.features || {};
const store = createStore(); const store = createStore();
addListType(store, DEPENDENCY_LIST_TYPES.vulnerable);
if (dependencyListVulnerabilities) {
addListType(store, DEPENDENCY_LIST_TYPES.vulnerable);
}
return new Vue({ return new Vue({
el, el,
...@@ -21,9 +17,6 @@ export default () => { ...@@ -21,9 +17,6 @@ export default () => {
components: { components: {
DependenciesApp, DependenciesApp,
}, },
provide: {
dependencyListVulnerabilities,
},
render(createElement) { render(createElement) {
return createElement(DependenciesApp, { return createElement(DependenciesApp, {
props: { props: {
......
...@@ -3,10 +3,6 @@ import { __, s__ } from '~/locale'; ...@@ -3,10 +3,6 @@ import { __, s__ } from '~/locale';
export const SORT_FIELDS = { export const SORT_FIELDS = {
name: s__('Dependencies|Component name'), name: s__('Dependencies|Component name'),
packager: s__('Dependencies|Packager'), packager: s__('Dependencies|Packager'),
};
export const SORT_FIELDS_WITH_SEVERITY = {
...SORT_FIELDS,
severity: s__('Vulnerability|Severity'), severity: s__('Vulnerability|Severity'),
}; };
......
...@@ -4,10 +4,6 @@ module Projects ...@@ -4,10 +4,6 @@ module Projects
class DependenciesController < Projects::ApplicationController class DependenciesController < Projects::ApplicationController
before_action :authorize_read_dependency_list! before_action :authorize_read_dependency_list!
before_action do
push_frontend_feature_flag(:dependency_list_vulnerabilities, default_enabled: true)
end
def authorize_read_dependency_list! def authorize_read_dependency_list!
render_404 unless can?(current_user, :read_dependencies, project) render_404 unless can?(current_user, :read_dependencies, project)
end end
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DependenciesApp component on creation given a dependency list which is known to be incomplete matches the snapshot 1`] = `
<div>
<dependencylistincompletealert-stub />
<!---->
<div
class="d-sm-flex justify-content-between align-items-baseline my-2"
>
<h3
class="h5"
>
Dependencies
<glbadge-stub
data-qa-selector="dependency_list_total_count"
pill=""
>
100
</glbadge-stub>
</h3>
<dependenciesactions-stub
namespace="allDependencies"
/>
</div>
<paginateddependenciestable-stub
namespace="allDependencies"
/>
</div>
`;
exports[`DependenciesApp component on creation given a fetch error matches the snapshot 1`] = `
<div>
<!---->
<!---->
<div
class="d-sm-flex justify-content-between align-items-baseline my-2"
>
<h3
class="h5"
>
Dependencies
<!---->
</h3>
<dependenciesactions-stub
namespace="allDependencies"
/>
</div>
<paginateddependenciestable-stub
namespace="allDependencies"
/>
</div>
`;
exports[`DependenciesApp component on creation given a list of dependencies and ok report matches the snapshot 1`] = `
<div>
<!---->
<!---->
<div
class="d-sm-flex justify-content-between align-items-baseline my-2"
>
<h3
class="h5"
>
Dependencies
<glbadge-stub
data-qa-selector="dependency_list_total_count"
pill=""
>
100
</glbadge-stub>
</h3>
<dependenciesactions-stub
namespace="allDependencies"
/>
</div>
<paginateddependenciestable-stub
namespace="allDependencies"
/>
</div>
`;
exports[`DependenciesApp component on creation given the dependency list job failed matches the snapshot 1`] = `
<div>
<!---->
<dependencylistjobfailedalert-stub
jobpath="/jobs/foo/321"
/>
<div
class="d-sm-flex justify-content-between align-items-baseline my-2"
>
<h3
class="h5"
>
Dependencies
<!---->
</h3>
<dependenciesactions-stub
namespace="allDependencies"
/>
</div>
<paginateddependenciestable-stub
namespace="allDependencies"
/>
</div>
`;
exports[`DependenciesApp component on creation given the dependency list job has not yet run matches the snapshot 1`] = `
<glemptystate-stub
description="The dependency list details information about the components used within your project."
primarybuttonlink="http://test.host"
primarybuttontext="Learn more about the dependency list"
svgpath="/bar.svg"
title="View dependency details for your project"
/>
`;
exports[`DependenciesApp component on creation matches the snapshot 1`] = `
<glloadingicon-stub
class="mt-4"
color="orange"
label="Loading"
size="md"
/>
`;
...@@ -42,79 +42,6 @@ exports[`DependenciesActions component matches the snapshot 1`] = ` ...@@ -42,79 +42,6 @@ exports[`DependenciesActions component matches the snapshot 1`] = `
</span> </span>
</gldropdownitem-stub> </gldropdownitem-stub>
</gldropdown-stub>
<glbutton-stub
class="flex-grow-0 js-sort-order"
data-original-title="Sort direction"
title=""
>
<icon-stub
cssclasses=""
name="sort-lowest"
size="16"
/>
</glbutton-stub>
</div>
<glbutton-stub
class="js-download"
data-original-title="Export as JSON"
download="dependencies.json"
href="http://test.host/dependencies.json"
title=""
>
<icon-stub
cssclasses=""
name="download"
size="16"
/>
</glbutton-stub>
</div>
`;
exports[`DependenciesActions component with feature flag enabled matches the snapshot 1`] = `
<div
class="btn-toolbar"
>
<div
class="btn-group flex-grow-1 mr-2"
>
<gldropdown-stub
class="flex-grow-1 text-center"
right=""
text="Component name"
>
<gldropdownitem-stub>
<span
class="d-flex"
>
<icon-stub
class="flex-shrink-0 append-right-4"
cssclasses=""
name="mobile-issue-close"
size="16"
/>
Component name
</span>
</gldropdownitem-stub>
<gldropdownitem-stub>
<span
class="d-flex"
>
<icon-stub
class="flex-shrink-0 append-right-4 invisible"
cssclasses=""
name="mobile-issue-close"
size="16"
/>
Packager
</span>
</gldropdownitem-stub>
<gldropdownitem-stub> <gldropdownitem-stub>
<span <span
class="d-flex" class="d-flex"
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DependenciesTableRow component given the dependencyListVulnerabilities flag is enabled when a dependency with no vulnerabilities is loaded matches the snapshot 1`] = ` exports[`DependenciesTableRow component when a dependency with no vulnerabilities is loaded matches the snapshot 1`] = `
<div <div
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2" class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
> >
...@@ -134,7 +134,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities ...@@ -134,7 +134,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
</div> </div>
`; `;
exports[`DependenciesTableRow component given the dependencyListVulnerabilities flag is enabled when a dependency with vulnerabilities is loaded matches the snapshot 1`] = ` exports[`DependenciesTableRow component when a dependency with vulnerabilities is loaded matches the snapshot 1`] = `
<div <div
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2" class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
> >
...@@ -270,7 +270,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities ...@@ -270,7 +270,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
</div> </div>
`; `;
exports[`DependenciesTableRow component given the dependencyListVulnerabilities flag is enabled when loading matches the snapshot 1`] = ` exports[`DependenciesTableRow component when loading matches the snapshot 1`] = `
<div <div
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2" class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
> >
...@@ -283,7 +283,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities ...@@ -283,7 +283,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
</div> </div>
`; `;
exports[`DependenciesTableRow component given the dependencyListVulnerabilities flag is enabled when passed no props matches the snapshot 1`] = ` exports[`DependenciesTableRow component when passed no props matches the snapshot 1`] = `
<div <div
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2" class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
> >
...@@ -295,123 +295,3 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities ...@@ -295,123 +295,3 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
<!----> <!---->
</div> </div>
`; `;
exports[`DependenciesTableRow component when a dependency is loaded matches the snapshot 1`] = `
<div
class="gl-responsive-table-row p-2"
>
<div
class="table-section section-20 section-wrap pr-md-3"
>
<div
class="table-mobile-header"
role="rowheader"
>
Component
</div>
<div
class="table-mobile-content"
>
left-pad
</div>
</div>
<div
class="table-section section-10 pr-md-3"
>
<div
class="table-mobile-header"
role="rowheader"
>
Version
</div>
<div
class="table-mobile-content"
>
0.0.3
</div>
</div>
<div
class="table-section section-20 section-wrap pr-md-3"
>
<div
class="table-mobile-header"
role="rowheader"
>
Packager
</div>
<div
class="table-mobile-content"
>
JavaScript (yarn)
</div>
</div>
<div
class="table-section section-15 section-wrap pr-md-3"
>
<div
class="table-mobile-header"
role="rowheader"
>
Location
</div>
<div
class="table-mobile-content"
>
<a
href="/a-group/a-project/blob/da39a3ee5e6b4b0d3255bfef95601890afd80709/yarn.lock"
>
yarn.lock
</a>
</div>
</div>
<div
class="table-section section-15"
>
<div
class="table-mobile-header"
role="rowheader"
>
License
</div>
<div
class="table-mobile-content"
>
<dependencylicenselinks-stub
licenses=""
title="left-pad"
/>
</div>
</div>
</div>
`;
exports[`DependenciesTableRow component when loading matches the snapshot 1`] = `
<div
class="gl-responsive-table-row p-2"
>
<glskeletonloading-stub
class="d-flex flex-column justify-content-center"
lines="1"
/>
</div>
`;
exports[`DependenciesTableRow component when passed no props matches the snapshot 1`] = `
<div
class="gl-responsive-table-row p-2"
>
<glskeletonloading-stub
class="d-flex flex-column justify-content-center"
lines="1"
/>
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DependenciesTable component given a list of dependencies (loaded) matches the snapshot 1`] = ` exports[`DependenciesTable component given a list of dependencies (loaded) matches the snapshot 1`] = `
<div>
<div
class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2"
role="row"
>
<div
class="table-section section-20"
role="rowheader"
>
Component
</div>
<div
class="table-section section-10"
role="rowheader"
>
Version
</div>
<div
class="table-section section-20"
role="rowheader"
>
Packager
</div>
<div
class="table-section section-15"
role="rowheader"
>
Location
</div>
<div
class="table-section section-15"
role="rowheader"
>
License
</div>
</div>
<dependenciestablerow-stub
dependency="[object Object]"
/>
<dependenciestablerow-stub
dependency="[object Object]"
/>
</div>
`;
exports[`DependenciesTable component given a list of dependencies (loading) matches the snapshot 1`] = `
<div>
<div
class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2"
role="row"
>
<div
class="table-section section-20"
role="rowheader"
>
Component
</div>
<div
class="table-section section-10"
role="rowheader"
>
Version
</div>
<div
class="table-section section-20"
role="rowheader"
>
Packager
</div>
<div
class="table-section section-15"
role="rowheader"
>
Location
</div>
<div
class="table-section section-15"
role="rowheader"
>
License
</div>
</div>
<dependenciestablerow-stub
dependency="[object Object]"
isloading="true"
/>
<dependenciestablerow-stub
dependency="[object Object]"
isloading="true"
/>
</div>
`;
exports[`DependenciesTable component given an empty list of dependencies matches the snapshot 1`] = `
<div>
<div
class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2"
role="row"
>
<div
class="table-section section-20"
role="rowheader"
>
Component
</div>
<div
class="table-section section-10"
role="rowheader"
>
Version
</div>
<div
class="table-section section-20"
role="rowheader"
>
Packager
</div>
<div
class="table-section section-15"
role="rowheader"
>
Location
</div>
<div
class="table-section section-15"
role="rowheader"
>
License
</div>
</div>
</div>
`;
exports[`DependenciesTable component given the dependencyListVulnerabilities flag is enabled given a list of dependencies (loaded) matches the snapshot 1`] = `
<div> <div>
<div <div
class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2" class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2"
...@@ -232,7 +65,7 @@ exports[`DependenciesTable component given the dependencyListVulnerabilities fla ...@@ -232,7 +65,7 @@ exports[`DependenciesTable component given the dependencyListVulnerabilities fla
</div> </div>
`; `;
exports[`DependenciesTable component given the dependencyListVulnerabilities flag is enabled given a list of dependencies (loading) matches the snapshot 1`] = ` exports[`DependenciesTable component given a list of dependencies (loading) matches the snapshot 1`] = `
<div> <div>
<div <div
class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2" class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2"
...@@ -299,7 +132,7 @@ exports[`DependenciesTable component given the dependencyListVulnerabilities fla ...@@ -299,7 +132,7 @@ exports[`DependenciesTable component given the dependencyListVulnerabilities fla
</div> </div>
`; `;
exports[`DependenciesTable component given the dependencyListVulnerabilities flag is enabled given an empty list of dependencies matches the snapshot 1`] = ` exports[`DependenciesTable component given an empty list of dependencies matches the snapshot 1`] = `
<div> <div>
<div <div
class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2" class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2"
......
import { GlBadge, GlEmptyState, GlLoadingIcon, GlTab } from '@gitlab/ui'; import { GlBadge, GlEmptyState, GlLoadingIcon, GlTab } from '@gitlab/ui';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils'; import { createLocalVue, mount } from '@vue/test-utils';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import createStore from 'ee/dependencies/store'; import createStore from 'ee/dependencies/store';
import { addListType } from 'ee/dependencies/store/utils'; import { addListType } from 'ee/dependencies/store/utils';
...@@ -12,220 +12,6 @@ import DependencyListJobFailedAlert from 'ee/dependencies/components/dependency_ ...@@ -12,220 +12,6 @@ import DependencyListJobFailedAlert from 'ee/dependencies/components/dependency_
import PaginatedDependenciesTable from 'ee/dependencies/components/paginated_dependencies_table.vue'; import PaginatedDependenciesTable from 'ee/dependencies/components/paginated_dependencies_table.vue';
describe('DependenciesApp component', () => { describe('DependenciesApp component', () => {
let store;
let wrapper;
const { namespace } = DEPENDENCY_LIST_TYPES.all;
const basicAppProps = {
endpoint: '/foo',
emptyStateSvgPath: '/bar.svg',
documentationPath: TEST_HOST,
};
const factory = (props = basicAppProps) => {
const localVue = createLocalVue();
store = createStore();
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = shallowMount(DependenciesApp, {
localVue,
store,
sync: false,
propsData: { ...props },
});
};
const expectComponentWithProps = (Component, props = {}) => {
const componentWrapper = wrapper.find(Component);
expect(componentWrapper.isVisible()).toBe(true);
expect(componentWrapper.props()).toEqual(expect.objectContaining(props));
};
afterEach(() => {
wrapper.destroy();
});
describe('on creation', () => {
let dependencies;
beforeEach(() => {
factory();
});
it('dispatches the correct initial actions', () => {
expect(store.dispatch.mock.calls).toEqual([
['setDependenciesEndpoint', basicAppProps.endpoint],
['fetchDependencies'],
]);
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
describe('given a list of dependencies and ok report', () => {
beforeEach(() => {
dependencies = ['foo', 'bar'];
Object.assign(store.state[namespace], {
initialized: true,
isLoading: false,
dependencies,
});
store.state[namespace].pageInfo.total = 100;
store.state[namespace].reportInfo.status = REPORT_STATUS.ok;
return wrapper.vm.$nextTick();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('passes the correct props to the paginated dependencies table', () => {
expectComponentWithProps(PaginatedDependenciesTable, {
namespace,
});
});
});
describe('given the dependency list job has not yet run', () => {
beforeEach(() => {
dependencies = [];
Object.assign(store.state[namespace], {
initialized: true,
isLoading: false,
dependencies,
});
store.state[namespace].pageInfo.total = 0;
store.state[namespace].reportInfo.status = REPORT_STATUS.jobNotSetUp;
return wrapper.vm.$nextTick();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
});
describe('given the dependency list job failed', () => {
beforeEach(() => {
dependencies = [];
Object.assign(store.state[namespace], {
initialized: true,
isLoading: false,
dependencies,
});
store.state[namespace].pageInfo.total = 0;
store.state[namespace].reportInfo.status = REPORT_STATUS.jobFailed;
store.state[namespace].reportInfo.jobPath = '/jobs/foo/321';
return wrapper.vm.$nextTick();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('passes the correct props to the job failure alert', () => {
expectComponentWithProps(DependencyListJobFailedAlert, {
jobPath: store.state[namespace].reportInfo.jobPath,
});
});
it('passes the correct props to the paginated dependencies table', () => {
expectComponentWithProps(PaginatedDependenciesTable, {
namespace,
});
});
describe('when the job failure alert emits the close event', () => {
beforeEach(() => {
const alertWrapper = wrapper.find(DependencyListJobFailedAlert);
alertWrapper.vm.$emit('close');
return wrapper.vm.$nextTick();
});
it('does not render the job failure alert', () => {
expect(wrapper.find(DependencyListJobFailedAlert).exists()).toBe(false);
});
});
});
describe('given a dependency list which is known to be incomplete', () => {
beforeEach(() => {
dependencies = ['foo', 'bar'];
Object.assign(store.state[namespace], {
initialized: true,
isLoading: false,
dependencies,
});
store.state[namespace].pageInfo.total = 100;
store.state[namespace].reportInfo.status = REPORT_STATUS.incomplete;
return wrapper.vm.$nextTick();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('passes the correct props to the incomplete-list alert', () => {
const alert = wrapper.find(DependencyListIncompleteAlert);
expect(alert.isVisible()).toBe(true);
});
it('passes the correct props to the paginated dependencies table', () => {
expectComponentWithProps(PaginatedDependenciesTable, {
namespace,
});
});
describe('when the incomplete-list alert emits the close event', () => {
beforeEach(() => {
const alertWrapper = wrapper.find(DependencyListIncompleteAlert);
alertWrapper.vm.$emit('close');
return wrapper.vm.$nextTick();
});
it('does not render the incomplete-list alert', () => {
expect(wrapper.find(DependencyListIncompleteAlert).exists()).toBe(false);
});
});
});
describe('given a fetch error', () => {
beforeEach(() => {
dependencies = [];
Object.assign(store.state[namespace], {
initialized: true,
isLoading: false,
errorLoading: true,
dependencies,
});
return wrapper.vm.$nextTick();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('passes the correct props to the paginated dependencies table', () => {
expectComponentWithProps(PaginatedDependenciesTable, {
namespace,
});
});
});
});
});
describe('DependenciesApp component with dependencyListVulnerabilities feature flag enabled', () => {
let store; let store;
let wrapper; let wrapper;
const { namespace: allNamespace } = DEPENDENCY_LIST_TYPES.all; const { namespace: allNamespace } = DEPENDENCY_LIST_TYPES.all;
...@@ -252,9 +38,6 @@ describe('DependenciesApp component with dependencyListVulnerabilities feature f ...@@ -252,9 +38,6 @@ describe('DependenciesApp component with dependencyListVulnerabilities feature f
store, store,
sync: false, sync: false,
propsData: { ...props }, propsData: { ...props },
provide: {
dependencyListVulnerabilities: true,
},
stubs, stubs,
}); });
}; };
......
...@@ -3,17 +3,10 @@ import { GlDropdownItem } from '@gitlab/ui'; ...@@ -3,17 +3,10 @@ import { GlDropdownItem } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import createStore from 'ee/dependencies/store'; import createStore from 'ee/dependencies/store';
import { DEPENDENCY_LIST_TYPES } from 'ee/dependencies/store/constants'; import { DEPENDENCY_LIST_TYPES } from 'ee/dependencies/store/constants';
import { import { SORT_FIELDS } from 'ee/dependencies/store/modules/list/constants';
SORT_FIELDS,
SORT_FIELDS_WITH_SEVERITY,
} from 'ee/dependencies/store/modules/list/constants';
import DependenciesActions from 'ee/dependencies/components/dependencies_actions.vue'; import DependenciesActions from 'ee/dependencies/components/dependencies_actions.vue';
describe.each` describe('DependenciesActions component', () => {
context | isFeatureFlagEnabled | sortFields
${''} | ${false} | ${SORT_FIELDS}
${' with feature flag enabled'} | ${true} | ${SORT_FIELDS_WITH_SEVERITY}
`('DependenciesActions component$context', ({ isFeatureFlagEnabled, sortFields }) => {
let store; let store;
let wrapper; let wrapper;
const { namespace } = DEPENDENCY_LIST_TYPES.all; const { namespace } = DEPENDENCY_LIST_TYPES.all;
...@@ -36,7 +29,6 @@ describe.each` ...@@ -36,7 +29,6 @@ describe.each`
beforeEach(() => { beforeEach(() => {
factory({ factory({
propsData: { namespace }, propsData: { namespace },
provide: { dependencyListVulnerabilities: isFeatureFlagEnabled },
}); });
store.state[namespace].endpoint = `${TEST_HOST}/dependencies`; store.state[namespace].endpoint = `${TEST_HOST}/dependencies`;
return wrapper.vm.$nextTick(); return wrapper.vm.$nextTick();
...@@ -61,7 +53,7 @@ describe.each` ...@@ -61,7 +53,7 @@ describe.each`
expect(store.dispatch.mock.calls).toEqual( expect(store.dispatch.mock.calls).toEqual(
expect.arrayContaining( expect.arrayContaining(
Object.keys(sortFields).map(field => [`${namespace}/setSortField`, field]), Object.keys(SORT_FIELDS).map(field => [`${namespace}/setSortField`, field]),
), ),
); );
}); });
......
...@@ -2,7 +2,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils'; ...@@ -2,7 +2,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import DependenciesTableRow from 'ee/dependencies/components/dependencies_table_row.vue'; import DependenciesTableRow from 'ee/dependencies/components/dependencies_table_row.vue';
import DependencyVulnerability from 'ee/dependencies/components/dependency_vulnerability.vue'; import DependencyVulnerability from 'ee/dependencies/components/dependency_vulnerability.vue';
import { MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY } from 'ee/dependencies/components/constants'; import { MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY } from 'ee/dependencies/components/constants';
import { makeDependency, provideEnabledFeatureFlag } from './utils'; import { makeDependency } from './utils';
import mockDataVulnerabilities from '../../../javascripts/security_dashboard/store/vulnerabilities/data/mock_data_vulnerabilities.json'; import mockDataVulnerabilities from '../../../javascripts/security_dashboard/store/vulnerabilities/data/mock_data_vulnerabilities.json';
describe('DependenciesTableRow component', () => { describe('DependenciesTableRow component', () => {
...@@ -66,12 +66,12 @@ describe('DependenciesTableRow component', () => { ...@@ -66,12 +66,12 @@ describe('DependenciesTableRow component', () => {
}); });
}); });
describe('when a dependency is loaded', () => { describe('when a dependency with no vulnerabilities is loaded', () => {
beforeEach(() => { beforeEach(() => {
factory({ factory({
propsData: { propsData: {
isLoading: false, isLoading: false,
dependency: makeDependency(), dependency: makeDependency({ vulnerabilities: [] }),
}, },
}); });
}); });
...@@ -81,123 +81,78 @@ describe('DependenciesTableRow component', () => { ...@@ -81,123 +81,78 @@ describe('DependenciesTableRow component', () => {
}); });
}); });
describe('given the dependencyListVulnerabilities flag is enabled', () => { describe('when a dependency with vulnerabilities is loaded', () => {
describe('when passed no props', () => { beforeEach(() => {
beforeEach(() => { factory({
factory(provideEnabledFeatureFlag()); propsData: {
}); isLoading: false,
dependency: makeDependency({ vulnerabilities: mockDataVulnerabilities }),
it('matches the snapshot', () => { },
expect(wrapper.element).toMatchSnapshot();
}); });
}); });
describe('when loading', () => { it('matches the snapshot', () => {
beforeEach(() => { expect(wrapper.element).toMatchSnapshot();
factory({
...provideEnabledFeatureFlag(),
propsData: {
isLoading: true,
},
});
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
}); });
describe('when a dependency with no vulnerabilities is loaded', () => { describe('when the list of vulnerabilities is expanded', () => {
beforeEach(() => { beforeEach(clickToggle);
factory({
...provideEnabledFeatureFlag(),
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: [] }),
},
});
});
it('matches the snapshot', () => { it('renders each vulnerability', () => {
expect(wrapper.element).toMatchSnapshot(); expectVulnerabilitiesExpanded(mockDataVulnerabilities);
}); });
});
describe('when a dependency with vulnerabilities is loaded', () => { describe('when clicking the toggle ', () => {
beforeEach(() => {
factory({
...provideEnabledFeatureFlag(),
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: mockDataVulnerabilities }),
},
});
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
describe('when the list of vulnerabilities is expanded', () => {
beforeEach(clickToggle); beforeEach(clickToggle);
it('renders each vulnerability', () => { it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed);
expectVulnerabilitiesExpanded(mockDataVulnerabilities); });
});
describe('when clicking the toggle ', () => {
beforeEach(clickToggle);
it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed);
});
describe('when the dependency prop changes', () => {
beforeEach(() => {
wrapper.setProps({
dependency: makeDependency({ vulnerabilities: mockDataVulnerabilities }),
});
return wrapper.vm.$nextTick(); describe('when the dependency prop changes', () => {
beforeEach(() => {
wrapper.setProps({
dependency: makeDependency({ vulnerabilities: mockDataVulnerabilities }),
}); });
it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed); return wrapper.vm.$nextTick();
}); });
describe('when the isLoading prop changes', () => { it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed);
beforeEach(() => { });
wrapper.setProps({
isLoading: true,
});
return wrapper.vm.$nextTick(); describe('when the isLoading prop changes', () => {
beforeEach(() => {
wrapper.setProps({
isLoading: true,
}); });
it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed); return wrapper.vm.$nextTick();
}); });
it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed);
}); });
}); });
});
describe('when a dependency with a huge number vulnerabilities is loaded and expanded', () => { describe('when a dependency with a huge number vulnerabilities is loaded and expanded', () => {
beforeEach(() => { beforeEach(() => {
const hugeNumberOfVulnerabilities = Array(1 + MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY) const hugeNumberOfVulnerabilities = Array(1 + MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY)
.fill(null) .fill(null)
.map((_, id) => ({ id })); .map((_, id) => ({ id }));
factory({
...provideEnabledFeatureFlag(),
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: hugeNumberOfVulnerabilities }),
},
});
return clickToggle(); factory({
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: hugeNumberOfVulnerabilities }),
},
}); });
it('does not render all of them', () => { return clickToggle();
expect(findVulnerabilities().length).toBe(MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY); });
expect(findExcessMessage().isVisible()).toBe(true);
}); it('does not render all of them', () => {
expect(findVulnerabilities().length).toBe(MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY);
expect(findExcessMessage().isVisible()).toBe(true);
}); });
}); });
}); });
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import DependenciesTable from 'ee/dependencies/components/dependencies_table.vue'; import DependenciesTable from 'ee/dependencies/components/dependencies_table.vue';
import DependenciesTableRow from 'ee/dependencies/components/dependencies_table_row.vue'; import DependenciesTableRow from 'ee/dependencies/components/dependencies_table_row.vue';
import { makeDependency, provideEnabledFeatureFlag } from './utils'; import { makeDependency } from './utils';
describe('DependenciesTable component', () => { describe('DependenciesTable component', () => {
let wrapper; let wrapper;
...@@ -66,54 +66,4 @@ describe('DependenciesTable component', () => { ...@@ -66,54 +66,4 @@ describe('DependenciesTable component', () => {
}); });
}); });
}); });
describe('given the dependencyListVulnerabilities flag is enabled', () => {
describe('given an empty list of dependencies', () => {
beforeEach(() => {
factory({
...provideEnabledFeatureFlag(),
propsData: {
dependencies: [],
isLoading: false,
},
});
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
});
[true, false].forEach(isLoading => {
describe(`given a list of dependencies (${isLoading ? 'loading' : 'loaded'})`, () => {
let dependencies;
beforeEach(() => {
dependencies = [makeDependency(), makeDependency({ name: 'foo' })];
factory({
...provideEnabledFeatureFlag(),
propsData: {
dependencies,
isLoading,
},
});
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('passes the correct props to the table rows', () => {
const rows = wrapper.findAll(DependenciesTableRow).wrappers;
rows.forEach((row, index) => {
expect(row.props()).toEqual(
expect.objectContaining({
dependency: dependencies[index],
isLoading,
}),
);
});
});
});
});
});
}); });
// eslint-disable-next-line import/prefer-default-export
export const makeDependency = (changes = {}) => ({ export const makeDependency = (changes = {}) => ({
name: 'left-pad', name: 'left-pad',
version: '0.0.3', version: '0.0.3',
...@@ -9,7 +10,3 @@ export const makeDependency = (changes = {}) => ({ ...@@ -9,7 +10,3 @@ export const makeDependency = (changes = {}) => ({
licenses: [], licenses: [],
...changes, ...changes,
}); });
export const provideEnabledFeatureFlag = () => ({
provide: { dependencyListVulnerabilities: true },
});
...@@ -6,7 +6,6 @@ module QA ...@@ -6,7 +6,6 @@ module QA
module Project::Secure module Project::Secure
class DependencyList < QA::Page::Base class DependencyList < QA::Page::Base
view 'ee/app/assets/javascripts/dependencies/components/app.vue' do view 'ee/app/assets/javascripts/dependencies/components/app.vue' do
element :dependency_list_total_count
element :dependency_list_all_count, "dependency_list_${label.toLowerCase().replace(' ', '_')" # rubocop:disable QA/ElementWithPattern element :dependency_list_all_count, "dependency_list_${label.toLowerCase().replace(' ', '_')" # rubocop:disable QA/ElementWithPattern
end end
......
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