2021-03-11 19:13:27 +05:30
import {
GlAlert ,
GlButton ,
GlDropdown ,
GlDropdownItem ,
GlFormSelect ,
GlLabel ,
GlSearchBoxByType ,
GlTable ,
} from '@gitlab/ui' ;
2020-07-28 23:09:34 +05:30
import { getByRole } from '@testing-library/dom' ;
2020-04-22 19:07:51 +05:30
import { mount , shallowMount } from '@vue/test-utils' ;
2020-07-28 23:09:34 +05:30
import AxiosMockAdapter from 'axios-mock-adapter' ;
2020-04-22 19:07:51 +05:30
import JiraImportForm from '~/jira_import/components/jira_import_form.vue' ;
2020-10-24 23:57:45 +05:30
import getJiraUserMappingMutation from '~/jira_import/queries/get_jira_user_mapping.mutation.graphql' ;
import initiateJiraImportMutation from '~/jira_import/queries/initiate_jira_import.mutation.graphql' ;
2021-03-11 19:13:27 +05:30
import searchProjectMembersQuery from '~/jira_import/queries/search_project_members.query.graphql' ;
import axios from '~/lib/utils/axios_utils' ;
2020-10-24 23:57:45 +05:30
import {
imports ,
issuesPath ,
jiraProjects ,
jiraUsersResponse ,
projectId ,
projectPath ,
userMappings as defaultUserMappings ,
} from '../mock_data' ;
2020-04-22 19:07:51 +05:30
describe ( 'JiraImportForm' , ( ) => {
2020-07-28 23:09:34 +05:30
let axiosMock ;
2020-10-24 23:57:45 +05:30
let mutateSpy ;
2021-03-11 19:13:27 +05:30
let querySpy ;
2020-04-22 19:07:51 +05:30
let wrapper ;
2020-07-28 23:09:34 +05:30
const currentUsername = 'mrgitlab' ;
2020-10-24 23:57:45 +05:30
const getAlert = ( ) => wrapper . find ( GlAlert ) ;
2020-07-28 23:09:34 +05:30
2020-05-24 23:13:21 +05:30
const getSelectDropdown = ( ) => wrapper . find ( GlFormSelect ) ;
2020-10-24 23:57:45 +05:30
const getContinueButton = ( ) => wrapper . find ( GlButton ) ;
2020-04-22 19:07:51 +05:30
const getCancelButton = ( ) => wrapper . findAll ( GlButton ) . at ( 1 ) ;
2020-10-24 23:57:45 +05:30
const getLabel = ( ) => wrapper . find ( GlLabel ) ;
const getTable = ( ) => wrapper . find ( GlTable ) ;
2020-11-24 15:15:51 +05:30
const getUserDropdown = ( ) => getTable ( ) . find ( GlDropdown ) ;
2020-10-24 23:57:45 +05:30
2021-03-08 18:12:59 +05:30
const getHeader = ( name ) => getByRole ( wrapper . element , 'columnheader' , { name } ) ;
2020-07-28 23:09:34 +05:30
2020-10-24 23:57:45 +05:30
const findLoadMoreUsersButton = ( ) => wrapper . find ( '[data-testid="load-more-users-button"]' ) ;
const mountComponent = ( {
hasMoreUsers = false ,
isSubmitting = false ,
loading = false ,
mutate = mutateSpy ,
selectedProject = 'MTG' ,
userMappings = defaultUserMappings ,
mountFunction = shallowMount ,
} = { } ) =>
2020-07-28 23:09:34 +05:30
mountFunction ( JiraImportForm , {
propsData : {
issuesPath ,
2020-10-24 23:57:45 +05:30
jiraImports : imports ,
2020-07-28 23:09:34 +05:30
jiraProjects ,
2020-10-24 23:57:45 +05:30
projectId ,
projectPath ,
2020-07-28 23:09:34 +05:30
} ,
data : ( ) => ( {
2020-10-24 23:57:45 +05:30
hasMoreUsers ,
2020-07-28 23:09:34 +05:30
isFetching : false ,
2020-10-24 23:57:45 +05:30
isSubmitting ,
2020-07-28 23:09:34 +05:30
searchTerm : '' ,
2020-10-24 23:57:45 +05:30
selectedProject ,
2020-07-28 23:09:34 +05:30
selectState : null ,
users : [ ] ,
2020-10-24 23:57:45 +05:30
userMappings ,
2020-07-28 23:09:34 +05:30
} ) ,
2020-10-24 23:57:45 +05:30
mocks : {
$apollo : {
loading ,
mutate ,
2021-03-11 19:13:27 +05:30
query : querySpy ,
2020-10-24 23:57:45 +05:30
} ,
} ,
2020-07-28 23:09:34 +05:30
currentUsername ,
} ) ;
beforeEach ( ( ) => {
axiosMock = new AxiosMockAdapter ( axios ) ;
2021-03-11 19:13:27 +05:30
mutateSpy = jest . fn ( ) . mockResolvedValue ( {
data : {
jiraImportStart : { errors : [ ] } ,
jiraImportUsers : { jiraUsers : [ ] , errors : [ ] } ,
} ,
} ) ;
querySpy = jest . fn ( ) . mockResolvedValue ( {
data : { project : { projectMembers : { nodes : [ ] } } } ,
} ) ;
2020-07-28 23:09:34 +05:30
} ) ;
2020-04-22 19:07:51 +05:30
afterEach ( ( ) => {
2020-07-28 23:09:34 +05:30
axiosMock . restore ( ) ;
2020-10-24 23:57:45 +05:30
mutateSpy . mockRestore ( ) ;
2021-03-11 19:13:27 +05:30
querySpy . mockRestore ( ) ;
2020-04-22 19:07:51 +05:30
wrapper . destroy ( ) ;
wrapper = null ;
} ) ;
2020-10-24 23:57:45 +05:30
describe ( 'select dropdown project selection' , ( ) => {
2020-04-22 19:07:51 +05:30
it ( 'is shown' , ( ) => {
wrapper = mountComponent ( ) ;
2020-11-24 15:15:51 +05:30
expect ( wrapper . find ( GlFormSelect ) . exists ( ) ) . toBe ( true ) ;
2020-04-22 19:07:51 +05:30
} ) ;
it ( 'contains a list of Jira projects to select from' , ( ) => {
2020-07-28 23:09:34 +05:30
wrapper = mountComponent ( { mountFunction : mount } ) ;
2020-04-22 19:07:51 +05:30
2020-05-24 23:13:21 +05:30
getSelectDropdown ( )
2020-04-22 19:07:51 +05:30
. findAll ( 'option' )
. wrappers . forEach ( ( optionEl , index ) => {
2020-07-28 23:09:34 +05:30
expect ( optionEl . text ( ) ) . toBe ( jiraProjects [ index ] . text ) ;
2020-04-22 19:07:51 +05:30
} ) ;
} ) ;
2020-07-28 23:09:34 +05:30
2020-10-24 23:57:45 +05:30
describe ( 'when selected project has been imported before' , ( ) => {
it ( 'shows jira-import::MTG-3 label since project MTG has been imported 2 time before' , ( ) => {
wrapper = mountComponent ( ) ;
expect ( getLabel ( ) . props ( 'title' ) ) . toBe ( 'jira-import::MTG-3' ) ;
} ) ;
it ( 'shows warning alert to explain project MTG has been imported 2 times before' , ( ) => {
wrapper = mountComponent ( { mountFunction : mount } ) ;
expect ( getAlert ( ) . text ( ) ) . toBe (
'You have imported from this project 2 times before. Each new import will create duplicate issues.' ,
) ;
} ) ;
} ) ;
2020-07-28 23:09:34 +05:30
2020-10-24 23:57:45 +05:30
describe ( 'when selected project has not been imported before' , ( ) => {
beforeEach ( ( ) => {
wrapper = mountComponent ( { selectedProject : 'MJP' } ) ;
} ) ;
it ( 'shows jira-import::MJP-1 label since project MJP has not been imported before' , ( ) => {
expect ( getLabel ( ) . props ( 'title' ) ) . toBe ( 'jira-import::MJP-1' ) ;
} ) ;
2020-07-28 23:09:34 +05:30
2020-10-24 23:57:45 +05:30
it ( 'does not show warning alert since project MJP has not been imported before' , ( ) => {
expect ( getAlert ( ) . exists ( ) ) . toBe ( false ) ;
} ) ;
2020-07-28 23:09:34 +05:30
} ) ;
2020-04-22 19:07:51 +05:30
} ) ;
describe ( 'form information' , ( ) => {
beforeEach ( ( ) => {
wrapper = mountComponent ( ) ;
} ) ;
2020-07-28 23:09:34 +05:30
it ( 'shows a heading for the user mapping section' , ( ) => {
expect (
getByRole ( wrapper . element , 'heading' , { name : 'Jira-GitLab user mapping template' } ) ,
) . toBeTruthy ( ) ;
} ) ;
2020-04-22 19:07:51 +05:30
it ( 'shows information to the user' , ( ) => {
expect ( wrapper . find ( 'p' ) . text ( ) ) . toBe (
2020-10-24 23:57:45 +05:30
'Jira users have been imported from the configured Jira instance. They can be mapped by selecting a GitLab user from the dropdown in the "GitLab username" column. When the form appears, the dropdown defaults to the user conducting the import.' ,
2020-04-22 19:07:51 +05:30
) ;
} ) ;
2020-07-28 23:09:34 +05:30
} ) ;
2020-04-22 19:07:51 +05:30
2020-07-28 23:09:34 +05:30
describe ( 'table' , ( ) => {
describe ( 'headers' , ( ) => {
beforeEach ( ( ) => {
wrapper = mountComponent ( { mountFunction : mount } ) ;
} ) ;
2020-04-22 19:07:51 +05:30
2020-07-28 23:09:34 +05:30
it ( 'has a "Jira display name" column' , ( ) => {
expect ( getHeader ( 'Jira display name' ) ) . toBeTruthy ( ) ;
} ) ;
2020-04-22 19:07:51 +05:30
2020-07-28 23:09:34 +05:30
it ( 'has an "arrow" column' , ( ) => {
expect ( getHeader ( 'Arrow' ) ) . toBeTruthy ( ) ;
} ) ;
2020-04-22 19:07:51 +05:30
2020-07-28 23:09:34 +05:30
it ( 'has a "GitLab username" column' , ( ) => {
expect ( getHeader ( 'GitLab username' ) ) . toBeTruthy ( ) ;
} ) ;
2020-04-22 19:07:51 +05:30
} ) ;
2020-07-28 23:09:34 +05:30
describe ( 'body' , ( ) => {
it ( 'shows all user mappings' , ( ) => {
wrapper = mountComponent ( { mountFunction : mount } ) ;
2020-10-24 23:57:45 +05:30
expect ( getTable ( ) . findAll ( 'tbody tr' ) ) . toHaveLength ( 2 ) ;
2020-07-28 23:09:34 +05:30
} ) ;
it ( 'shows correct information in each cell' , ( ) => {
wrapper = mountComponent ( { mountFunction : mount } ) ;
2020-10-24 23:57:45 +05:30
expect ( getTable ( ) . element ) . toMatchSnapshot ( ) ;
} ) ;
describe ( 'when there is no Jira->GitLab user mapping' , ( ) => {
it ( 'shows the logged in user in the dropdown' , ( ) => {
wrapper = mountComponent ( {
mountFunction : mount ,
userMappings : [
{
jiraAccountId : 'aei23f98f-q23fj98qfj' ,
jiraDisplayName : 'Jane Doe' ,
jiraEmail : 'janedoe@example.com' ,
gitlabId : undefined ,
gitlabUsername : undefined ,
} ,
] ,
} ) ;
expect ( getUserDropdown ( ) . text ( ) ) . toContain ( currentUsername ) ;
} ) ;
} ) ;
describe ( 'when there is a Jira->GitLab user mapping' , ( ) => {
it ( 'shows the mapped user in the dropdown' , ( ) => {
const gitlabUsername = 'mai' ;
wrapper = mountComponent ( {
mountFunction : mount ,
userMappings : [
{
jiraAccountId : 'aei23f98f-q23fj98qfj' ,
jiraDisplayName : 'Jane Doe' ,
jiraEmail : 'janedoe@example.com' ,
gitlabId : 14 ,
gitlabUsername ,
} ,
] ,
} ) ;
expect ( getUserDropdown ( ) . text ( ) ) . toContain ( gitlabUsername ) ;
} ) ;
2020-07-28 23:09:34 +05:30
} ) ;
2020-04-22 19:07:51 +05:30
} ) ;
} ) ;
2021-03-11 19:13:27 +05:30
describe ( 'member search' , ( ) => {
describe ( 'when searching for a member' , ( ) => {
beforeEach ( ( ) => {
querySpy = jest . fn ( ) . mockResolvedValue ( {
data : {
project : {
projectMembers : {
nodes : [
{
user : {
id : 7 ,
name : 'Frederic Chopin' ,
username : 'fchopin' ,
} ,
} ,
] ,
} ,
} ,
} ,
} ) ;
wrapper = mountComponent ( { mountFunction : mount } ) ;
wrapper . find ( GlSearchBoxByType ) . vm . $emit ( 'input' , 'fred' ) ;
} ) ;
it ( 'makes a GraphQL call' , ( ) => {
const queryArgument = {
query : searchProjectMembersQuery ,
variables : {
fullPath : projectPath ,
search : 'fred' ,
} ,
} ;
expect ( querySpy ) . toHaveBeenCalledWith ( expect . objectContaining ( queryArgument ) ) ;
} ) ;
it ( 'updates the user list' , ( ) => {
expect ( getUserDropdown ( ) . findAll ( GlDropdownItem ) ) . toHaveLength ( 1 ) ;
expect ( getUserDropdown ( ) . find ( GlDropdownItem ) . text ( ) ) . toContain (
'fchopin (Frederic Chopin)' ,
) ;
} ) ;
} ) ;
} ) ;
2020-07-28 23:09:34 +05:30
describe ( 'buttons' , ( ) => {
describe ( '"Continue" button' , ( ) => {
it ( 'is shown' , ( ) => {
wrapper = mountComponent ( ) ;
2020-04-22 19:07:51 +05:30
2020-10-24 23:57:45 +05:30
expect ( getContinueButton ( ) . text ( ) ) . toBe ( 'Continue' ) ;
2020-07-28 23:09:34 +05:30
} ) ;
it ( 'is in loading state when the form is submitting' , async ( ) => {
wrapper = mountComponent ( { isSubmitting : true } ) ;
2020-04-22 19:07:51 +05:30
2020-10-24 23:57:45 +05:30
expect ( getContinueButton ( ) . props ( 'loading' ) ) . toBe ( true ) ;
2020-07-28 23:09:34 +05:30
} ) ;
2020-04-22 19:07:51 +05:30
} ) ;
2020-07-28 23:09:34 +05:30
describe ( '"Cancel" button' , ( ) => {
beforeEach ( ( ) => {
wrapper = mountComponent ( ) ;
} ) ;
2020-05-24 23:13:21 +05:30
2020-07-28 23:09:34 +05:30
it ( 'is shown' , ( ) => {
expect ( getCancelButton ( ) . text ( ) ) . toBe ( 'Cancel' ) ;
} ) ;
2020-04-22 19:07:51 +05:30
2020-07-28 23:09:34 +05:30
it ( 'links to the Issues page' , ( ) => {
expect ( getCancelButton ( ) . attributes ( 'href' ) ) . toBe ( issuesPath ) ;
} ) ;
} ) ;
2020-05-24 23:13:21 +05:30
} ) ;
2020-10-24 23:57:45 +05:30
describe ( 'submitting the form' , ( ) => {
it ( 'initiates the Jira import mutation with the expected arguments' , ( ) => {
2020-07-28 23:09:34 +05:30
wrapper = mountComponent ( ) ;
2020-04-22 19:07:51 +05:30
2020-10-24 23:57:45 +05:30
const mutationArguments = {
mutation : initiateJiraImportMutation ,
variables : {
input : {
jiraProjectKey : 'MTG' ,
projectPath ,
usersMapping : [
{
jiraAccountId : 'aei23f98f-q23fj98qfj' ,
gitlabId : 15 ,
} ,
{
jiraAccountId : 'fu39y8t34w-rq3u289t3h4i' ,
gitlabId : undefined ,
} ,
] ,
} ,
} ,
} ;
2020-07-28 23:09:34 +05:30
wrapper . find ( 'form' ) . trigger ( 'submit' ) ;
2020-04-22 19:07:51 +05:30
2020-10-24 23:57:45 +05:30
expect ( mutateSpy ) . toHaveBeenCalledWith ( expect . objectContaining ( mutationArguments ) ) ;
} ) ;
} ) ;
describe ( 'on mount GraphQL user mapping mutation' , ( ) => {
it ( 'is called with the expected arguments' , ( ) => {
wrapper = mountComponent ( ) ;
const mutationArguments = {
mutation : getJiraUserMappingMutation ,
variables : {
input : {
projectPath ,
startAt : 0 ,
} ,
} ,
} ;
expect ( mutateSpy ) . toHaveBeenCalledWith ( expect . objectContaining ( mutationArguments ) ) ;
} ) ;
describe ( 'when there is an error when called' , ( ) => {
beforeEach ( ( ) => {
const mutate = jest . fn ( ( ) => Promise . reject ( ) ) ;
wrapper = mountComponent ( { mutate } ) ;
} ) ;
it ( 'shows error message' , ( ) => {
expect ( getAlert ( ) . exists ( ) ) . toBe ( true ) ;
} ) ;
} ) ;
} ) ;
describe ( 'load more users button' , ( ) => {
describe ( 'when all users have been loaded' , ( ) => {
it ( 'is not shown' , ( ) => {
wrapper = mountComponent ( ) ;
expect ( findLoadMoreUsersButton ( ) . exists ( ) ) . toBe ( false ) ;
} ) ;
} ) ;
describe ( 'when all users have not been loaded' , ( ) => {
it ( 'is shown' , ( ) => {
wrapper = mountComponent ( { hasMoreUsers : true } ) ;
expect ( findLoadMoreUsersButton ( ) . exists ( ) ) . toBe ( true ) ;
} ) ;
} ) ;
describe ( 'when clicked' , ( ) => {
beforeEach ( ( ) => {
mutateSpy = jest . fn ( ( ) =>
Promise . resolve ( {
data : {
jiraImportStart : { errors : [ ] } ,
jiraImportUsers : { jiraUsers : jiraUsersResponse , errors : [ ] } ,
} ,
} ) ,
) ;
wrapper = mountComponent ( { hasMoreUsers : true } ) ;
} ) ;
it ( 'calls the GraphQL user mapping mutation' , async ( ) => {
const mutationArguments = {
mutation : getJiraUserMappingMutation ,
variables : {
input : {
projectPath ,
startAt : 0 ,
} ,
} ,
} ;
findLoadMoreUsersButton ( ) . vm . $emit ( 'click' ) ;
expect ( mutateSpy ) . toHaveBeenCalledWith ( expect . objectContaining ( mutationArguments ) ) ;
} ) ;
2020-07-28 23:09:34 +05:30
} ) ;
2020-04-22 19:07:51 +05:30
} ) ;
} ) ;