diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-04 00:10:03 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-06-04 00:10:03 +0000 |
commit | c9ebdf468d0ffc669b2ac9c388730d6c3f2741a2 (patch) | |
tree | fa63d665aae06ac1a9bbeffb1426b5173baabe4e /spec | |
parent | 8e2f50b44d51768c38d300a2ba2f9208107933b2 (diff) | |
download | gitlab-ce-c9ebdf468d0ffc669b2ac9c388730d6c3f2741a2.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
4 files changed, 196 insertions, 11 deletions
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 3598aa2f423..595304789a6 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -172,7 +172,7 @@ RSpec.describe 'File blob', :js do end end - context 'sucessfully change ref of similar name' do + context 'successfully change ref of similar name' do before do project.repository.create_branch('dev') project.repository.create_branch('development') @@ -182,14 +182,32 @@ RSpec.describe 'File blob', :js do visit_blob('files/js/application.js', ref: 'development') switch_ref_to('dev') - expect(page.find('.file-title-name').text).to eq('application.js') + aggregate_failures do + expect(page.find('.file-title-name').text).to eq('application.js') + expect(page).not_to have_css('flash-container') + end end it 'switch ref from shorter to longer ref name' do visit_blob('files/js/application.js', ref: 'dev') switch_ref_to('development') + aggregate_failures do + expect(page.find('.file-title-name').text).to eq('application.js') + expect(page).not_to have_css('flash-container') + end + end + end + + it 'successfully changes ref when the ref name matches the project name' do + project.repository.create_branch(project.name) + + visit_blob('files/js/application.js', ref: project.name) + switch_ref_to('master') + + aggregate_failures do expect(page.find('.file-title-name').text).to eq('application.js') + expect(page).not_to have_css('flash-container') end end end diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js index b140eea9439..537622b7918 100644 --- a/spec/frontend/notes/components/comment_form_spec.js +++ b/spec/frontend/notes/components/comment_form_spec.js @@ -328,20 +328,45 @@ describe('issue_comment_form component', () => { mountComponent({ mountFunction: mount }); }); - it('should save note when cmd+enter is pressed', () => { - jest.spyOn(wrapper.vm, 'handleSave'); + describe('when no draft exists', () => { + it('should save note when cmd+enter is pressed', () => { + jest.spyOn(wrapper.vm, 'handleSave'); - findTextArea().trigger('keydown.enter', { metaKey: true }); + findTextArea().trigger('keydown.enter', { metaKey: true }); - expect(wrapper.vm.handleSave).toHaveBeenCalled(); + expect(wrapper.vm.handleSave).toHaveBeenCalledWith(); + }); + + it('should save note when ctrl+enter is pressed', () => { + jest.spyOn(wrapper.vm, 'handleSave'); + + findTextArea().trigger('keydown.enter', { ctrlKey: true }); + + expect(wrapper.vm.handleSave).toHaveBeenCalledWith(); + }); }); - it('should save note when ctrl+enter is pressed', () => { - jest.spyOn(wrapper.vm, 'handleSave'); + describe('when a draft exists', () => { + beforeEach(() => { + store.registerModule('batchComments', batchComments()); + store.state.batchComments.drafts = [{ note: 'A' }]; + }); + + it('should save note draft when cmd+enter is pressed', () => { + jest.spyOn(wrapper.vm, 'handleSaveDraft'); + + findTextArea().trigger('keydown.enter', { metaKey: true }); + + expect(wrapper.vm.handleSaveDraft).toHaveBeenCalledWith(); + }); + + it('should save note draft when ctrl+enter is pressed', () => { + jest.spyOn(wrapper.vm, 'handleSaveDraft'); - findTextArea().trigger('keydown.enter', { ctrlKey: true }); + findTextArea().trigger('keydown.enter', { ctrlKey: true }); - expect(wrapper.vm.handleSave).toHaveBeenCalled(); + expect(wrapper.vm.handleSaveDraft).toHaveBeenCalledWith(); + }); }); }); }); diff --git a/spec/frontend/releases/components/app_index_apollo_client_spec.js b/spec/frontend/releases/components/app_index_apollo_client_spec.js index 32ebeacbdff..84bcea36406 100644 --- a/spec/frontend/releases/components/app_index_apollo_client_spec.js +++ b/spec/frontend/releases/components/app_index_apollo_client_spec.js @@ -9,7 +9,8 @@ import ReleaseBlock from '~/releases/components/release_block.vue'; import ReleaseSkeletonLoader from '~/releases/components/release_skeleton_loader.vue'; import ReleasesEmptyState from '~/releases/components/releases_empty_state.vue'; import ReleasesPaginationApolloClient from '~/releases/components/releases_pagination_apollo_client.vue'; -import { PAGE_SIZE } from '~/releases/constants'; +import ReleasesSortApolloClient from '~/releases/components/releases_sort_apollo_client.vue'; +import { PAGE_SIZE, RELEASED_AT_DESC, CREATED_ASC } from '~/releases/constants'; import allReleasesQuery from '~/releases/graphql/queries/all_releases.query.graphql'; Vue.use(VueApollo); @@ -68,6 +69,7 @@ describe('app_index_apollo_client.vue', () => { wrapper.findByText(ReleasesIndexApolloClientApp.i18n.newRelease); const findAllReleaseBlocks = () => wrapper.findAllComponents(ReleaseBlock); const findPagination = () => wrapper.findComponent(ReleasesPaginationApolloClient); + const findSort = () => wrapper.findComponent(ReleasesSortApolloClient); // Expectations const expectLoadingIndicator = () => { @@ -135,6 +137,12 @@ describe('app_index_apollo_client.vue', () => { }); }; + const expectSort = () => { + it('renders the sort controls', () => { + expect(findSort().exists()).toBe(true); + }); + }; + // Tests describe('when the component is loading data', () => { beforeEach(() => { @@ -147,6 +155,7 @@ describe('app_index_apollo_client.vue', () => { expectNewReleaseButton(); expectReleases(0); expectNoPagination(); + expectSort(); }); describe('when the data has successfully loaded, but there are no releases', () => { @@ -161,6 +170,7 @@ describe('app_index_apollo_client.vue', () => { expectNewReleaseButton(); expectReleases(0); expectNoPagination(); + expectSort(); }); describe('when an error occurs while loading data', () => { @@ -174,6 +184,7 @@ describe('app_index_apollo_client.vue', () => { expectNewReleaseButton(); expectReleases(0); expectNoPagination(); + expectSort(); }); describe('when the data has successfully loaded with a single page of results', () => { @@ -201,6 +212,7 @@ describe('app_index_apollo_client.vue', () => { expectNewReleaseButton(); expectReleases(originalAllReleasesQueryResponse.data.project.releases.nodes.length); expectPagination(); + expectSort(); }); describe('URL parameters', () => { @@ -213,6 +225,7 @@ describe('app_index_apollo_client.vue', () => { expect(allReleasesQueryMock).toHaveBeenCalledWith({ first: PAGE_SIZE, fullPath: projectPath, + sort: RELEASED_AT_DESC, }); }); }); @@ -228,6 +241,7 @@ describe('app_index_apollo_client.vue', () => { before, last: PAGE_SIZE, fullPath: projectPath, + sort: RELEASED_AT_DESC, }); }); }); @@ -243,6 +257,7 @@ describe('app_index_apollo_client.vue', () => { after, first: PAGE_SIZE, fullPath: projectPath, + sort: RELEASED_AT_DESC, }); }); }); @@ -258,6 +273,7 @@ describe('app_index_apollo_client.vue', () => { after, first: PAGE_SIZE, fullPath: projectPath, + sort: RELEASED_AT_DESC, }); }); }); @@ -298,4 +314,27 @@ describe('app_index_apollo_client.vue', () => { ]); }); }); + + describe('sorting', () => { + beforeEach(() => { + createComponent(); + }); + + it(`sorts by ${RELEASED_AT_DESC} by default`, () => { + expect(allReleasesQueryMock.mock.calls).toEqual([ + [expect.objectContaining({ sort: RELEASED_AT_DESC })], + ]); + }); + + it('requeries the GraphQL endpoint when the sort is changed', async () => { + findSort().vm.$emit('input', CREATED_ASC); + + await wrapper.vm.$nextTick(); + + expect(allReleasesQueryMock.mock.calls).toEqual([ + [expect.objectContaining({ sort: RELEASED_AT_DESC })], + [expect.objectContaining({ sort: CREATED_ASC })], + ]); + }); + }); }); diff --git a/spec/frontend/releases/components/releases_sort_apollo_client_spec.js b/spec/frontend/releases/components/releases_sort_apollo_client_spec.js new file mode 100644 index 00000000000..d93a932af01 --- /dev/null +++ b/spec/frontend/releases/components/releases_sort_apollo_client_spec.js @@ -0,0 +1,103 @@ +import { GlSorting, GlSortingItem } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import ReleasesSortApolloClient from '~/releases/components/releases_sort_apollo_client.vue'; +import { RELEASED_AT_ASC, RELEASED_AT_DESC, CREATED_ASC, CREATED_DESC } from '~/releases/constants'; + +describe('releases_sort_apollo_client.vue', () => { + let wrapper; + + const createComponent = (valueProp = RELEASED_AT_ASC) => { + wrapper = shallowMountExtended(ReleasesSortApolloClient, { + propsData: { + value: valueProp, + }, + stubs: { + GlSortingItem, + }, + }); + }; + + afterEach(() => { + wrapper.destroy(); + }); + + const findSorting = () => wrapper.findComponent(GlSorting); + const findSortingItems = () => wrapper.findAllComponents(GlSortingItem); + const findReleasedDateItem = () => + findSortingItems().wrappers.find((item) => item.text() === 'Released date'); + const findCreatedDateItem = () => + findSortingItems().wrappers.find((item) => item.text() === 'Created date'); + const getSortingItemsInfo = () => + findSortingItems().wrappers.map((item) => ({ + label: item.text(), + active: item.attributes().active === 'true', + })); + + describe.each` + valueProp | text | isAscending | items + ${RELEASED_AT_ASC} | ${'Released date'} | ${true} | ${[{ label: 'Released date', active: true }, { label: 'Created date', active: false }]} + ${RELEASED_AT_DESC} | ${'Released date'} | ${false} | ${[{ label: 'Released date', active: true }, { label: 'Created date', active: false }]} + ${CREATED_ASC} | ${'Created date'} | ${true} | ${[{ label: 'Released date', active: false }, { label: 'Created date', active: true }]} + ${CREATED_DESC} | ${'Created date'} | ${false} | ${[{ label: 'Released date', active: false }, { label: 'Created date', active: true }]} + `('component states', ({ valueProp, text, isAscending, items }) => { + beforeEach(() => { + createComponent(valueProp); + }); + + it(`when the sort is ${valueProp}, provides the GlSorting with the props text="${text}" and isAscending=${isAscending}`, () => { + expect(findSorting().props()).toEqual( + expect.objectContaining({ + text, + isAscending, + }), + ); + }); + + it(`when the sort is ${valueProp}, renders the expected dropdown items`, () => { + expect(getSortingItemsInfo()).toEqual(items); + }); + }); + + const clickReleasedDateItem = () => findReleasedDateItem().vm.$emit('click'); + const clickCreatedDateItem = () => findCreatedDateItem().vm.$emit('click'); + const clickSortDirectionButton = () => findSorting().vm.$emit('sortDirectionChange'); + + const releasedAtDropdownItemDescription = 'released at dropdown item'; + const createdAtDropdownItemDescription = 'created at dropdown item'; + const sortDirectionButtonDescription = 'sort direction button'; + + describe.each` + initialValueProp | itemClickFn | itemToClickDescription | emittedEvent + ${RELEASED_AT_ASC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${undefined} + ${RELEASED_AT_ASC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${CREATED_ASC} + ${RELEASED_AT_ASC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${RELEASED_AT_DESC} + ${RELEASED_AT_DESC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${undefined} + ${RELEASED_AT_DESC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${CREATED_DESC} + ${RELEASED_AT_DESC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${RELEASED_AT_ASC} + ${CREATED_ASC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${RELEASED_AT_ASC} + ${CREATED_ASC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${undefined} + ${CREATED_ASC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${CREATED_DESC} + ${CREATED_DESC} | ${clickReleasedDateItem} | ${releasedAtDropdownItemDescription} | ${RELEASED_AT_DESC} + ${CREATED_DESC} | ${clickCreatedDateItem} | ${createdAtDropdownItemDescription} | ${undefined} + ${CREATED_DESC} | ${clickSortDirectionButton} | ${sortDirectionButtonDescription} | ${CREATED_ASC} + `('input event', ({ initialValueProp, itemClickFn, itemToClickDescription, emittedEvent }) => { + beforeEach(() => { + createComponent(initialValueProp); + itemClickFn(); + }); + + it(`emits ${ + emittedEvent || 'nothing' + } when value prop is ${initialValueProp} and the ${itemToClickDescription} is clicked`, () => { + expect(wrapper.emitted().input?.[0]?.[0]).toEqual(emittedEvent); + }); + }); + + describe('prop validation', () => { + it('validates that the `value` prop is one of the expected sort strings', () => { + expect(() => { + createComponent('not a valid value'); + }).toThrow('Invalid prop: custom validator check failed'); + }); + }); +}); |