diff options
Diffstat (limited to 'spec/frontend/invite_members')
5 files changed, 101 insertions, 18 deletions
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js index 045a454e63a..2058784b033 100644 --- a/spec/frontend/invite_members/components/invite_members_modal_spec.js +++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js @@ -1,4 +1,4 @@ -import { GlLink, GlModal, GlSprintf, GlFormGroup } from '@gitlab/ui'; +import { GlLink, GlModal, GlSprintf, GlFormGroup, GlCollapse, GlIcon } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import { nextTick } from 'vue'; import { stubComponent } from 'helpers/stub_component'; @@ -18,6 +18,7 @@ import { MEMBERS_PLACEHOLDER_DISABLED, MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT, LEARN_GITLAB, + EXPANDED_ERRORS, } from '~/invite_members/constants'; import eventHub from '~/invite_members/event_hub'; import ContentTransition from '~/vue_shared/components/content_transition.vue'; @@ -36,6 +37,7 @@ import { user3, user4, user5, + user6, GlEmoji, } from '../mock_data/member_modal'; @@ -95,9 +97,12 @@ describe('InviteMembersModal', () => { const findBase = () => wrapper.findComponent(InviteModalBase); const findIntroText = () => wrapper.findByTestId('modal-base-intro-text').text(); const findMemberErrorAlert = () => wrapper.findByTestId('alert-member-error'); + const findMoreInviteErrorsButton = () => wrapper.findByTestId('accordion-button'); + const findAccordion = () => wrapper.findComponent(GlCollapse); + const findErrorsIcon = () => wrapper.findComponent(GlIcon); const findMemberErrorMessage = (element) => - `${Object.keys(invitationsApiResponse.MULTIPLE_RESTRICTED.message)[element]}: ${ - Object.values(invitationsApiResponse.MULTIPLE_RESTRICTED.message)[element] + `${Object.keys(invitationsApiResponse.EXPANDED_RESTRICTED.message)[element]}: ${ + Object.values(invitationsApiResponse.EXPANDED_RESTRICTED.message)[element] }`; const emitEventFromModal = (eventName) => () => findModal().vm.$emit(eventName, { preventDefault: jest.fn() }); @@ -666,8 +671,8 @@ describe('InviteMembersModal', () => { it('displays errors for multiple and allows clearing', async () => { createInviteMembersToGroupWrapper(); - await triggerMembersTokenSelect([user3, user4, user5]); - mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.MULTIPLE_RESTRICTED); + await triggerMembersTokenSelect([user3, user4, user5, user6]); + mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.EXPANDED_RESTRICTED); clickInviteButton(); @@ -675,19 +680,44 @@ describe('InviteMembersModal', () => { expect(findMemberErrorAlert().exists()).toBe(true); expect(findMemberErrorAlert().props('title')).toContain( - "The following 3 members couldn't be invited", + "The following 4 members couldn't be invited", ); expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(0)); expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(1)); expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(2)); + expect(findMemberErrorAlert().text()).toContain(findMemberErrorMessage(3)); + expect(findAccordion().exists()).toBe(true); + expect(findMoreInviteErrorsButton().text()).toContain('Show more (2)'); + expect(findErrorsIcon().attributes('class')).not.toContain('gl-rotate-180'); + expect(findAccordion().attributes('visible')).toBeUndefined(); + + await findMoreInviteErrorsButton().vm.$emit('click'); + + expect(findMoreInviteErrorsButton().text()).toContain(EXPANDED_ERRORS); + expect(findErrorsIcon().attributes('class')).toContain('gl-rotate-180'); + expect(findAccordion().attributes('visible')).toBeDefined(); + + await findMoreInviteErrorsButton().vm.$emit('click'); + + expect(findMoreInviteErrorsButton().text()).toContain('Show more (2)'); + expect(findAccordion().attributes('visible')).toBeUndefined(); await removeMembersToken(user3); + expect(findMoreInviteErrorsButton().text()).toContain('Show more (1)'); expect(findMemberErrorAlert().props('title')).toContain( - "The following 2 members couldn't be invited", + "The following 3 members couldn't be invited", ); expect(findMemberErrorAlert().text()).not.toContain(findMemberErrorMessage(0)); + await removeMembersToken(user6); + + expect(findMoreInviteErrorsButton().exists()).toBe(false); + expect(findMemberErrorAlert().props('title')).toContain( + "The following 2 members couldn't be invited", + ); + expect(findMemberErrorAlert().text()).not.toContain(findMemberErrorMessage(2)); + await removeMembersToken(user4); expect(findMemberErrorAlert().props('title')).toContain( diff --git a/spec/frontend/invite_members/components/members_token_select_spec.js b/spec/frontend/invite_members/components/members_token_select_spec.js index 6375d0f7e2e..0455460918c 100644 --- a/spec/frontend/invite_members/components/members_token_select_spec.js +++ b/spec/frontend/invite_members/components/members_token_select_spec.js @@ -5,6 +5,7 @@ import { stubComponent } from 'helpers/stub_component'; import waitForPromises from 'helpers/wait_for_promises'; import * as UserApi from '~/api/user_api'; import MembersTokenSelect from '~/invite_members/components/members_token_select.vue'; +import { VALID_TOKEN_BACKGROUND, INVALID_TOKEN_BACKGROUND } from '~/invite_members/constants'; const label = 'testgroup'; const placeholder = 'Search for a member'; @@ -49,6 +50,39 @@ describe('MembersTokenSelect', () => { }); }); + describe('when there are invalidMembers', () => { + it('adds in the correct class values for the tokens', async () => { + const badToken = { ...user1, class: INVALID_TOKEN_BACKGROUND }; + const goodToken = { ...user2, class: VALID_TOKEN_BACKGROUND }; + + wrapper = createComponent(); + + findTokenSelector().vm.$emit('input', [user1, user2]); + + await waitForPromises(); + + expect(findTokenSelector().props('selectedTokens')).toEqual([user1, user2]); + + await wrapper.setProps({ invalidMembers: { one_1: 'bad stuff' } }); + + expect(findTokenSelector().props('selectedTokens')).toEqual([badToken, goodToken]); + }); + + it('does not change class when invalid members are cleared', async () => { + // arrange - invalidMembers is non-empty and then tokens are added + wrapper = createComponent(); + await wrapper.setProps({ invalidMembers: { one_1: 'bad stuff' } }); + findTokenSelector().vm.$emit('input', [user1, user2]); + await waitForPromises(); + + // act - invalidMembers clears out + await wrapper.setProps({ invalidMembers: {} }); + + // assert - we didn't try to update the tokens + expect(findTokenSelector().props('selectedTokens')).toEqual([user1, user2]); + }); + }); + describe('users', () => { beforeEach(() => { jest.spyOn(UserApi, 'getUsers').mockResolvedValue({ data: allUsers }); diff --git a/spec/frontend/invite_members/components/user_limit_notification_spec.js b/spec/frontend/invite_members/components/user_limit_notification_spec.js index bbc17932a49..543fc28a342 100644 --- a/spec/frontend/invite_members/components/user_limit_notification_spec.js +++ b/spec/frontend/invite_members/components/user_limit_notification_spec.js @@ -9,6 +9,8 @@ import { import { freeUsersLimit, membersCount } from '../mock_data/member_modal'; +const WARNING_ALERT_TITLE = 'You only have space for 2 more members in name'; + describe('UserLimitNotification', () => { let wrapper; @@ -33,7 +35,7 @@ describe('UserLimitNotification', () => { }, ...props, }, - provide: { name: 'my group' }, + provide: { name: 'name' }, stubs: { GlSprintf }, }); }; @@ -50,7 +52,7 @@ describe('UserLimitNotification', () => { }); }); - describe('when close to limit with a personal namepace', () => { + describe('when close to limit within a personal namepace', () => { beforeEach(() => { createComponent(true, false, { membersCount: 3, userNamespace: true }); }); @@ -58,27 +60,24 @@ describe('UserLimitNotification', () => { it('renders the limit for a personal namespace', () => { const alert = findAlert(); - expect(alert.attributes('title')).toEqual( - 'You only have space for 2 more members in your personal projects', - ); + expect(alert.attributes('title')).toEqual(WARNING_ALERT_TITLE); + expect(alert.text()).toEqual( 'To make more space, you can remove members who no longer need access.', ); }); }); - describe('when close to limit', () => { + describe('when close to limit within a group', () => { it("renders user's limit notification", () => { createComponent(true, false, { membersCount: 3 }); const alert = findAlert(); - expect(alert.attributes('title')).toEqual( - 'You only have space for 2 more members in my group', - ); + expect(alert.attributes('title')).toEqual(WARNING_ALERT_TITLE); expect(alert.text()).toEqual( - 'To get more members an owner of this namespace can start a trial or upgrade to a paid tier.', + 'To get more members an owner of the group can start a trial or upgrade to a paid tier.', ); }); }); @@ -89,7 +88,7 @@ describe('UserLimitNotification', () => { const alert = findAlert(); - expect(alert.attributes('title')).toEqual("You've reached your 5 members limit for my group"); + expect(alert.attributes('title')).toEqual("You've reached your 5 members limit for name"); expect(alert.text()).toEqual(REACHED_LIMIT_UPGRADE_SUGGESTION_MESSAGE); }); diff --git a/spec/frontend/invite_members/mock_data/api_responses.js b/spec/frontend/invite_members/mock_data/api_responses.js index 4ad3b6aeb66..6fe06decb6b 100644 --- a/spec/frontend/invite_members/mock_data/api_responses.js +++ b/spec/frontend/invite_members/mock_data/api_responses.js @@ -26,6 +26,20 @@ const MULTIPLE_RESTRICTED = { status: 'error', }; +const EXPANDED_RESTRICTED = { + message: { + 'email@example.com': + "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.", + 'email4@example.com': + "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check the Domain denylist.", + 'email5@example.com': + "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check the Domain denylist.", + root: + "The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.", + }, + status: 'error', +}; + const EMAIL_TAKEN = { message: { 'email@example.org': "The member's email address has already been taken", @@ -41,4 +55,5 @@ export const invitationsApiResponse = { EMAIL_RESTRICTED, MULTIPLE_RESTRICTED, EMAIL_TAKEN, + EXPANDED_RESTRICTED, }; diff --git a/spec/frontend/invite_members/mock_data/member_modal.js b/spec/frontend/invite_members/mock_data/member_modal.js index 7d675b6206c..4f4e9345e46 100644 --- a/spec/frontend/invite_members/mock_data/member_modal.js +++ b/spec/frontend/invite_members/mock_data/member_modal.js @@ -39,5 +39,10 @@ export const user5 = { name: 'root', avatar_url: '', }; +export const user6 = { + id: 'user-defined-token3', + name: 'email5@example.com', + avatar_url: '', +}; export const GlEmoji = { template: '<img/>' }; |