diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-01 12:09:43 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-01 12:09:43 +0300 |
commit | 5ffb2b7bcde1c76f939c5dca2ff65bac3404a88f (patch) | |
tree | cde2072e0ddb7f861014d0529c9e2f82040b3d5f /spec/frontend | |
parent | 7401c3a232003e3901010eccb4a31b7aa2741473 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
10 files changed, 152 insertions, 133 deletions
diff --git a/spec/frontend/organizations/groups_and_projects/components/app_spec.js b/spec/frontend/organizations/groups_and_projects/components/app_spec.js index f7dff4aca82..e2301de8607 100644 --- a/spec/frontend/organizations/groups_and_projects/components/app_spec.js +++ b/spec/frontend/organizations/groups_and_projects/components/app_spec.js @@ -1,7 +1,7 @@ import { GlCollapsibleListbox, GlSorting, GlSortingItem } from '@gitlab/ui'; import App from '~/organizations/groups_and_projects/components/app.vue'; -import GroupsPage from '~/organizations/groups_and_projects/components/groups_page.vue'; -import ProjectsPage from '~/organizations/groups_and_projects/components/projects_page.vue'; +import GroupsView from '~/organizations/shared/components/groups_view.vue'; +import ProjectsView from '~/organizations/shared/components/projects_view.vue'; import { RESOURCE_TYPE_GROUPS, RESOURCE_TYPE_PROJECTS } from '~/organizations/constants'; import { SORT_ITEM_CREATED, @@ -35,10 +35,10 @@ describe('GroupsAndProjectsApp', () => { describe.each` display | expectedComponent | expectedDisplayListboxSelectedProp - ${null} | ${GroupsPage} | ${RESOURCE_TYPE_GROUPS} - ${'unsupported_value'} | ${GroupsPage} | ${RESOURCE_TYPE_GROUPS} - ${RESOURCE_TYPE_GROUPS} | ${GroupsPage} | ${RESOURCE_TYPE_GROUPS} - ${RESOURCE_TYPE_PROJECTS} | ${ProjectsPage} | ${RESOURCE_TYPE_PROJECTS} + ${null} | ${GroupsView} | ${RESOURCE_TYPE_GROUPS} + ${'unsupported_value'} | ${GroupsView} | ${RESOURCE_TYPE_GROUPS} + ${RESOURCE_TYPE_GROUPS} | ${GroupsView} | ${RESOURCE_TYPE_GROUPS} + ${RESOURCE_TYPE_PROJECTS} | ${ProjectsView} | ${RESOURCE_TYPE_PROJECTS} `( 'when `display` query string is $display', ({ display, expectedComponent, expectedDisplayListboxSelectedProp }) => { diff --git a/spec/frontend/organizations/groups_and_projects/components/groups_page_spec.js b/spec/frontend/organizations/shared/components/groups_view_spec.js index 57f4911e5f3..2b47bba3530 100644 --- a/spec/frontend/organizations/groups_and_projects/components/groups_page_spec.js +++ b/spec/frontend/organizations/shared/components/groups_view_spec.js @@ -1,9 +1,9 @@ import VueApollo from 'vue-apollo'; import Vue from 'vue'; import { GlLoadingIcon } from '@gitlab/ui'; -import GroupsPage from '~/organizations/groups_and_projects/components/groups_page.vue'; -import { formatGroups } from '~/organizations/groups_and_projects/utils'; -import resolvers from '~/organizations/groups_and_projects/graphql/resolvers'; +import GroupsView from '~/organizations/shared/components/groups_view.vue'; +import { formatGroups } from '~/organizations/shared/utils'; +import resolvers from '~/organizations/shared/graphql/resolvers'; import GroupsList from '~/vue_shared/components/groups_list/groups_list.vue'; import { createAlert } from '~/alert'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -16,14 +16,14 @@ jest.mock('~/alert'); Vue.use(VueApollo); jest.useFakeTimers(); -describe('GroupsPage', () => { +describe('GroupsView', () => { let wrapper; let mockApollo; const createComponent = ({ mockResolvers = resolvers } = {}) => { mockApollo = createMockApollo([], mockResolvers); - wrapper = shallowMountExtended(GroupsPage, { apolloProvider: mockApollo }); + wrapper = shallowMountExtended(GroupsView, { apolloProvider: mockApollo }); }; afterEach(() => { @@ -79,7 +79,7 @@ describe('GroupsPage', () => { await waitForPromises(); expect(createAlert).toHaveBeenCalledWith({ - message: GroupsPage.i18n.errorMessage, + message: GroupsView.i18n.errorMessage, error, captureError: true, }); diff --git a/spec/frontend/organizations/groups_and_projects/components/projects_page_spec.js b/spec/frontend/organizations/shared/components/projects_view_spec.js index 2965de7cfc8..faa8fe2b24c 100644 --- a/spec/frontend/organizations/groups_and_projects/components/projects_page_spec.js +++ b/spec/frontend/organizations/shared/components/projects_view_spec.js @@ -1,9 +1,9 @@ import VueApollo from 'vue-apollo'; import Vue from 'vue'; import { GlLoadingIcon } from '@gitlab/ui'; -import ProjectsPage from '~/organizations/groups_and_projects/components/projects_page.vue'; -import { formatProjects } from '~/organizations/groups_and_projects/utils'; -import resolvers from '~/organizations/groups_and_projects/graphql/resolvers'; +import ProjectsView from '~/organizations/shared/components/projects_view.vue'; +import { formatProjects } from '~/organizations/shared/utils'; +import resolvers from '~/organizations/shared/graphql/resolvers'; import ProjectsList from '~/vue_shared/components/projects_list/projects_list.vue'; import { createAlert } from '~/alert'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; @@ -16,14 +16,14 @@ jest.mock('~/alert'); Vue.use(VueApollo); jest.useFakeTimers(); -describe('ProjectsPage', () => { +describe('ProjectsView', () => { let wrapper; let mockApollo; const createComponent = ({ mockResolvers = resolvers } = {}) => { mockApollo = createMockApollo([], mockResolvers); - wrapper = shallowMountExtended(ProjectsPage, { apolloProvider: mockApollo }); + wrapper = shallowMountExtended(ProjectsView, { apolloProvider: mockApollo }); }; afterEach(() => { @@ -79,7 +79,7 @@ describe('ProjectsPage', () => { await waitForPromises(); expect(createAlert).toHaveBeenCalledWith({ - message: ProjectsPage.i18n.errorMessage, + message: ProjectsView.i18n.errorMessage, error, captureError: true, }); diff --git a/spec/frontend/organizations/groups_and_projects/utils_spec.js b/spec/frontend/organizations/shared/utils_spec.js index 8b88e1ff64d..2912db739c3 100644 --- a/spec/frontend/organizations/groups_and_projects/utils_spec.js +++ b/spec/frontend/organizations/shared/utils_spec.js @@ -1,4 +1,4 @@ -import { formatProjects, formatGroups } from '~/organizations/groups_and_projects/utils'; +import { formatProjects, formatGroups } from '~/organizations/shared/utils'; import { ACTION_EDIT, ACTION_DELETE } from '~/vue_shared/components/list_actions/constants'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { organizationProjects, organizationGroups } from '~/organizations/mock_data'; diff --git a/spec/frontend/organizations/show/components/groups_and_projects_spec.js b/spec/frontend/organizations/show/components/groups_and_projects_spec.js index a6fac7d953f..cbf5cd5bdb4 100644 --- a/spec/frontend/organizations/show/components/groups_and_projects_spec.js +++ b/spec/frontend/organizations/show/components/groups_and_projects_spec.js @@ -2,6 +2,8 @@ import { GlCollapsibleListbox, GlLink } from '@gitlab/ui'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import GroupsAndProjects from '~/organizations/show/components/groups_and_projects.vue'; import { createRouter } from '~/organizations/show'; +import GroupsView from '~/organizations/shared/components/groups_view.vue'; +import ProjectsView from '~/organizations/shared/components/projects_view.vue'; describe('OrganizationShowGroupsAndProjects', () => { const router = createRouter(); @@ -43,22 +45,37 @@ describe('OrganizationShowGroupsAndProjects', () => { }); describe.each` - displayQueryParam | expectedHref - ${'frequently_visited_projects'} | ${`${defaultPropsData.groupsAndProjectsOrganizationPath}?display=projects`} - ${'frequently_visited_groups'} | ${`${defaultPropsData.groupsAndProjectsOrganizationPath}?display=groups`} - `('when display query param is $displayQueryParam', ({ displayQueryParam, expectedHref }) => { - beforeEach(() => { - createComponent({ routeQuery: { display: displayQueryParam } }); - }); + displayQueryParam | expectedViewAllLinkQuery | expectedViewComponent | expectedDisplayListboxSelectedProp + ${'frequently_visited_projects'} | ${'?display=projects'} | ${ProjectsView} | ${'frequently_visited_projects'} + ${'frequently_visited_groups'} | ${'?display=groups'} | ${GroupsView} | ${'frequently_visited_groups'} + ${'unsupported'} | ${'?display=projects'} | ${ProjectsView} | ${'frequently_visited_projects'} + `( + 'when display query param is $displayQueryParam', + ({ + displayQueryParam, + expectedViewAllLinkQuery, + expectedViewComponent, + expectedDisplayListboxSelectedProp, + }) => { + beforeEach(() => { + createComponent({ routeQuery: { display: displayQueryParam } }); + }); - it('sets listbox `selected` prop correctly', () => { - expect(findCollapsibleListbox().props('selected')).toBe(displayQueryParam); - }); + it('sets listbox `selected` prop correctly', () => { + expect(findCollapsibleListbox().props('selected')).toBe(expectedDisplayListboxSelectedProp); + }); - it('renders "View all" link with correct href', () => { - expect(wrapper.findComponent(GlLink).attributes('href')).toBe(expectedHref); - }); - }); + it('renders "View all" link with correct href', () => { + expect(wrapper.findComponent(GlLink).attributes('href')).toBe( + `${defaultPropsData.groupsAndProjectsOrganizationPath}${expectedViewAllLinkQuery}`, + ); + }); + + it('renders expected view', () => { + expect(wrapper.findComponent(expectedViewComponent).exists()).toBe(true); + }); + }, + ); it('renders label and associates listbox with it', () => { createComponent(); diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js index fad8863e3d9..acf8b718400 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js @@ -37,7 +37,6 @@ describe('packages_list', () => { const defaultProps = { list: [firstPackage, secondPackage], isLoading: false, - pageInfo: {}, groupSettings: defaultPackageGroupSettings, }; @@ -113,7 +112,6 @@ describe('packages_list', () => { expect(findRegistryList().props()).toMatchObject({ title: '2 packages', items: defaultProps.list, - pagination: defaultProps.pageInfo, hiddenDelete: false, isLoading: false, }); @@ -314,22 +312,4 @@ describe('packages_list', () => { expect(emptySlot.exists()).toBe(true); }); }); - - describe('pagination', () => { - beforeEach(() => { - mountComponent({ props: { pageInfo: { hasPreviousPage: true } } }); - }); - - it('emits prev-page events when the prev event is fired', () => { - findRegistryList().vm.$emit('prev-page'); - - expect(wrapper.emitted('prev-page')).toHaveLength(1); - }); - - it('emits next-page events when the next event is fired', () => { - findRegistryList().vm.$emit('next-page'); - - expect(wrapper.emitted('next-page')).toHaveLength(1); - }); - }); }); diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js index 82fa5b76367..f4e36f51c27 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_search_spec.js @@ -3,19 +3,12 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { sortableFields } from '~/packages_and_registries/package_registry/utils'; import component from '~/packages_and_registries/package_registry/components/list/package_search.vue'; import PackageTypeToken from '~/packages_and_registries/package_registry/components/list/tokens/package_type_token.vue'; -import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue'; -import UrlSync from '~/vue_shared/components/url_sync.vue'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; -import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; +import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue'; import { LIST_KEY_CREATED_AT } from '~/packages_and_registries/package_registry/constants'; -import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils'; import { TOKEN_TYPE_TYPE } from '~/vue_shared/components/filtered_search_bar/constants'; -jest.mock('~/packages_and_registries/shared/utils'); - -useMockLocationHelper(); - describe('Package Search', () => { let wrapper; @@ -24,8 +17,7 @@ describe('Package Search', () => { sorting: { sort: 'desc' }, }; - const findRegistrySearch = () => wrapper.findComponent(RegistrySearch); - const findUrlSync = () => wrapper.findComponent(UrlSync); + const findPersistedSearch = () => wrapper.findComponent(PersistedSearch); const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync); const mountComponent = (isGroupPage = false) => { @@ -36,34 +28,23 @@ describe('Package Search', () => { }; }, stubs: { - UrlSync, LocalStorageSync, }, }); }; - beforeEach(() => { - extractFilterAndSorting.mockReturnValue(defaultQueryParamsMock); - }); - it('has a registry search component', async () => { mountComponent(); await nextTick(); - expect(findRegistrySearch().exists()).toBe(true); + expect(findPersistedSearch().exists()).toBe(true); }); it('registry search is mounted after mount', () => { mountComponent(); - expect(findRegistrySearch().exists()).toBe(false); - }); - - it('has a UrlSync component', () => { - mountComponent(); - - expect(findUrlSync().exists()).toBe(true); + expect(findPersistedSearch().exists()).toBe(false); }); it('has a LocalStorageSync component', () => { @@ -87,7 +68,7 @@ describe('Package Search', () => { await nextTick(); - expect(findRegistrySearch().props()).toMatchObject({ + expect(findPersistedSearch().props()).toMatchObject({ tokens: expect.arrayContaining([ expect.objectContaining({ token: PackageTypeToken, @@ -99,85 +80,63 @@ describe('Package Search', () => { }); }); - it('on sorting:changed emits update event and update internal sort', async () => { - const payload = { sort: 'foo' }; + it('on update event re-emits update event and updates internal sort', async () => { + const payload = { + sort: 'CREATED_FOO', + filters: defaultQueryParamsMock.filters, + sorting: { sort: 'foo', orderBy: 'created_at' }, + }; mountComponent(); await nextTick(); - findRegistrySearch().vm.$emit('sorting:changed', payload); + findPersistedSearch().vm.$emit('update', payload); await nextTick(); - expect(findRegistrySearch().props('sorting')).toEqual({ sort: 'foo', orderBy: 'created_at' }); + expect(findLocalStorageSync().props('value')).toEqual({ sort: 'foo', orderBy: 'created_at' }); - // there is always a first call on mounted that emits up default values - expect(wrapper.emitted('update')[1]).toEqual([ + expect(wrapper.emitted('update')[0]).toEqual([ { filters: { packageName: '', packageType: undefined, }, - sort: 'CREATED_FOO', + sort: payload.sort, + sorting: payload.sorting, }, ]); }); - it('on filter:changed updates the filters', async () => { - const payload = ['foo']; + it('on update event, re-emits update event with formatted filters', async () => { + const payload = { + sort: 'CREATED_FOO', + filters: [ + { type: 'type', value: { data: 'Generic', operator: '=' }, id: 'token-3' }, + { id: 'token-4', type: 'filtered-search-term', value: { data: 'gl' } }, + { id: 'token-5', type: 'filtered-search-term', value: { data: '' } }, + ], + sorting: { sort: 'foo', orderBy: 'created_at' }, + }; mountComponent(); await nextTick(); - findRegistrySearch().vm.$emit('filter:changed', payload); + findPersistedSearch().vm.$emit('update', payload); await nextTick(); - expect(findRegistrySearch().props('filters')).toEqual(['foo']); - }); - - it('on filter:submit emits update event', async () => { - mountComponent(); - - await nextTick(); - - findRegistrySearch().vm.$emit('filter:submit'); - - expect(wrapper.emitted('update')[1]).toEqual([ + expect(wrapper.emitted('update')[0]).toEqual([ { filters: { - packageName: '', - packageType: undefined, + packageName: 'gl', + packageType: 'GENERIC', }, - sort: 'CREATED_DESC', + sort: payload.sort, + sorting: payload.sorting, }, ]); }); - - it('on query:changed calls updateQuery from UrlSync', async () => { - jest.spyOn(UrlSync.methods, 'updateQuery').mockImplementation(() => {}); - - mountComponent(); - - await nextTick(); - - findRegistrySearch().vm.$emit('query:changed'); - - expect(UrlSync.methods.updateQuery).toHaveBeenCalled(); - }); - - it('sets the component sorting and filtering based on the querystring', async () => { - mountComponent(); - - await nextTick(); - - expect(getQueryParams).toHaveBeenCalled(); - - expect(findRegistrySearch().props()).toMatchObject({ - filters: defaultQueryParamsMock.filters, - sorting: defaultQueryParamsMock.sorting, - }); - }); }); diff --git a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js index 0d262036ee7..0ce2b86b9a4 100644 --- a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js @@ -17,7 +17,7 @@ import { EMPTY_LIST_HELP_URL, PACKAGE_HELP_URL, } from '~/packages_and_registries/package_registry/constants'; - +import PersistedPagination from '~/packages_and_registries/shared/components/persisted_pagination.vue'; import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql'; import destroyPackagesMutation from '~/packages_and_registries/package_registry/graphql/mutations/destroy_packages.mutation.graphql'; import { packagesListQuery, packageData, pagination } from '../mock_data'; @@ -53,6 +53,7 @@ describe('PackagesListApp', () => { const findEmptyState = () => wrapper.findComponent(GlEmptyState); const findDeletePackages = () => wrapper.findComponent(DeletePackages); const findSettingsLink = () => wrapper.findComponent(GlButton); + const findPagination = () => wrapper.findComponent(PersistedPagination); const mountComponent = ({ resolver = jest.fn().mockResolvedValue(packagesListQuery()), @@ -99,6 +100,15 @@ describe('PackagesListApp', () => { expect(resolver).not.toHaveBeenCalled(); }); + it('has persisted pagination', async () => { + const resolver = jest.fn().mockResolvedValue(packagesListQuery()); + + mountComponent({ resolver }); + await waitForFirstRequest(); + + expect(findPagination().props('pagination')).toEqual(pagination()); + }); + it('has a package title', async () => { mountComponent(); @@ -194,7 +204,6 @@ describe('PackagesListApp', () => { expect(findListComponent().props()).toMatchObject({ list: expect.arrayContaining([expect.objectContaining({ id: packageData().id })]), isLoading: false, - pageInfo: expect.objectContaining({ endCursor: pagination().endCursor }), groupSettings: expect.objectContaining({ mavenPackageRequestsForwarding: true, npmPackageRequestsForwarding: true, @@ -203,9 +212,9 @@ describe('PackagesListApp', () => { }); }); - it('when list emits next-page fetches the next set of records', async () => { + it('when pagination emits next event fetches the next set of records', async () => { await waitForFirstRequest(); - findListComponent().vm.$emit('next-page'); + findPagination().vm.$emit('next'); await waitForPromises(); expect(resolver).toHaveBeenCalledWith( @@ -213,9 +222,9 @@ describe('PackagesListApp', () => { ); }); - it('when list emits prev-page fetches the prev set of records', async () => { + it('when pagination emits prev event fetches the prev set of records', async () => { await waitForFirstRequest(); - findListComponent().vm.$emit('prev-page'); + findPagination().vm.$emit('prev'); await waitForPromises(); expect(resolver).toHaveBeenCalledWith( diff --git a/spec/frontend/packages_and_registries/package_registry/utils_spec.js b/spec/frontend/packages_and_registries/package_registry/utils_spec.js index 019f94aaec2..ecb5a8a77f1 100644 --- a/spec/frontend/packages_and_registries/package_registry/utils_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/utils_spec.js @@ -1,4 +1,9 @@ -import { getPackageTypeLabel } from '~/packages_and_registries/package_registry/utils'; +import { + getPackageTypeLabel, + getNextPageParams, + getPreviousPageParams, + getPageParams, +} from '~/packages_and_registries/package_registry/utils'; describe('Packages shared utils', () => { describe('getPackageTypeLabel', () => { @@ -21,3 +26,48 @@ describe('Packages shared utils', () => { }); }); }); + +describe('getNextPageParams', () => { + it('should return the next page params with the provided cursor', () => { + const cursor = 'abc123'; + expect(getNextPageParams(cursor)).toEqual({ + after: cursor, + first: 20, + }); + }); +}); + +describe('getPreviousPageParams', () => { + it('should return the previous page params with the provided cursor', () => { + const cursor = 'abc123'; + expect(getPreviousPageParams(cursor)).toEqual({ + first: null, + before: cursor, + last: 20, + }); + }); +}); + +describe('getPageParams', () => { + it('should return the previous page params if before cursor is available', () => { + const pageInfo = { before: 'abc123' }; + expect(getPageParams(pageInfo)).toEqual({ + first: null, + before: pageInfo.before, + last: 20, + }); + }); + + it('should return the next page params if after cursor is available', () => { + const pageInfo = { after: 'abc123' }; + expect(getPageParams(pageInfo)).toEqual({ + after: pageInfo.after, + first: 20, + }); + }); + + it('should return an empty object if both before and after cursors are not available', () => { + const pageInfo = {}; + expect(getPageParams(pageInfo)).toEqual({}); + }); +}); diff --git a/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js b/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js index 296caf091d5..615fba2e282 100644 --- a/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js +++ b/spec/frontend/packages_and_registries/shared/components/persisted_search_spec.js @@ -86,6 +86,7 @@ describe('Persisted Search', () => { after: '123', before: null, }, + sorting: defaultQueryParamsMock.sorting, }, ]); }); @@ -109,6 +110,7 @@ describe('Persisted Search', () => { { filters: [], sort: 'TEST_DESC', + sorting: defaultQueryParamsMock.sorting, pageInfo: { before: '456', after: null, @@ -136,6 +138,7 @@ describe('Persisted Search', () => { filters: ['foo'], sort: 'TEST_DESC', pageInfo: {}, + sorting: payload, }, ]); }); @@ -169,6 +172,7 @@ describe('Persisted Search', () => { after: '123', before: null, }, + sorting: defaultQueryParamsMock.sorting, }, ]); }); |