diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/frontend/lib/utils/common_utils_spec.js | 34 | ||||
-rw-r--r-- | spec/frontend/notes/components/mr_discussion_filter_spec.js | 28 | ||||
-rw-r--r-- | spec/frontend/profile/components/follow_spec.js | 49 | ||||
-rw-r--r-- | spec/frontend/profile/components/followers_tab_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/profile/components/following_tab_spec.js | 2 | ||||
-rw-r--r-- | spec/frontend/profile/components/snippets/snippets_tab_spec.js | 43 | ||||
-rw-r--r-- | spec/frontend/profile/mock_data.js | 1 | ||||
-rw-r--r-- | spec/frontend/work_items/components/notes/work_item_note_spec.js | 10 | ||||
-rw-r--r-- | spec/helpers/users_helper_spec.rb | 18 |
9 files changed, 171 insertions, 16 deletions
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js index b4ec00ab766..444d4a96f9c 100644 --- a/spec/frontend/lib/utils/common_utils_spec.js +++ b/spec/frontend/lib/utils/common_utils_spec.js @@ -1140,4 +1140,38 @@ describe('common_utils', () => { expect(result).toEqual([{ hello: '' }, { helloWorld: '' }]); }); }); + + describe('isCurrentUser', () => { + describe('when user is not signed in', () => { + it('returns `false`', () => { + window.gon.current_user_id = null; + + expect(commonUtils.isCurrentUser(1)).toBe(false); + }); + }); + + describe('when current user id does not match the provided user id', () => { + it('returns `false`', () => { + window.gon.current_user_id = 2; + + expect(commonUtils.isCurrentUser(1)).toBe(false); + }); + }); + + describe('when current user id matches the provided user id', () => { + it('returns `true`', () => { + window.gon.current_user_id = 1; + + expect(commonUtils.isCurrentUser(1)).toBe(true); + }); + }); + + describe('when provided user id is a string and it matches current user id', () => { + it('returns `true`', () => { + window.gon.current_user_id = 1; + + expect(commonUtils.isCurrentUser('1')).toBe(true); + }); + }); + }); }); diff --git a/spec/frontend/notes/components/mr_discussion_filter_spec.js b/spec/frontend/notes/components/mr_discussion_filter_spec.js index beb25c30af6..2bb47fd3c9e 100644 --- a/spec/frontend/notes/components/mr_discussion_filter_spec.js +++ b/spec/frontend/notes/components/mr_discussion_filter_spec.js @@ -67,7 +67,7 @@ describe('Merge request discussion filter component', () => { it('lists current filters', () => { createComponent(); - expect(wrapper.findAllComponents(GlListboxItem).length).toBe(MR_FILTER_OPTIONS.length); + expect(wrapper.findAllComponents(GlListboxItem)).toHaveLength(MR_FILTER_OPTIONS.length); }); it('updates store when selecting filter', async () => { @@ -107,4 +107,30 @@ describe('Merge request discussion filter component', () => { expect(wrapper.findComponent(GlButton).text()).toBe(expectedText); }); + + it('when clicking de-select it de-selects all options', async () => { + createComponent(); + + wrapper.find('[data-testid="listbox-reset-button"]').vm.$emit('click'); + + await nextTick(); + + expect(wrapper.findAll('[aria-selected="true"]')).toHaveLength(0); + }); + + it('when clicking select all it selects all options', async () => { + createComponent(); + + wrapper.find('[data-testid="listbox-item-approval"]').vm.$emit('select', false); + + await nextTick(); + + expect(wrapper.findAll('[aria-selected="true"]')).toHaveLength(9); + + wrapper.find('[data-testid="listbox-select-all-button"]').vm.$emit('click'); + + await nextTick(); + + expect(wrapper.findAll('[aria-selected="true"]')).toHaveLength(10); + }); }); diff --git a/spec/frontend/profile/components/follow_spec.js b/spec/frontend/profile/components/follow_spec.js index 2555e41257f..a2e8d065a46 100644 --- a/spec/frontend/profile/components/follow_spec.js +++ b/spec/frontend/profile/components/follow_spec.js @@ -1,11 +1,19 @@ -import { GlAvatarLabeled, GlAvatarLink, GlLoadingIcon, GlPagination } from '@gitlab/ui'; +import { + GlAvatarLabeled, + GlAvatarLink, + GlEmptyState, + GlLoadingIcon, + GlPagination, +} from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import users from 'test_fixtures/api/users/followers/get.json'; import Follow from '~/profile/components/follow.vue'; import { DEFAULT_PER_PAGE } from '~/api'; +import { isCurrentUser } from '~/lib/utils/common_utils'; jest.mock('~/rest_api'); +jest.mock('~/lib/utils/common_utils'); describe('FollowersTab', () => { let wrapper; @@ -15,6 +23,13 @@ describe('FollowersTab', () => { loading: false, page: 1, totalItems: 50, + currentUserEmptyStateTitle: 'UserProfile|You do not have any followers.', + visitorEmptyStateTitle: "UserProfile|This user doesn't have any followers.", + }; + + const defaultProvide = { + followEmptyState: '/illustrations/empty-state/empty-friends-md.svg', + userId: '1', }; const createComponent = ({ propsData = {} } = {}) => { @@ -23,11 +38,13 @@ describe('FollowersTab', () => { ...defaultPropsData, ...propsData, }, + provide: defaultProvide, }); }; const findPagination = () => wrapper.findComponent(GlPagination); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + const findEmptyState = () => wrapper.findComponent(GlEmptyState); describe('when `loading` prop is `true`', () => { it('renders loading icon', () => { @@ -95,5 +112,35 @@ describe('FollowersTab', () => { expect(wrapper.emitted('pagination-input')).toEqual([[nextPage]]); }); }); + + describe('when the users prop is empty', () => { + describe('when user is the current user', () => { + beforeEach(() => { + isCurrentUser.mockImplementation(() => true); + createComponent({ propsData: { users: [] } }); + }); + + it('displays empty state with correct message', () => { + expect(findEmptyState().props()).toMatchObject({ + svgPath: defaultProvide.followEmptyState, + title: defaultPropsData.currentUserEmptyStateTitle, + }); + }); + }); + + describe('when user is a visitor', () => { + beforeEach(() => { + isCurrentUser.mockImplementation(() => false); + createComponent({ propsData: { users: [] } }); + }); + + it('displays empty state with correct message', () => { + expect(findEmptyState().props()).toMatchObject({ + svgPath: defaultProvide.followEmptyState, + title: defaultPropsData.visitorEmptyStateTitle, + }); + }); + }); + }); }); }); diff --git a/spec/frontend/profile/components/followers_tab_spec.js b/spec/frontend/profile/components/followers_tab_spec.js index 0370005d0a4..75586a2c9ea 100644 --- a/spec/frontend/profile/components/followers_tab_spec.js +++ b/spec/frontend/profile/components/followers_tab_spec.js @@ -75,6 +75,8 @@ describe('FollowersTab', () => { loading: false, page: 1, totalItems: 6, + currentUserEmptyStateTitle: FollowersTab.i18n.currentUserEmptyStateTitle, + visitorEmptyStateTitle: FollowersTab.i18n.visitorEmptyStateTitle, }); }); diff --git a/spec/frontend/profile/components/following_tab_spec.js b/spec/frontend/profile/components/following_tab_spec.js index 1eadb2c7388..48d84187739 100644 --- a/spec/frontend/profile/components/following_tab_spec.js +++ b/spec/frontend/profile/components/following_tab_spec.js @@ -68,6 +68,8 @@ describe('FollowingTab', () => { loading: false, page: MOCK_PAGE, totalItems: MOCK_TOTAL_FOLLOWING, + currentUserEmptyStateTitle: FollowingTab.i18n.currentUserEmptyStateTitle, + visitorEmptyStateTitle: FollowingTab.i18n.visitorEmptyStateTitle, }); }); diff --git a/spec/frontend/profile/components/snippets/snippets_tab_spec.js b/spec/frontend/profile/components/snippets/snippets_tab_spec.js index 47e2fbcf2c0..5992bb03e4d 100644 --- a/spec/frontend/profile/components/snippets/snippets_tab_spec.js +++ b/spec/frontend/profile/components/snippets/snippets_tab_spec.js @@ -7,6 +7,7 @@ import { SNIPPET_MAX_LIST_COUNT } from '~/profile/constants'; import SnippetsTab from '~/profile/components/snippets/snippets_tab.vue'; import SnippetRow from '~/profile/components/snippets/snippet_row.vue'; import getUserSnippets from '~/profile/components/graphql/get_user_snippets.query.graphql'; +import { isCurrentUser } from '~/lib/utils/common_utils'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; import { @@ -15,8 +16,14 @@ import { MOCK_USER_SNIPPETS_RES, MOCK_USER_SNIPPETS_PAGINATION_RES, MOCK_USER_SNIPPETS_EMPTY_RES, + MOCK_NEW_SNIPPET_PATH, } from 'jest/profile/mock_data'; +jest.mock('~/lib/utils/common_utils'); +jest.mock('~/helpers/help_page_helper', () => ({ + helpPagePath: jest.fn().mockImplementation(() => 'http://127.0.0.1:3000/help/user/snippets'), +})); + Vue.use(VueApollo); describe('UserProfileSnippetsTab', () => { @@ -32,6 +39,7 @@ describe('UserProfileSnippetsTab', () => { provide: { userId: MOCK_USER.id, snippetsEmptyState: MOCK_SNIPPETS_EMPTY_STATE, + newSnippetPath: MOCK_NEW_SNIPPET_PATH, }, }); }; @@ -52,9 +60,38 @@ describe('UserProfileSnippetsTab', () => { expect(findSnippetRows().exists()).toBe(false); }); - it('does render empty state with correct svg', () => { - expect(findGlEmptyState().exists()).toBe(true); - expect(findGlEmptyState().attributes('svgpath')).toBe(MOCK_SNIPPETS_EMPTY_STATE); + describe('when user is the current user', () => { + beforeEach(() => { + isCurrentUser.mockImplementation(() => true); + createComponent(); + }); + + it('displays empty state with correct message', () => { + expect(findGlEmptyState().props()).toMatchObject({ + svgPath: MOCK_SNIPPETS_EMPTY_STATE, + title: SnippetsTab.i18n.currentUserEmptyStateTitle, + description: SnippetsTab.i18n.emptyStateDescription, + primaryButtonLink: MOCK_NEW_SNIPPET_PATH, + primaryButtonText: SnippetsTab.i18n.newSnippet, + secondaryButtonLink: 'http://127.0.0.1:3000/help/user/snippets', + secondaryButtonText: SnippetsTab.i18n.learnMore, + }); + }); + }); + + describe('when user is a visitor', () => { + beforeEach(() => { + isCurrentUser.mockImplementation(() => false); + createComponent(); + }); + + it('displays empty state with correct message', () => { + expect(findGlEmptyState().props()).toMatchObject({ + svgPath: MOCK_SNIPPETS_EMPTY_STATE, + title: SnippetsTab.i18n.visitorEmptyStateTitle, + description: null, + }); + }); }); }); diff --git a/spec/frontend/profile/mock_data.js b/spec/frontend/profile/mock_data.js index 856534aebd3..6c4ff0a84f9 100644 --- a/spec/frontend/profile/mock_data.js +++ b/spec/frontend/profile/mock_data.js @@ -22,6 +22,7 @@ export const userCalendarResponse = { }; export const MOCK_SNIPPETS_EMPTY_STATE = 'illustrations/empty-state/empty-snippets-md.svg'; +export const MOCK_NEW_SNIPPET_PATH = '/-/snippets/new'; export const MOCK_USER = { id: '1', diff --git a/spec/frontend/work_items/components/notes/work_item_note_spec.js b/spec/frontend/work_items/components/notes/work_item_note_spec.js index 94e3b3ccc81..c5d1decfb42 100644 --- a/spec/frontend/work_items/components/notes/work_item_note_spec.js +++ b/spec/frontend/work_items/components/notes/work_item_note_spec.js @@ -95,14 +95,10 @@ describe('Work Item Note', () => { updateWorkItemMutationHandler = updateWorkItemMutationSuccessHandler, assignees = mockAssignees, workItemByIidResponseHandler = workItemResponseHandler, - workItemsMvc2 = false, } = {}) => { wrapper = shallowMount(WorkItemNote, { provide: { fullPath: 'test-project-path', - glFeatures: { - workItemsMvc2, - }, }, propsData: { workItemId, @@ -432,12 +428,6 @@ describe('Work Item Note', () => { }); }); - it('does not show awards when feature flag disabled', () => { - createComponent(); - - expect(findAwardsList().exists()).toBe(false); - }); - it('passes note props to awards list', () => { createComponent({ note: mockWorkItemCommentNote, workItemsMvc2: true }); diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb index 6ee208dfd15..c0d3c31a36d 100644 --- a/spec/helpers/users_helper_spec.rb +++ b/spec/helpers/users_helper_spec.rb @@ -496,13 +496,17 @@ RSpec.describe UsersHelper do describe '#user_profile_tabs_app_data' do before do + allow(helper).to receive(:current_user).and_return(user) allow(helper).to receive(:user_calendar_path).with(user, :json).and_return('/users/root/calendar.json') allow(helper).to receive(:user_activity_path).with(user, :json).and_return('/users/root/activity.json') + allow(helper).to receive(:new_snippet_path).and_return('/-/snippets/new') allow(user).to receive_message_chain(:followers, :count).and_return(2) allow(user).to receive_message_chain(:followees, :count).and_return(3) end it 'returns expected hash' do + allow(helper).to receive(:can?).with(user, :create_snippet).and_return(true) + expect(helper.user_profile_tabs_app_data(user)).to match({ followees_count: 3, followers_count: 2, @@ -510,9 +514,21 @@ RSpec.describe UsersHelper do user_activity_path: '/users/root/activity.json', utc_offset: 0, user_id: user.id, - snippets_empty_state: match_asset_path('illustrations/empty-state/empty-snippets-md.svg') + new_snippet_path: '/-/snippets/new', + snippets_empty_state: match_asset_path('illustrations/empty-state/empty-snippets-md.svg'), + follow_empty_state: match_asset_path('illustrations/empty-state/empty-friends-md.svg') }) end + + context 'when user does not have create_snippet permissions' do + before do + allow(helper).to receive(:can?).with(user, :create_snippet).and_return(false) + end + + it 'returns nil for new_snippet_path property' do + expect(helper.user_profile_tabs_app_data(user)[:new_snippet_path]).to be_nil + end + end end describe '#load_max_project_member_accesses' do |