Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
e0d3a44f
Commit
e0d3a44f
authored
Nov 25, 2021
by
Simon Knox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve copy when no iteration found in sidebar
Changelog: changed EE: true
parent
e8ed8549
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
169 additions
and
285 deletions
+169
-285
app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
...avascripts/sidebar/components/sidebar_dropdown_widget.vue
+24
-45
app/assets/javascripts/sidebar/constants.js
app/assets/javascripts/sidebar/constants.js
+33
-0
ee/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
...avascripts/sidebar/components/sidebar_dropdown_widget.vue
+57
-14
ee/app/assets/javascripts/sidebar/constants.js
ee/app/assets/javascripts/sidebar/constants.js
+22
-1
ee/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
...ontend/sidebar/components/sidebar_dropdown_widget_spec.js
+22
-219
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
...ontend/sidebar/components/sidebar_dropdown_widget_spec.js
+8
-6
No files found.
app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
View file @
e0d3a44f
...
...
@@ -14,9 +14,10 @@ import createFlash from '~/flash';
import
{
getIdFromGraphQLId
}
from
'
~/graphql_shared/utils
'
;
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
{
timeFor
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
__
,
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
SidebarEditableItem
from
'
~/sidebar/components/sidebar_editable_item.vue
'
;
import
{
dropdowni18nText
,
Tracking
,
IssuableAttributeState
,
IssuableAttributeType
,
...
...
@@ -24,14 +25,11 @@ import {
noAttributeId
,
defaultEpicSort
,
epicIidPattern
,
}
from
'
~
/sidebar/constants
'
;
}
from
'
ee_else_ce
/sidebar/constants
'
;
export
default
{
noAttributeId
,
IssuableAttributeState
,
issuableAttributesQueries
,
i18n
:
{
[
IssuableAttributeType
.
Milestone
]:
__
(
'
Milestone
'
),
expired
:
__
(
'
(expired)
'
),
none
:
__
(
'
None
'
),
},
...
...
@@ -53,14 +51,24 @@ export default {
isClassicSidebar
:
{
default
:
false
,
},
issuableAttributesQueries
:
{
default
:
issuableAttributesQueries
,
},
issuableAttributesState
:
{
default
:
IssuableAttributeState
,
},
widgetTitleText
:
{
default
:
{
[
IssuableAttributeType
.
Milestone
]:
__
(
'
Milestone
'
),
expired
:
__
(
'
(expired)
'
),
none
:
__
(
'
None
'
),
},
},
},
props
:
{
issuableAttribute
:
{
type
:
String
,
required
:
true
,
validator
(
value
)
{
return
[
IssuableAttributeType
.
Milestone
].
includes
(
value
);
},
},
workspacePath
:
{
required
:
true
,
...
...
@@ -132,13 +140,13 @@ export default {
return
{
fullPath
:
this
.
attrWorkspacePath
,
title
:
this
.
searchTerm
,
state
:
this
.
$options
.
IssuableAttribute
State
[
this
.
issuableAttribute
],
state
:
this
.
issuableAttributes
State
[
this
.
issuableAttribute
],
};
}
const
variables
=
{
fullPath
:
this
.
attrWorkspacePath
,
state
:
this
.
$options
.
IssuableAttribute
State
[
this
.
issuableAttribute
],
state
:
this
.
issuableAttributes
State
[
this
.
issuableAttribute
],
sort
:
defaultEpicSort
,
};
...
...
@@ -180,7 +188,7 @@ export default {
},
computed
:
{
issuableAttributeQuery
()
{
return
this
.
$options
.
issuableAttributesQueries
[
this
.
issuableAttribute
];
return
this
.
issuableAttributesQueries
[
this
.
issuableAttribute
];
},
attributeTitle
()
{
return
this
.
currentAttribute
?.
title
||
this
.
i18n
.
noAttribute
;
...
...
@@ -189,9 +197,7 @@ export default {
return
this
.
currentAttribute
?.
webUrl
;
},
dropdownText
()
{
return
this
.
currentAttribute
?
this
.
currentAttribute
?.
title
:
this
.
$options
.
i18n
[
this
.
issuableAttribute
];
return
this
.
currentAttribute
?
this
.
currentAttribute
?.
title
:
this
.
attributeTypeTitle
;
},
loading
()
{
return
this
.
$apollo
.
queries
.
currentAttribute
.
loading
;
...
...
@@ -200,7 +206,7 @@ export default {
return
this
.
attributesList
.
length
===
0
;
},
attributeTypeTitle
()
{
return
this
.
$options
.
i18n
[
this
.
issuableAttribute
];
return
this
.
widgetTitleText
[
this
.
issuableAttribute
];
},
attributeTypeIcon
()
{
return
this
.
icon
||
this
.
issuableAttribute
;
...
...
@@ -209,37 +215,10 @@ export default {
return
timeFor
(
this
.
currentAttribute
?.
dueDate
);
},
i18n
()
{
return
{
noAttribute
:
sprintf
(
s__
(
'
DropdownWidget|No %{issuableAttribute}
'
),
{
issuableAttribute
:
this
.
issuableAttribute
,
}),
assignAttribute
:
sprintf
(
s__
(
'
DropdownWidget|Assign %{issuableAttribute}
'
),
{
issuableAttribute
:
this
.
issuableAttribute
,
}),
noAttributesFound
:
sprintf
(
s__
(
'
DropdownWidget|No %{issuableAttribute} found
'
),
{
issuableAttribute
:
this
.
issuableAttribute
,
}),
updateError
:
sprintf
(
s__
(
'
DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again.
'
,
),
{
issuableAttribute
:
this
.
issuableAttribute
,
issuableType
:
this
.
issuableType
},
),
listFetchError
:
sprintf
(
s__
(
'
DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again.
'
,
),
{
issuableAttribute
:
this
.
issuableAttribute
,
issuableType
:
this
.
issuableType
},
),
currentFetchError
:
sprintf
(
s__
(
'
DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}.
'
,
),
{
issuableAttribute
:
this
.
issuableAttribute
,
issuableType
:
this
.
issuableType
},
),
};
return
dropdowni18nText
(
this
.
issuableAttribute
,
this
.
issuableType
);
},
isEpic
()
{
// MV to EE https://gitlab.com/gitlab-org/gitlab/-/issues/345311
return
this
.
issuableAttribute
===
IssuableType
.
Epic
;
},
},
...
...
@@ -252,7 +231,7 @@ export default {
const
selectedAttribute
=
Boolean
(
attributeId
)
&&
this
.
attributesList
.
find
((
p
)
=>
p
.
id
===
attributeId
);
this
.
selectedTitle
=
selectedAttribute
?
selectedAttribute
.
title
:
this
.
$options
.
i18n
.
none
;
this
.
selectedTitle
=
selectedAttribute
?
selectedAttribute
.
title
:
this
.
widgetTitleText
.
none
;
const
{
current
}
=
this
.
issuableAttributeQuery
;
const
{
mutation
}
=
current
[
this
.
issuableType
];
...
...
app/assets/javascripts/sidebar/constants.js
View file @
e0d3a44f
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
updateIssueLabelsMutation
from
'
~/boards/graphql/issue_set_labels.mutation.graphql
'
;
import
{
IssuableType
,
WorkspaceType
}
from
'
~/issue_show/constants
'
;
import
{
DEFAULT_DEBOUNCE_AND_THROTTLE_MS
}
from
'
~/lib/utils/constants
'
;
...
...
@@ -272,3 +273,35 @@ export const todoMutations = {
[
TodoMutationTypes
.
Create
]:
todoCreateMutation
,
[
TodoMutationTypes
.
MarkDone
]:
todoMarkDoneMutation
,
};
export
function
dropdowni18nText
(
issuableAttribute
,
issuableType
)
{
return
{
noAttribute
:
sprintf
(
s__
(
'
DropdownWidget|No %{issuableAttribute}
'
),
{
issuableAttribute
,
}),
assignAttribute
:
sprintf
(
s__
(
'
DropdownWidget|Assign %{issuableAttribute}
'
),
{
issuableAttribute
,
}),
noAttributesFound
:
sprintf
(
s__
(
'
DropdownWidget|No %{issuableAttribute} found
'
),
{
issuableAttribute
,
}),
updateError
:
sprintf
(
s__
(
'
DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again.
'
,
),
{
issuableAttribute
,
issuableType
},
),
listFetchError
:
sprintf
(
s__
(
'
DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again.
'
,
),
{
issuableAttribute
,
issuableType
},
),
currentFetchError
:
sprintf
(
s__
(
'
DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}.
'
,
),
{
issuableAttribute
,
issuableType
},
),
};
}
ee/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
View file @
e0d3a44f
<
script
>
// This is a false violation of @gitlab/no-runtime-template-compiler, since it
// extends a valid Vue single file component.
/* eslint-disable @gitlab/no-runtime-template-compiler */
import
{
__
}
from
'
~/locale
'
;
import
SidebarDropdownWidgetFoss
from
'
~/sidebar/components/sidebar_dropdown_widget.vue
'
;
import
SidebarDropdownWidget
from
'
~/sidebar/components/sidebar_dropdown_widget.vue
'
;
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
{
IssuableAttributeState
,
IssuableAttributeType
,
IssuableAttributeState
,
issuableAttributesQueries
,
}
from
'
../constants
'
;
export
default
{
extends
:
SidebarDropdownWidgetFoss
,
IssuableAttributeState
,
issuableAttributesQueries
,
i18n
:
{
const
widgetTitleText
=
{
[
IssuableAttributeType
.
Milestone
]:
__
(
'
Milestone
'
),
[
IssuableAttributeType
.
Iteration
]:
__
(
'
Iteration
'
),
[
IssuableAttributeType
.
Epic
]:
__
(
'
Epic
'
),
none
:
__
(
'
None
'
),
expired
:
__
(
'
(expired)
'
),
};
export
default
{
components
:
{
SidebarDropdownWidget
},
provide
:
{
issuableAttributesQueries
,
widgetTitleText
,
issuableAttributesState
:
IssuableAttributeState
,
},
inheritAttrs
:
false
,
props
:
{
issuableAttribute
:
{
type
:
String
,
...
...
@@ -33,6 +36,46 @@ export default {
].
includes
(
value
);
},
},
workspacePath
:
{
required
:
true
,
type
:
String
,
},
iid
:
{
required
:
true
,
type
:
String
,
},
attrWorkspacePath
:
{
required
:
true
,
type
:
String
,
},
issuableType
:
{
type
:
String
,
required
:
true
,
validator
(
value
)
{
return
[
IssuableType
.
Issue
,
IssuableType
.
MergeRequest
].
includes
(
value
);
},
},
icon
:
{
type
:
String
,
required
:
false
,
default
:
undefined
,
},
},
};
</
script
>
<
template
>
<sidebar-dropdown-widget
:icon=
"icon"
:issuable-type=
"issuableType"
:attr-workspace-path=
"attrWorkspacePath"
:issuable-attribute=
"issuableAttribute"
:iid=
"iid"
:workspace-path=
"workspacePath"
v-bind=
"$attrs"
v-on=
"$listeners"
>
<template
v-for=
"(_, name) in $scopedSlots"
#[name]=
"slotData"
>
<slot
:name=
"name"
v-bind=
"slotData"
></slot>
</
template
>
</sidebar-dropdown-widget>
</template>
ee/app/assets/javascripts/sidebar/constants.js
View file @
e0d3a44f
import
{
IssuableType
}
from
'
~/issue_show/constants
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
{
__
,
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
IssuableAttributeType
as
IssuableAttributeTypeFoss
,
IssuableAttributeState
as
IssuableAttributeStateFoss
,
issuableAttributesQueries
as
issuableAttributesQueriesFoss
,
dropdowni18nText
as
dropdowni18nTextFoss
,
Tracking
,
defaultEpicSort
,
epicIidPattern
,
}
from
'
~/sidebar/constants
'
;
import
updateStatusMutation
from
'
~/sidebar/queries/updateStatus.mutation.graphql
'
;
import
epicAncestorsQuery
from
'
./queries/epic_ancestors.query.graphql
'
;
...
...
@@ -17,6 +21,8 @@ import projectIssueIterationMutation from './queries/project_issue_iteration.mut
import
projectIssueIterationQuery
from
'
./queries/project_issue_iteration.query.graphql
'
;
import
updateIssueWeightMutation
from
'
./queries/update_issue_weight.mutation.graphql
'
;
export
{
Tracking
,
defaultEpicSort
,
epicIidPattern
};
export
const
healthStatus
=
{
ON_TRACK
:
'
onTrack
'
,
NEEDS_ATTENTION
:
'
needsAttention
'
,
...
...
@@ -150,3 +156,18 @@ export const healthStatusQueries = {
query
:
issueHealthStatusQuery
,
},
};
export
function
dropdowni18nText
(
issuableAttribute
,
issuableType
)
{
let
noAttributesFound
=
s__
(
'
DropdownWidget|No %{issuableAttribute} found
'
);
if
(
issuableAttribute
===
IssuableAttributeType
.
Iteration
)
{
noAttributesFound
=
s__
(
'
DropdownWidget|No open %{issuableAttribute} found
'
);
}
return
{
...
dropdowni18nTextFoss
(
issuableAttribute
,
issuableType
),
noAttributesFound
:
sprintf
(
noAttributesFound
,
{
issuableAttribute
,
}),
};
}
ee/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
View file @
e0d3a44f
...
...
@@ -2,17 +2,15 @@ import {
GlDropdown
,
GlDropdownItem
,
GlDropdownText
,
GlLink
,
GlSearchBoxByType
,
GlFormInput
,
GlLoadingIcon
,
}
from
'
@gitlab/ui
'
;
import
*
as
Sentry
from
'
@sentry/browser
'
;
import
{
createLocalVue
,
shallowMount
,
mount
}
from
'
@vue/test-utils
'
;
import
{
createLocalVue
,
mount
}
from
'
@vue/test-utils
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
SidebarDropdownWidget
from
'
ee/sidebar/components/sidebar_dropdown_widget.vue
'
;
import
{
IssuableAttributeType
}
from
'
ee/sidebar/constants
'
;
import
{
IssuableAttributeType
,
issuableAttributesQueries
}
from
'
ee/sidebar/constants
'
;
import
groupEpicsQuery
from
'
ee/sidebar/queries/group_epics.query.graphql
'
;
import
projectIssueEpicMutation
from
'
ee/sidebar/queries/project_issue_epic.mutation.graphql
'
;
import
projectIssueEpicQuery
from
'
ee/sidebar/queries/project_issue_epic.query.graphql
'
;
...
...
@@ -41,18 +39,9 @@ describe('SidebarDropdownWidget', () => {
let
mockApollo
;
const
promiseData
=
{
issuableSetAttribute
:
{
issue
:
{
attribute
:
{
id
:
'
123
'
}
}
}
};
const
firstErrorMsg
=
'
first error
'
;
const
promiseWithErrors
=
{
...
promiseData
,
issuableSetAttribute
:
{
...
promiseData
.
issuableSetAttribute
,
errors
:
[
firstErrorMsg
]
},
};
const
mutationSuccess
=
()
=>
jest
.
fn
().
mockResolvedValue
({
data
:
promiseData
});
const
mutationError
=
()
=>
jest
.
fn
().
mockRejectedValue
(
'
Failed to set epic on this issue. Please try again.
'
);
const
mutationSuccessWithErrors
=
()
=>
jest
.
fn
().
mockResolvedValue
({
data
:
promiseWithErrors
});
const
findGlLink
=
()
=>
wrapper
.
findComponent
(
GlLink
);
const
findDropdown
=
()
=>
wrapper
.
findComponent
(
GlDropdown
);
const
findDropdownText
=
()
=>
wrapper
.
findComponent
(
GlDropdownText
);
const
findSearchBox
=
()
=>
wrapper
.
findComponent
(
GlSearchBoxByType
);
...
...
@@ -62,11 +51,7 @@ describe('SidebarDropdownWidget', () => {
const
findSidebarEditableItem
=
()
=>
wrapper
.
findComponent
(
SidebarEditableItem
);
const
findEditButton
=
()
=>
findSidebarEditableItem
().
find
(
'
[data-testid="edit-button"]
'
);
const
findEditableLoadingIcon
=
()
=>
findSidebarEditableItem
().
find
(
GlLoadingIcon
);
const
findAttributeItems
=
()
=>
wrapper
.
findByTestId
(
'
epic-items
'
);
const
findSelectedAttribute
=
()
=>
wrapper
.
findByTestId
(
'
select-epic
'
);
const
findNoAttributeItem
=
()
=>
wrapper
.
findByTestId
(
'
no-epic-item
'
);
const
findLoadingIconDropdown
=
()
=>
wrapper
.
findByTestId
(
'
loading-icon-dropdown
'
);
const
waitForDropdown
=
async
()
=>
{
// BDropdown first changes its `visible` property
...
...
@@ -94,7 +79,7 @@ describe('SidebarDropdownWidget', () => {
// Used with createComponent which shallow mounts components
const
toggleDropdown
=
async
()
=>
{
wrapper
.
vm
.
$refs
.
editable
.
expand
(
);
wrapper
.
find
(
SidebarEditableItem
).
vm
.
$emit
(
'
open
'
);
await
waitForDropdown
();
};
...
...
@@ -114,7 +99,7 @@ describe('SidebarDropdownWidget', () => {
wrapper
=
extendedWrapper
(
mount
(
SidebarDropdownWidget
,
{
localVue
,
provide
:
{
canUpdate
:
true
},
provide
:
{
canUpdate
:
true
,
issuableAttributesQueries
},
apolloProvider
:
mockApollo
,
propsData
:
{
workspacePath
:
mockIssue
.
projectPath
,
...
...
@@ -130,9 +115,14 @@ describe('SidebarDropdownWidget', () => {
await
waitForApollo
();
};
const
createComponent
=
({
data
=
{},
mutationPromise
=
mutationSuccess
,
queries
=
{}
}
=
{})
=>
{
const
createComponent
=
({
data
=
{},
issuableAttribute
=
IssuableAttributeType
.
Epic
,
mutationPromise
=
mutationSuccess
,
queries
=
{},
}
=
{})
=>
{
wrapper
=
extendedWrapper
(
shallowM
ount
(
SidebarDropdownWidget
,
{
m
ount
(
SidebarDropdownWidget
,
{
provide
:
{
canUpdate
:
true
},
data
()
{
return
data
;
...
...
@@ -142,7 +132,7 @@ describe('SidebarDropdownWidget', () => {
attrWorkspacePath
:
''
,
iid
:
''
,
issuableType
:
IssuableType
.
Issue
,
issuableAttribute
:
IssuableAttributeType
.
Epic
,
issuableAttribute
,
},
mocks
:
{
$apollo
:
{
...
...
@@ -164,7 +154,6 @@ describe('SidebarDropdownWidget', () => {
// We need to mock out `showDropdown` which
// invokes `show` method of BDropdown used inside GlDropdown.
jest
.
spyOn
(
wrapper
.
vm
,
'
showDropdown
'
).
mockImplementation
();
};
afterEach
(()
=>
{
...
...
@@ -172,194 +161,10 @@ describe('SidebarDropdownWidget', () => {
wrapper
=
null
;
});
describe
(
'
when not editing
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
data
:
{
currentAttribute
:
{
id
:
'
id
'
,
title
:
'
title
'
,
webUrl
:
'
webUrl
'
},
},
stubs
:
{
GlDropdown
,
SidebarEditableItem
,
},
});
});
it
(
'
shows the current attribute
'
,
()
=>
{
expect
(
findSelectedAttribute
().
text
()).
toBe
(
'
title
'
);
});
it
(
'
links to the current attribute
'
,
()
=>
{
expect
(
findGlLink
().
attributes
().
href
).
toBe
(
'
webUrl
'
);
});
it
(
'
does not show a loading spinner next to the heading
'
,
()
=>
{
expect
(
findEditableLoadingIcon
().
exists
()).
toBe
(
false
);
});
it
(
'
shows a loading spinner while fetching the current attribute
'
,
()
=>
{
createComponent
({
queries
:
{
currentAttribute
:
{
loading
:
true
},
},
});
expect
(
findEditableLoadingIcon
().
exists
()).
toBe
(
true
);
});
it
(
'
shows the loading spinner and the title of the selected attribute while updating
'
,
()
=>
{
createComponent
({
data
:
{
updating
:
true
,
selectedTitle
:
'
Some epic title
'
,
},
queries
:
{
currentAttribute
:
{
loading
:
false
},
},
});
expect
(
findEditableLoadingIcon
().
exists
()).
toBe
(
true
);
expect
(
findSelectedAttribute
().
text
()).
toBe
(
'
Some epic title
'
);
});
describe
(
'
when current attribute does not exist
'
,
()
=>
{
it
(
'
renders "None" as the selected attribute title
'
,
()
=>
{
createComponent
();
expect
(
findSelectedAttribute
().
text
()).
toBe
(
'
None
'
);
});
});
});
describe
(
'
when a user can edit
'
,
()
=>
{
describe
(
'
when user is editing
'
,
()
=>
{
describe
(
'
when rendering the dropdown
'
,
()
=>
{
it
(
'
shows a loading spinner while fetching a list of attributes
'
,
async
()
=>
{
createComponent
({
queries
:
{
attributesList
:
{
loading
:
true
},
},
});
await
toggleDropdown
();
expect
(
findLoadingIconDropdown
().
exists
()).
toBe
(
true
);
});
describe
(
'
GlDropdownItem with the right title and id
'
,
()
=>
{
const
id
=
'
id
'
;
const
title
=
'
title
'
;
beforeEach
(
async
()
=>
{
createComponent
({
data
:
{
attributesList
:
[{
id
,
title
}],
currentAttribute
:
{
id
,
title
}
},
});
await
toggleDropdown
();
});
it
(
'
does not show a loading spinner
'
,
()
=>
{
expect
(
findLoadingIconDropdown
().
exists
()).
toBe
(
false
);
});
it
(
'
renders title $title
'
,
()
=>
{
expect
(
findDropdownItemWithText
(
title
).
exists
()).
toBe
(
true
);
});
it
(
'
checks the correct dropdown item
'
,
()
=>
{
expect
(
findAllDropdownItems
()
.
filter
((
w
)
=>
w
.
props
(
'
isChecked
'
)
===
true
)
.
at
(
0
)
.
text
(),
).
toBe
(
title
);
});
});
describe
(
'
when no data is assigned
'
,
()
=>
{
beforeEach
(
async
()
=>
{
createComponent
();
await
toggleDropdown
();
});
it
(
'
finds GlDropdownItem with "No epic"
'
,
()
=>
{
expect
(
findNoAttributeItem
().
text
()).
toBe
(
'
No epic
'
);
});
it
(
'
"No epic" is checked
'
,
()
=>
{
expect
(
findNoAttributeItem
().
props
(
'
isChecked
'
)).
toBe
(
true
);
});
it
(
'
does not render any dropdown item
'
,
()
=>
{
expect
(
findAttributeItems
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
when clicking on dropdown item
'
,
()
=>
{
describe
(
'
when currentAttribute is equal to attribute id
'
,
()
=>
{
it
(
'
does not call setIssueAttribute mutation
'
,
async
()
=>
{
createComponent
({
data
:
{
attributesList
:
[{
id
:
'
id
'
,
title
:
'
title
'
}],
currentAttribute
:
{
id
:
'
id
'
,
title
:
'
title
'
},
},
});
await
toggleDropdown
();
findDropdownItemWithText
(
'
title
'
).
vm
.
$emit
(
'
click
'
);
expect
(
wrapper
.
vm
.
$apollo
.
mutate
).
toHaveBeenCalledTimes
(
0
);
});
});
describe
(
'
when currentAttribute is not equal to attribute id
'
,
()
=>
{
describe
(
'
when error
'
,
()
=>
{
const
bootstrapComponent
=
(
mutationResp
)
=>
{
createComponent
({
data
:
{
attributesList
:
[
{
id
:
'
123
'
,
title
:
'
123
'
},
{
id
:
'
id
'
,
title
:
'
title
'
},
],
currentAttribute
:
'
123
'
,
},
mutationPromise
:
mutationResp
,
});
};
describe
.
each
`
description | mutationResp | expectedMsg
${
'
top-level error
'
}
|
${
mutationError
}
|
${
'
Failed to set epic on this issue. Please try again.
'
}
${
'
user-recoverable error
'
}
|
${
mutationSuccessWithErrors
}
|
${
firstErrorMsg
}
`
(
`$description`
,
({
mutationResp
,
expectedMsg
})
=>
{
beforeEach
(
async
()
=>
{
bootstrapComponent
(
mutationResp
);
await
toggleDropdown
();
findDropdownItemWithText
(
'
title
'
).
vm
.
$emit
(
'
click
'
);
});
it
(
`calls createFlash with "
${
expectedMsg
}
"`
,
async
()
=>
{
await
wrapper
.
vm
.
$nextTick
();
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
expectedMsg
,
captureError
:
true
,
error
:
expectedMsg
,
});
});
});
});
});
});
});
describe
(
'
when a user is searching
'
,
()
=>
{
describe
(
'
when search result is not found
'
,
()
=>
{
it
(
'
renders "No epic
found"
'
,
async
()
=>
{
createComponent
(
);
it
(
'
renders "No open iteration
found"
'
,
async
()
=>
{
createComponent
({
issuableAttribute
:
IssuableAttributeType
.
Iteration
}
);
await
toggleDropdown
();
...
...
@@ -367,9 +172,7 @@ describe('SidebarDropdownWidget', () => {
await
wrapper
.
vm
.
$nextTick
();
expect
(
findDropdownText
().
text
()).
toBe
(
'
No epic found
'
);
});
});
expect
(
findDropdownText
().
text
()).
toBe
(
'
No open iteration found
'
);
});
});
});
...
...
@@ -434,7 +237,7 @@ describe('SidebarDropdownWidget', () => {
await
clickEdit
();
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
wrapper
.
vm
.
i18n
.
listFetchError
,
message
:
'
Failed to fetch the epic for this issue. Please try again.
'
,
captureError
:
true
,
error
:
expect
.
any
(
Error
),
});
...
...
@@ -528,7 +331,7 @@ describe('SidebarDropdownWidget', () => {
});
expect
(
createFlash
).
toHaveBeenCalledWith
({
message
:
wrapper
.
vm
.
i18n
.
currentFetchError
,
message
:
'
An error occurred while fetching the assigned epic of the selected issue.
'
,
captureError
:
true
,
error
:
expect
.
any
(
Error
),
});
...
...
locale/gitlab.pot
View file @
e0d3a44f
...
...
@@ -12482,6 +12482,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
msgid "DropdownWidget|No open %{issuableAttribute} found"
msgstr ""
msgid "Due Date"
msgstr ""
...
...
spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
View file @
e0d3a44f
...
...
@@ -369,6 +369,7 @@ describe('SidebarDropdownWidget', () => {
describe
(
'
when a user is searching
'
,
()
=>
{
describe
(
'
when search result is not found
'
,
()
=>
{
describe
(
'
when milestone
'
,
()
=>
{
it
(
'
renders "No milestone found"
'
,
async
()
=>
{
createComponent
();
...
...
@@ -384,6 +385,7 @@ describe('SidebarDropdownWidget', () => {
});
});
});
});
describe
(
'
with mock apollo
'
,
()
=>
{
let
error
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment