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 {
DependencyListJobFailedAlert,
PaginatedDependenciesTable,
},
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: {
endpoint: {
type: String,
......@@ -115,44 +109,27 @@ export default {
@close="dismissJobFailedAlert"
/>
<template v-if="dependencyListVulnerabilities">
<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>
<h3 class="h5">{{ __('Dependencies') }}</h3>
<template v-else>
<div class="d-sm-flex justify-content-between align-items-baseline my-2">
<h3 class="h5">
{{ __('Dependencies') }}
<gl-badge v-if="pageInfo.total" pill data-qa-selector="dependency_list_total_count">{{
pageInfo.total
<gl-tabs v-model="currentListIndex" content-class="pt-0">
<gl-tab
v-for="listType in listTypes"
:key="listType.namespace"
:disabled="isTabDisabled(listType.namespace)"
>
<template #title>
{{ listType.label }}
<gl-badge pill :data-qa-selector="qaCountSelector(listType.label)">{{
totals[listType.namespace]
}}</gl-badge>
</h3>
<dependencies-actions :namespace="currentList" />
</div>
<paginated-dependencies-table :namespace="currentList" />
</template>
</template>
<paginated-dependencies-table :namespace="listType.namespace" />
</gl-tab>
<template #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>
</div>
</template>
......@@ -3,11 +3,7 @@ import { mapActions, mapState } from 'vuex';
import { GlButton, GlDropdown, GlDropdownItem, GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { DEPENDENCY_LIST_TYPES } from '../store/constants';
import {
SORT_FIELDS,
SORT_FIELDS_WITH_SEVERITY,
SORT_ORDER,
} from '../store/modules/list/constants';
import { SORT_FIELDS, SORT_ORDER } from '../store/modules/list/constants';
export default {
name: 'DependenciesActions',
......@@ -20,12 +16,6 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: {
namespace: {
type: String,
......@@ -36,7 +26,7 @@ export default {
},
data() {
return {
sortFields: this.dependencyListVulnerabilities ? SORT_FIELDS_WITH_SEVERITY : SORT_FIELDS,
sortFields: SORT_FIELDS,
};
},
computed: {
......
......@@ -7,12 +7,6 @@ export default {
components: {
DependenciesTableRow,
},
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: {
dependencies: {
type: Array,
......@@ -25,6 +19,7 @@ export default {
},
data() {
const tableSections = [
{ className: 'section-20', label: s__('Dependencies|Status') },
{ className: 'section-20', label: s__('Dependencies|Component') },
{ className: 'section-10', label: s__('Dependencies|Version') },
{ className: 'section-20', label: s__('Dependencies|Packager') },
......@@ -32,10 +27,6 @@ export default {
{ className: 'section-15', label: s__('Dependencies|License') },
];
if (this.dependencyListVulnerabilities) {
tableSections.unshift({ className: 'section-20', label: s__('Dependencies|Status') });
}
return { tableSections };
},
};
......
......@@ -14,12 +14,6 @@ export default {
GlSkeletonLoading,
Icon,
},
inject: {
dependencyListVulnerabilities: {
from: 'dependencyListVulnerabilities',
default: false,
},
},
props: {
dependency: {
type: Object,
......@@ -74,10 +68,7 @@ export default {
</script>
<template>
<div
v-if="dependencyListVulnerabilities"
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
>
<div class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2">
<gl-skeleton-loading
v-if="isLoading"
:lines="1"
......@@ -161,47 +152,4 @@ export default {
</li>
</ul>
</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>
......@@ -7,13 +7,9 @@ import { addListType } from './store/utils';
export default () => {
const el = document.querySelector('#js-dependencies-app');
const { endpoint, emptyStateSvgPath, documentationPath } = el.dataset;
const { dependencyListVulnerabilities = false } = gon.features || {};
const store = createStore();
if (dependencyListVulnerabilities) {
addListType(store, DEPENDENCY_LIST_TYPES.vulnerable);
}
addListType(store, DEPENDENCY_LIST_TYPES.vulnerable);
return new Vue({
el,
......@@ -21,9 +17,6 @@ export default () => {
components: {
DependenciesApp,
},
provide: {
dependencyListVulnerabilities,
},
render(createElement) {
return createElement(DependenciesApp, {
props: {
......
......@@ -3,10 +3,6 @@ import { __, s__ } from '~/locale';
export const SORT_FIELDS = {
name: s__('Dependencies|Component name'),
packager: s__('Dependencies|Packager'),
};
export const SORT_FIELDS_WITH_SEVERITY = {
...SORT_FIELDS,
severity: s__('Vulnerability|Severity'),
};
......
......@@ -4,10 +4,6 @@ module Projects
class DependenciesController < Projects::ApplicationController
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!
render_404 unless can?(current_user, :read_dependencies, project)
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`] = `
</span>
</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>
<span
class="d-flex"
......
// 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
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
>
......@@ -134,7 +134,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
</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
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
>
......@@ -270,7 +270,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
</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
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
>
......@@ -283,7 +283,7 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
</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
class="gl-responsive-table-row flex-md-column align-items-md-stretch px-2"
>
......@@ -295,123 +295,3 @@ exports[`DependenciesTableRow component given the dependencyListVulnerabilities
<!---->
</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
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
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
</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
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
</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
class="gl-responsive-table-row table-row-header text-2 bg-secondary-50 px-2"
......
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 createStore from 'ee/dependencies/store';
import { addListType } from 'ee/dependencies/store/utils';
......@@ -12,220 +12,6 @@ import DependencyListJobFailedAlert from 'ee/dependencies/components/dependency_
import PaginatedDependenciesTable from 'ee/dependencies/components/paginated_dependencies_table.vue';
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 wrapper;
const { namespace: allNamespace } = DEPENDENCY_LIST_TYPES.all;
......@@ -252,9 +38,6 @@ describe('DependenciesApp component with dependencyListVulnerabilities feature f
store,
sync: false,
propsData: { ...props },
provide: {
dependencyListVulnerabilities: true,
},
stubs,
});
};
......
......@@ -3,17 +3,10 @@ import { GlDropdownItem } from '@gitlab/ui';
import { TEST_HOST } from 'helpers/test_constants';
import createStore from 'ee/dependencies/store';
import { DEPENDENCY_LIST_TYPES } from 'ee/dependencies/store/constants';
import {
SORT_FIELDS,
SORT_FIELDS_WITH_SEVERITY,
} from 'ee/dependencies/store/modules/list/constants';
import { SORT_FIELDS } from 'ee/dependencies/store/modules/list/constants';
import DependenciesActions from 'ee/dependencies/components/dependencies_actions.vue';
describe.each`
context | isFeatureFlagEnabled | sortFields
${''} | ${false} | ${SORT_FIELDS}
${' with feature flag enabled'} | ${true} | ${SORT_FIELDS_WITH_SEVERITY}
`('DependenciesActions component$context', ({ isFeatureFlagEnabled, sortFields }) => {
describe('DependenciesActions component', () => {
let store;
let wrapper;
const { namespace } = DEPENDENCY_LIST_TYPES.all;
......@@ -36,7 +29,6 @@ describe.each`
beforeEach(() => {
factory({
propsData: { namespace },
provide: { dependencyListVulnerabilities: isFeatureFlagEnabled },
});
store.state[namespace].endpoint = `${TEST_HOST}/dependencies`;
return wrapper.vm.$nextTick();
......@@ -61,7 +53,7 @@ describe.each`
expect(store.dispatch.mock.calls).toEqual(
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';
import DependenciesTableRow from 'ee/dependencies/components/dependencies_table_row.vue';
import DependencyVulnerability from 'ee/dependencies/components/dependency_vulnerability.vue';
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';
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(() => {
factory({
propsData: {
isLoading: false,
dependency: makeDependency(),
dependency: makeDependency({ vulnerabilities: [] }),
},
});
});
......@@ -81,123 +81,78 @@ describe('DependenciesTableRow component', () => {
});
});
describe('given the dependencyListVulnerabilities flag is enabled', () => {
describe('when passed no props', () => {
beforeEach(() => {
factory(provideEnabledFeatureFlag());
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
describe('when a dependency with vulnerabilities is loaded', () => {
beforeEach(() => {
factory({
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: mockDataVulnerabilities }),
},
});
});
describe('when loading', () => {
beforeEach(() => {
factory({
...provideEnabledFeatureFlag(),
propsData: {
isLoading: true,
},
});
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
});
describe('when a dependency with no vulnerabilities is loaded', () => {
beforeEach(() => {
factory({
...provideEnabledFeatureFlag(),
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: [] }),
},
});
});
describe('when the list of vulnerabilities is expanded', () => {
beforeEach(clickToggle);
it('matches the snapshot', () => {
expect(wrapper.element).toMatchSnapshot();
it('renders each vulnerability', () => {
expectVulnerabilitiesExpanded(mockDataVulnerabilities);
});
});
describe('when a dependency with vulnerabilities is loaded', () => {
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', () => {
describe('when clicking the toggle ', () => {
beforeEach(clickToggle);
it('renders each vulnerability', () => {
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 }),
});
it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed);
});
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', () => {
beforeEach(() => {
wrapper.setProps({
isLoading: true,
});
it('closes the list of vulnerabilities', expectVulnerabilitiesCollapsed);
});
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', () => {
beforeEach(() => {
const hugeNumberOfVulnerabilities = Array(1 + MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY)
.fill(null)
.map((_, id) => ({ id }));
factory({
...provideEnabledFeatureFlag(),
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: hugeNumberOfVulnerabilities }),
},
});
describe('when a dependency with a huge number vulnerabilities is loaded and expanded', () => {
beforeEach(() => {
const hugeNumberOfVulnerabilities = Array(1 + MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY)
.fill(null)
.map((_, id) => ({ id }));
return clickToggle();
factory({
propsData: {
isLoading: false,
dependency: makeDependency({ vulnerabilities: hugeNumberOfVulnerabilities }),
},
});
it('does not render all of them', () => {
expect(findVulnerabilities().length).toBe(MAX_DISPLAYED_VULNERABILITIES_PER_DEPENDENCY);
expect(findExcessMessage().isVisible()).toBe(true);
});
return clickToggle();
});
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 DependenciesTable from 'ee/dependencies/components/dependencies_table.vue';
import DependenciesTableRow from 'ee/dependencies/components/dependencies_table_row.vue';
import { makeDependency, provideEnabledFeatureFlag } from './utils';
import { makeDependency } from './utils';
describe('DependenciesTable component', () => {
let wrapper;
......@@ -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 = {}) => ({
name: 'left-pad',
version: '0.0.3',
......@@ -9,7 +10,3 @@ export const makeDependency = (changes = {}) => ({
licenses: [],
...changes,
});
export const provideEnabledFeatureFlag = () => ({
provide: { dependencyListVulnerabilities: true },
});
......@@ -6,7 +6,6 @@ module QA
module Project::Secure
class DependencyList < QA::Page::Base
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
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