summaryrefslogtreecommitdiff
path: root/spec/frontend/packages/list/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/packages/list/components')
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap14
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap457
-rw-r--r--spec/frontend/packages/list/components/packages_filter_spec.js50
-rw-r--r--spec/frontend/packages/list/components/packages_list_app_spec.js148
-rw-r--r--spec/frontend/packages/list/components/packages_list_spec.js219
-rw-r--r--spec/frontend/packages/list/components/packages_sort_spec.js92
6 files changed, 980 insertions, 0 deletions
diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap
new file mode 100644
index 00000000000..ed77f25916f
--- /dev/null
+++ b/spec/frontend/packages/list/components/__snapshots__/packages_filter_spec.js.snap
@@ -0,0 +1,14 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`packages_filter renders 1`] = `
+<gl-search-box-by-click-stub
+ clearable="true"
+ clearbuttontitle="Clear"
+ clearrecentsearchestext="Clear recent searches"
+ closebuttontitle="Close"
+ norecentsearchestext="You don't have any recent searches"
+ placeholder="Filter by name"
+ recentsearchesheader="Recent searches"
+ value=""
+/>
+`;
diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
new file mode 100644
index 00000000000..2b7a4c83bed
--- /dev/null
+++ b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
@@ -0,0 +1,457 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`packages_list_app renders 1`] = `
+<b-tabs-stub
+ activenavitemclass="gl-tab-nav-item-active gl-tab-nav-item-active-indigo"
+ class="gl-tabs"
+ contentclass=",gl-tab-content"
+ navclass="gl-tabs-nav"
+ nofade="true"
+ nonavstyle="true"
+ tag="div"
+>
+ <template>
+
+ <b-tab-stub
+ tag="div"
+ title="All"
+ titlelinkclass="gl-tab-nav-item"
+ >
+ <template>
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt="There are no packages yet"
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div>
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+ </template>
+ </b-tab-stub>
+ <b-tab-stub
+ tag="div"
+ title="Composer"
+ titlelinkclass="gl-tab-nav-item"
+ >
+ <template>
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt="There are no Composer packages yet"
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no Composer packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div>
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+ </template>
+ </b-tab-stub>
+ <b-tab-stub
+ tag="div"
+ title="Conan"
+ titlelinkclass="gl-tab-nav-item"
+ >
+ <template>
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt="There are no Conan packages yet"
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no Conan packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div>
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+ </template>
+ </b-tab-stub>
+ <b-tab-stub
+ tag="div"
+ title="Maven"
+ titlelinkclass="gl-tab-nav-item"
+ >
+ <template>
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt="There are no Maven packages yet"
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no Maven packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div>
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+ </template>
+ </b-tab-stub>
+ <b-tab-stub
+ tag="div"
+ title="NPM"
+ titlelinkclass="gl-tab-nav-item"
+ >
+ <template>
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt="There are no NPM packages yet"
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no NPM packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div>
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+ </template>
+ </b-tab-stub>
+ <b-tab-stub
+ tag="div"
+ title="NuGet"
+ titlelinkclass="gl-tab-nav-item"
+ >
+ <template>
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt="There are no NuGet packages yet"
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no NuGet packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div>
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+ </template>
+ </b-tab-stub>
+ <b-tab-stub
+ tag="div"
+ title="PyPi"
+ titlelinkclass="gl-tab-nav-item"
+ >
+ <template>
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt="There are no PyPi packages yet"
+ class="gl-max-w-full"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="h4"
+ >
+ There are no PyPi packages yet
+ </h1>
+
+ <p>
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div>
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+ </template>
+ </b-tab-stub>
+
+ <!---->
+ </template>
+ <template>
+ <div
+ class="d-flex align-self-center ml-md-auto py-1 py-md-0"
+ >
+ <package-filter-stub
+ class="mr-1"
+ />
+
+ <package-sort-stub />
+ </div>
+ </template>
+</b-tabs-stub>
+`;
diff --git a/spec/frontend/packages/list/components/packages_filter_spec.js b/spec/frontend/packages/list/components/packages_filter_spec.js
new file mode 100644
index 00000000000..b186b5f5e48
--- /dev/null
+++ b/spec/frontend/packages/list/components/packages_filter_spec.js
@@ -0,0 +1,50 @@
+import Vuex from 'vuex';
+import { GlSearchBoxByClick } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import PackagesFilter from '~/packages/list/components/packages_filter.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('packages_filter', () => {
+ let wrapper;
+ let store;
+
+ const findGlSearchBox = () => wrapper.find(GlSearchBoxByClick);
+
+ const mountComponent = () => {
+ store = new Vuex.Store();
+ store.dispatch = jest.fn();
+
+ wrapper = shallowMount(PackagesFilter, {
+ localVue,
+ store,
+ });
+ };
+
+ beforeEach(mountComponent);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders', () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ describe('emits events', () => {
+ it('sets the filter value in the store on input', () => {
+ const searchString = 'foo';
+ findGlSearchBox().vm.$emit('input', searchString);
+
+ expect(store.dispatch).toHaveBeenCalledWith('setFilter', searchString);
+ });
+
+ it('emits the filter event when search box is submitted', () => {
+ findGlSearchBox().vm.$emit('submit');
+
+ expect(wrapper.emitted('filter')).toBeTruthy();
+ });
+ });
+});
diff --git a/spec/frontend/packages/list/components/packages_list_app_spec.js b/spec/frontend/packages/list/components/packages_list_app_spec.js
new file mode 100644
index 00000000000..31bab3886c1
--- /dev/null
+++ b/spec/frontend/packages/list/components/packages_list_app_spec.js
@@ -0,0 +1,148 @@
+import Vuex from 'vuex';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlEmptyState, GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
+import PackageListApp from '~/packages/list/components/packages_list_app.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('packages_list_app', () => {
+ let wrapper;
+ let store;
+
+ const PackageList = {
+ name: 'package-list',
+ template: '<div><slot name="empty-state"></slot></div>',
+ };
+ const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
+
+ const emptyListHelpUrl = 'helpUrl';
+ const findEmptyState = () => wrapper.find(GlEmptyState);
+ const findListComponent = () => wrapper.find(PackageList);
+ const findTabComponent = (index = 0) => wrapper.findAll(GlTab).at(index);
+
+ const createStore = (filterQuery = '') => {
+ store = new Vuex.Store({
+ state: {
+ isLoading: false,
+ config: {
+ resourceId: 'project_id',
+ emptyListIllustration: 'helpSvg',
+ emptyListHelpUrl,
+ },
+ filterQuery,
+ },
+ });
+ store.dispatch = jest.fn();
+ };
+
+ const mountComponent = () => {
+ wrapper = shallowMount(PackageListApp, {
+ localVue,
+ store,
+ stubs: {
+ GlEmptyState,
+ GlLoadingIcon,
+ PackageList,
+ GlTab,
+ GlTabs,
+ GlSprintf,
+ GlLink,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createStore();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders', () => {
+ mountComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ describe('empty state', () => {
+ it('generate the correct empty list link', () => {
+ mountComponent();
+
+ const link = findListComponent().find(GlLink);
+
+ expect(link.attributes('href')).toBe(emptyListHelpUrl);
+ expect(link.text()).toBe('publish and share your packages');
+ });
+
+ it('includes the right content on the default tab', () => {
+ mountComponent();
+
+ const heading = findEmptyState().find('h1');
+
+ expect(heading.text()).toBe('There are no packages yet');
+ });
+ });
+
+ it('call requestPackagesList on page:changed', () => {
+ mountComponent();
+
+ const list = findListComponent();
+ list.vm.$emit('page:changed', 1);
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList', { page: 1 });
+ });
+
+ it('call requestDeletePackage on package:delete', () => {
+ mountComponent();
+
+ const list = findListComponent();
+ list.vm.$emit('package:delete', 'foo');
+ expect(store.dispatch).toHaveBeenCalledWith('requestDeletePackage', 'foo');
+ });
+
+ it('calls requestPackagesList on sort:changed', () => {
+ mountComponent();
+
+ const list = findListComponent();
+ list.vm.$emit('sort:changed');
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
+ });
+
+ it('does not call requestPackagesList two times on render', () => {
+ mountComponent();
+
+ expect(store.dispatch).toHaveBeenCalledTimes(1);
+ });
+
+ describe('tab change', () => {
+ it('calls requestPackagesList when all tab is clicked', () => {
+ mountComponent();
+
+ findTabComponent().trigger('click');
+
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
+ });
+
+ it('calls requestPackagesList when a package type tab is clicked', () => {
+ mountComponent();
+
+ findTabComponent(1).trigger('click');
+
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
+ });
+ });
+
+ describe('filter without results', () => {
+ beforeEach(() => {
+ createStore('foo');
+ mountComponent();
+ });
+
+ it('should show specific empty message', () => {
+ expect(findEmptyState().text()).toContain('Sorry, your filter produced no results');
+ expect(findEmptyState().text()).toContain(
+ 'To widen your search, change or remove the filters above',
+ );
+ });
+ });
+});
diff --git a/spec/frontend/packages/list/components/packages_list_spec.js b/spec/frontend/packages/list/components/packages_list_spec.js
new file mode 100644
index 00000000000..a90d5056212
--- /dev/null
+++ b/spec/frontend/packages/list/components/packages_list_spec.js
@@ -0,0 +1,219 @@
+import Vuex from 'vuex';
+import { last } from 'lodash';
+import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import stubChildren from 'helpers/stub_children';
+import Tracking from '~/tracking';
+import PackagesList from '~/packages/list/components/packages_list.vue';
+import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
+import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
+import * as SharedUtils from '~/packages/shared/utils';
+import { TrackingActions } from '~/packages/shared/constants';
+import { packageList } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('packages_list', () => {
+ let wrapper;
+ let store;
+
+ const GlSortingItem = { name: 'sorting-item-stub', template: '<div><slot></slot></div>' };
+ const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>bar</div>' };
+
+ const findPackagesListLoader = () => wrapper.find(PackagesListLoader);
+ const findPackageListPagination = () => wrapper.find(GlPagination);
+ const findPackageListDeleteModal = () => wrapper.find(GlModal);
+ const findEmptySlot = () => wrapper.find({ name: 'empty-slot-stub' });
+ const findPackagesListRow = () => wrapper.find(PackagesListRow);
+
+ const createStore = (isGroupPage, packages, isLoading) => {
+ const state = {
+ isLoading,
+ packages,
+ pagination: {
+ perPage: 1,
+ total: 1,
+ page: 1,
+ },
+ config: {
+ isGroupPage,
+ },
+ sorting: {
+ orderBy: 'version',
+ sort: 'desc',
+ },
+ };
+ store = new Vuex.Store({
+ state,
+ getters: {
+ getList: () => packages,
+ },
+ });
+ store.dispatch = jest.fn();
+ };
+
+ const mountComponent = ({
+ isGroupPage = false,
+ packages = packageList,
+ isLoading = false,
+ ...options
+ } = {}) => {
+ createStore(isGroupPage, packages, isLoading);
+
+ wrapper = mount(PackagesList, {
+ localVue,
+ store,
+ stubs: {
+ ...stubChildren(PackagesList),
+ GlTable,
+ GlSortingItem,
+ GlModal,
+ },
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when is loading', () => {
+ beforeEach(() => {
+ mountComponent({
+ packages: [],
+ isLoading: true,
+ });
+ });
+
+ it('shows skeleton loader when loading', () => {
+ expect(findPackagesListLoader().exists()).toBe(true);
+ });
+ });
+
+ describe('when is not loading', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('does not show skeleton loader when not loading', () => {
+ expect(findPackagesListLoader().exists()).toBe(false);
+ });
+ });
+
+ describe('layout', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('contains a pagination component', () => {
+ const sorting = findPackageListPagination();
+ expect(sorting.exists()).toBe(true);
+ });
+
+ it('contains a modal component', () => {
+ const sorting = findPackageListDeleteModal();
+ expect(sorting.exists()).toBe(true);
+ });
+ });
+
+ describe('when the user can destroy the package', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('setItemToBeDeleted sets itemToBeDeleted and open the modal', () => {
+ const mockModalShow = jest.spyOn(wrapper.vm.$refs.packageListDeleteModal, 'show');
+ const item = last(wrapper.vm.list);
+
+ findPackagesListRow().vm.$emit('packageToDelete', item);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.itemToBeDeleted).toEqual(item);
+ expect(mockModalShow).toHaveBeenCalled();
+ });
+ });
+
+ it('deleteItemConfirmation resets itemToBeDeleted', () => {
+ wrapper.setData({ itemToBeDeleted: 1 });
+ wrapper.vm.deleteItemConfirmation();
+ expect(wrapper.vm.itemToBeDeleted).toEqual(null);
+ });
+
+ it('deleteItemConfirmation emit package:delete', () => {
+ const itemToBeDeleted = { id: 2 };
+ wrapper.setData({ itemToBeDeleted });
+ wrapper.vm.deleteItemConfirmation();
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]);
+ });
+ });
+
+ it('deleteItemCanceled resets itemToBeDeleted', () => {
+ wrapper.setData({ itemToBeDeleted: 1 });
+ wrapper.vm.deleteItemCanceled();
+ expect(wrapper.vm.itemToBeDeleted).toEqual(null);
+ });
+ });
+
+ describe('when the list is empty', () => {
+ beforeEach(() => {
+ mountComponent({
+ packages: [],
+ slots: {
+ 'empty-state': EmptySlotStub,
+ },
+ });
+ });
+
+ it('show the empty slot', () => {
+ const emptySlot = findEmptySlot();
+ expect(emptySlot.exists()).toBe(true);
+ });
+ });
+
+ describe('pagination component', () => {
+ let pagination;
+ let modelEvent;
+
+ beforeEach(() => {
+ mountComponent();
+ pagination = findPackageListPagination();
+ // retrieve the event used by v-model, a more sturdy approach than hardcoding it
+ modelEvent = pagination.vm.$options.model.event;
+ });
+
+ it('emits page:changed events when the page changes', () => {
+ pagination.vm.$emit(modelEvent, 2);
+ expect(wrapper.emitted('page:changed')).toEqual([[2]]);
+ });
+ });
+
+ describe('tracking', () => {
+ let eventSpy;
+ let utilSpy;
+ const category = 'foo';
+
+ beforeEach(() => {
+ mountComponent();
+ eventSpy = jest.spyOn(Tracking, 'event');
+ utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
+ wrapper.setData({ itemToBeDeleted: { package_type: 'conan' } });
+ });
+
+ it('tracking category calls packageTypeToTrackCategory', () => {
+ expect(wrapper.vm.tracking.category).toBe(category);
+ expect(utilSpy).toHaveBeenCalledWith('conan');
+ });
+
+ it('deleteItemConfirmation calls event', () => {
+ wrapper.vm.deleteItemConfirmation();
+ expect(eventSpy).toHaveBeenCalledWith(
+ category,
+ TrackingActions.DELETE_PACKAGE,
+ expect.any(Object),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/packages/list/components/packages_sort_spec.js b/spec/frontend/packages/list/components/packages_sort_spec.js
new file mode 100644
index 00000000000..ff3e8e19413
--- /dev/null
+++ b/spec/frontend/packages/list/components/packages_sort_spec.js
@@ -0,0 +1,92 @@
+import Vuex from 'vuex';
+import { GlSorting } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import stubChildren from 'helpers/stub_children';
+import PackagesSort from '~/packages/list/components/packages_sort.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('packages_sort', () => {
+ let wrapper;
+ let store;
+ let sorting;
+ let sortingItems;
+
+ const GlSortingItem = { name: 'sorting-item-stub', template: '<div><slot></slot></div>' };
+
+ const findPackageListSorting = () => wrapper.find(GlSorting);
+ const findSortingItems = () => wrapper.findAll(GlSortingItem);
+
+ const createStore = isGroupPage => {
+ const state = {
+ config: {
+ isGroupPage,
+ },
+ sorting: {
+ orderBy: 'version',
+ sort: 'desc',
+ },
+ };
+ store = new Vuex.Store({
+ state,
+ });
+ store.dispatch = jest.fn();
+ };
+
+ const mountComponent = (isGroupPage = false) => {
+ createStore(isGroupPage);
+
+ wrapper = mount(PackagesSort, {
+ localVue,
+ store,
+ stubs: {
+ ...stubChildren(PackagesSort),
+ GlSortingItem,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when is in projects', () => {
+ beforeEach(() => {
+ mountComponent();
+ sorting = findPackageListSorting();
+ sortingItems = findSortingItems();
+ });
+
+ it('has all the sortable items', () => {
+ expect(sortingItems).toHaveLength(wrapper.vm.sortableFields.length);
+ });
+
+ it('on sort change set sorting in vuex and emit event', () => {
+ sorting.vm.$emit('sortDirectionChange');
+ expect(store.dispatch).toHaveBeenCalledWith('setSorting', { sort: 'asc' });
+ expect(wrapper.emitted('sort:changed')).toBeTruthy();
+ });
+
+ it('on sort item click set sorting and emit event', () => {
+ const item = sortingItems.at(0);
+ const { orderBy } = wrapper.vm.sortableFields[0];
+ item.vm.$emit('click');
+ expect(store.dispatch).toHaveBeenCalledWith('setSorting', { orderBy });
+ expect(wrapper.emitted('sort:changed')).toBeTruthy();
+ });
+ });
+
+ describe('when is in group', () => {
+ beforeEach(() => {
+ mountComponent(true);
+ sorting = findPackageListSorting();
+ sortingItems = findSortingItems();
+ });
+
+ it('has all the sortable items', () => {
+ expect(sortingItems).toHaveLength(wrapper.vm.sortableFields.length);
+ });
+ });
+});