summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-06-04 00:10:03 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-06-04 00:10:03 +0000
commitc9ebdf468d0ffc669b2ac9c388730d6c3f2741a2 (patch)
treefa63d665aae06ac1a9bbeffb1426b5173baabe4e /spec
parent8e2f50b44d51768c38d300a2ba2f9208107933b2 (diff)
downloadgitlab-ce-c9ebdf468d0ffc669b2ac9c388730d6c3f2741a2.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb22
-rw-r--r--spec/frontend/notes/components/comment_form_spec.js41
-rw-r--r--spec/frontend/releases/components/app_index_apollo_client_spec.js41
-rw-r--r--spec/frontend/releases/components/releases_sort_apollo_client_spec.js103
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');
+ });
+ });
+});