diff options
Diffstat (limited to 'spec/frontend')
3 files changed, 196 insertions, 3 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 8c3c549a5eb..3cdf6432b95 100644 --- a/spec/frontend/invite_members/components/invite_members_modal_spec.js +++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js @@ -16,16 +16,25 @@ import Api from '~/api'; import ExperimentTracking from '~/experimentation/experiment_tracking'; import InviteMembersModal from '~/invite_members/components/invite_members_modal.vue'; import MembersTokenSelect from '~/invite_members/components/members_token_select.vue'; -import { INVITE_MEMBERS_IN_COMMENT, MEMBER_AREAS_OF_FOCUS } from '~/invite_members/constants'; +import { + INVITE_MEMBERS_IN_COMMENT, + MEMBER_AREAS_OF_FOCUS, + INVITE_MEMBERS_FOR_TASK, +} from '~/invite_members/constants'; import eventHub from '~/invite_members/event_hub'; import axios from '~/lib/utils/axios_utils'; import httpStatus from '~/lib/utils/http_status'; +import { getParameterValues } from '~/lib/utils/url_utility'; import { apiPaths, membersApiResponse, invitationsApiResponse } from '../mock_data/api_responses'; let wrapper; let mock; jest.mock('~/experimentation/experiment_tracking'); +jest.mock('~/lib/utils/url_utility', () => ({ + ...jest.requireActual('~/lib/utils/url_utility'), + getParameterValues: jest.fn(() => []), +})); const id = '1'; const name = 'test name'; @@ -40,6 +49,15 @@ const areasOfFocusOptions = [ { text: 'area1', value: 'area1' }, { text: 'area2', value: 'area2' }, ]; +const tasksToBeDoneOptions = [ + { text: 'First task', value: 'first' }, + { text: 'Second task', value: 'second' }, +]; +const newProjectPath = 'projects/new'; +const projects = [ + { text: 'First project', value: '1' }, + { text: 'Second project', value: '2' }, +]; const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' }; const user2 = { id: 2, name: 'Name Two', username: 'one_2', avatar_url: '' }; @@ -59,6 +77,9 @@ const sharedGroup = { id: '981' }; const createComponent = (data = {}, props = {}) => { wrapper = shallowMountExtended(InviteMembersModal, { + provide: { + newProjectPath, + }, propsData: { id, name, @@ -68,6 +89,8 @@ const createComponent = (data = {}, props = {}) => { areasOfFocusOptions, defaultAccessLevel, noSelectionAreasOfFocus, + tasksToBeDoneOptions, + projects, helpLink, ...props, }, @@ -131,6 +154,10 @@ describe('InviteMembersModal', () => { const membersFormGroupDescription = () => findMembersFormGroup().props('description'); const findMembersSelect = () => wrapper.findComponent(MembersTokenSelect); const findAreaofFocusCheckBoxGroup = () => wrapper.findComponent(GlFormCheckboxGroup); + const findTasksToBeDone = () => wrapper.findByTestId('invite-members-modal-tasks-to-be-done'); + const findTasks = () => wrapper.findByTestId('invite-members-modal-tasks'); + const findProjectSelect = () => wrapper.findByTestId('invite-members-modal-project-select'); + const findNoProjectsAlert = () => wrapper.findByTestId('invite-members-modal-no-projects-alert'); describe('rendering the modal', () => { beforeEach(() => { @@ -191,6 +218,127 @@ describe('InviteMembersModal', () => { }); }); + describe('rendering the tasks to be done', () => { + const setupComponent = ( + extraData = {}, + props = {}, + urlParameter = ['invite_members_for_task'], + ) => { + const data = { + selectedAccessLevel: 30, + selectedTasksToBeDone: ['ci', 'code'], + ...extraData, + }; + getParameterValues.mockImplementation(() => urlParameter); + createComponent(data, props); + }; + + afterAll(() => { + getParameterValues.mockImplementation(() => []); + }); + + it('renders the tasks to be done', () => { + setupComponent(); + + expect(findTasksToBeDone().exists()).toBe(true); + }); + + describe('when the selected access level is lower than 30', () => { + it('does not render the tasks to be done', () => { + setupComponent({ selectedAccessLevel: 20 }); + + expect(findTasksToBeDone().exists()).toBe(false); + }); + }); + + describe('when the url does not contain the parameter `open_modal=invite_members_for_task`', () => { + it('does not render the tasks to be done', () => { + setupComponent({}, {}, []); + + expect(findTasksToBeDone().exists()).toBe(false); + }); + }); + + describe('rendering the tasks', () => { + it('renders the tasks', () => { + setupComponent(); + + expect(findTasks().exists()).toBe(true); + }); + + it('does not render an alert', () => { + setupComponent(); + + expect(findNoProjectsAlert().exists()).toBe(false); + }); + + describe('when there are no projects passed in the data', () => { + it('does not render the tasks', () => { + setupComponent({}, { projects: [] }); + + expect(findTasks().exists()).toBe(false); + }); + + it('renders an alert with a link to the new projects path', () => { + setupComponent({}, { projects: [] }); + + expect(findNoProjectsAlert().exists()).toBe(true); + expect(findNoProjectsAlert().findComponent(GlLink).attributes('href')).toBe( + newProjectPath, + ); + }); + }); + }); + + describe('rendering the project dropdown', () => { + it('renders the project select', () => { + setupComponent(); + + expect(findProjectSelect().exists()).toBe(true); + }); + + describe('when the modal is shown for a project', () => { + it('does not render the project select', () => { + setupComponent({}, { isProject: true }); + + expect(findProjectSelect().exists()).toBe(false); + }); + }); + + describe('when no tasks are selected', () => { + it('does not render the project select', () => { + setupComponent({ selectedTasksToBeDone: [] }); + + expect(findProjectSelect().exists()).toBe(false); + }); + }); + }); + + describe('tracking events', () => { + it('tracks the view for invite_members_for_task', () => { + setupComponent(); + + expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name); + expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith( + INVITE_MEMBERS_FOR_TASK.view, + ); + }); + + it('tracks the submit for invite_members_for_task', () => { + setupComponent(); + clickInviteButton(); + + expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name, { + label: 'selected_tasks_to_be_done', + property: 'ci,code', + }); + expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith( + INVITE_MEMBERS_FOR_TASK.submit, + ); + }); + }); + }); + describe('displaying the correct introText and form group description', () => { describe('when inviting to a project', () => { describe('when inviting members', () => { @@ -267,6 +415,8 @@ describe('InviteMembersModal', () => { invite_source: inviteSource, format: 'json', areas_of_focus: noSelectionAreasOfFocus, + tasks_to_be_done: [], + tasks_project_id: '', }; describe('when member is added successfully', () => { @@ -448,6 +598,8 @@ describe('InviteMembersModal', () => { email: 'email@example.com', invite_source: inviteSource, areas_of_focus: noSelectionAreasOfFocus, + tasks_to_be_done: [], + tasks_project_id: '', format: 'json', }; @@ -576,6 +728,8 @@ describe('InviteMembersModal', () => { invite_source: inviteSource, areas_of_focus: noSelectionAreasOfFocus, format: 'json', + tasks_to_be_done: [], + tasks_project_id: '', }; const emailPostData = { ...postData, email: 'email@example.com' }; diff --git a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js index 44656b2b67d..939a2939243 100644 --- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js +++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js @@ -40,6 +40,8 @@ describe('Pipeline Status', () => { const findPipelineId = () => wrapper.find('[data-testid="pipeline-id"]'); const findPipelineCommit = () => wrapper.find('[data-testid="pipeline-commit"]'); const findPipelineErrorMsg = () => wrapper.find('[data-testid="pipeline-error-msg"]'); + const findPipelineNotTriggeredErrorMsg = () => + wrapper.find('[data-testid="pipeline-not-triggered-error-msg"]'); const findPipelineLoadingMsg = () => wrapper.find('[data-testid="pipeline-loading-msg"]'); const findPipelineViewBtn = () => wrapper.find('[data-testid="pipeline-view-btn"]'); const findStatusIcon = () => wrapper.find('[data-testid="pipeline-status-icon"]'); @@ -117,7 +119,8 @@ describe('Pipeline Status', () => { await waitForPromises(); }); - it('renders error', () => { + it('renders api error', () => { + expect(findPipelineNotTriggeredErrorMsg().exists()).toBe(false); expect(findIcon().attributes('name')).toBe('warning-solid'); expect(findPipelineErrorMsg().text()).toBe(i18n.fetchError); }); @@ -129,6 +132,23 @@ describe('Pipeline Status', () => { expect(findPipelineViewBtn().exists()).toBe(false); }); }); + + describe('when pipeline is null', () => { + beforeEach(() => { + mockPipelineQuery.mockResolvedValue({ + data: { project: { pipeline: null } }, + }); + + createComponentWithApollo(); + waitForPromises(); + }); + + it('renders pipeline not triggered error', () => { + expect(findPipelineErrorMsg().exists()).toBe(false); + expect(findIcon().attributes('name')).toBe('information-o'); + expect(findPipelineNotTriggeredErrorMsg().text()).toBe(i18n.pipelineNotTriggeredMsg); + }); + }); }); describe('when feature flag for pipeline mini graph is enabled', () => { diff --git a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js index 7e81df1d7d2..c72c23a3a60 100644 --- a/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js +++ b/spec/frontend/sidebar/components/assignees/uncollapsed_assignee_list_spec.js @@ -10,7 +10,7 @@ const DEFAULT_RENDER_COUNT = 5; describe('UncollapsedAssigneeList component', () => { let wrapper; - function createComponent(props = {}) { + function createComponent(props = {}, glFeatures = {}) { const propsData = { users: [], rootPath: TEST_HOST, @@ -19,6 +19,7 @@ describe('UncollapsedAssigneeList component', () => { wrapper = mount(UncollapsedAssigneeList, { propsData, + provide: { glFeatures }, }); } @@ -99,4 +100,22 @@ describe('UncollapsedAssigneeList component', () => { }); }); }); + + describe('merge requests', () => { + it.each` + numberOfUsers + ${1} + ${5} + `('displays as a vertical list for $numberOfUsers of users', ({ numberOfUsers }) => { + createComponent( + { + users: UsersMockHelper.createNumberRandomUsers(numberOfUsers), + issuableType: 'merge_request', + }, + { mrAttentionRequests: true }, + ); + + expect(wrapper.findAll('[data-testid="username"]').length).toBe(numberOfUsers); + }); + }); }); |