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
b38c9bd2
Commit
b38c9bd2
authored
Apr 30, 2020
by
Florie Guibert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Consolidate epic tree buttons
Merge Add issue and epic buttons on epic tree
parent
72ec0a48
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
174 additions
and
303 deletions
+174
-303
doc/user/group/epics/img/epic_view_v12.3.png
doc/user/group/epics/img/epic_view_v12.3.png
+0
-0
doc/user/group/epics/img/epic_view_v13.0.png
doc/user/group/epics/img/epic_view_v13.0.png
+0
-0
doc/user/group/epics/index.md
doc/user/group/epics/index.md
+4
-2
ee/app/assets/javascripts/related_items_tree/components/epic_actions_split_button.vue
...lated_items_tree/components/epic_actions_split_button.vue
+0
-43
ee/app/assets/javascripts/related_items_tree/components/epic_issue_actions_split_button.vue
...items_tree/components/epic_issue_actions_split_button.vue
+85
-0
ee/app/assets/javascripts/related_items_tree/components/issue_actions_split_button.vue
...ated_items_tree/components/issue_actions_split_button.vue
+0
-44
ee/app/assets/javascripts/related_items_tree/components/related_items_tree_app.vue
.../related_items_tree/components/related_items_tree_app.vue
+1
-18
ee/app/assets/javascripts/related_items_tree/components/related_items_tree_header.vue
...lated_items_tree/components/related_items_tree_header.vue
+20
-20
ee/changelogs/unreleased/214419-consolidate-epic-tree-buttons-add-create-epics-and-issues.yml
...olidate-epic-tree-buttons-add-create-epics-and-issues.yml
+5
-0
ee/spec/features/epics/epic_issues_spec.rb
ee/spec/features/epics/epic_issues_spec.rb
+12
-8
ee/spec/frontend/related_items_tree/components/related_items_tree_app_spec.js
...ated_items_tree/components/related_items_tree_app_spec.js
+0
-77
ee/spec/frontend/related_items_tree/components/related_items_tree_header_spec.js
...d_items_tree/components/related_items_tree_header_spec.js
+44
-88
qa/qa/ee/page/group/epic/show.rb
qa/qa/ee/page/group/epic/show.rb
+3
-3
No files found.
doc/user/group/epics/img/epic_view_v12.3.png
deleted
100644 → 0
View file @
72ec0a48
60 KB
doc/user/group/epics/img/epic_view_v13.0.png
0 → 100644
View file @
b38c9bd2
67.2 KB
doc/user/group/epics/index.md
View file @
b38c9bd2
...
...
@@ -58,7 +58,7 @@ An epic's page contains the following tabs:
-
Hover over the total counts to see a breakdown of open and closed items.
-
**Roadmap**
: a roadmap view of child epics which have start and due dates.
![
epic view
](
img/epic_view_v1
2.3
.png
)
![
epic view
](
img/epic_view_v1
3.0
.png
)
## Adding an issue to an epic
...
...
@@ -75,6 +75,7 @@ the issue is automatically unlinked from its current parent.
To add an issue to an epic:
1.
Click the
**Add**
dropdown button.
1.
Click
**Add an issue**
.
1.
Identify the issue to be added, using either of the following methods:
-
Paste the link of the issue.
...
...
@@ -91,7 +92,7 @@ Creating an issue from an epic enables you to maintain focus on the broader cont
To create an issue from an epic:
1.
On the epic's page, under
**Epics and Issues**
, click the
arrow next to
**Add an issue**
and select
**Create new issue**
.
1.
On the epic's page, under
**Epics and Issues**
, click the
**Add**
dropdown button
and select
**Create new issue**
.
1.
Under
**Title**
, enter the title for the new issue.
1.
From the
**Project**
dropdown, select the project in which the issue should be created.
1.
Click
**Create issue**
.
...
...
@@ -128,6 +129,7 @@ the maximum depth being 5.
To add a child epic to an epic:
1.
Click the
**Add**
dropdown button.
1.
Click
**Add an epic**
.
1.
Identify the epic to be added, using either of the following methods:
-
Paste the link of the epic.
...
...
ee/app/assets/javascripts/related_items_tree/components/epic_actions_split_button.vue
deleted
100644 → 0
View file @
72ec0a48
<
script
>
import
SplitButton
from
'
~/vue_shared/components/split_button.vue
'
;
import
{
s__
}
from
'
~/locale
'
;
const
actionItems
=
[
{
title
:
s__
(
'
Epics|Add an epic
'
),
description
:
s__
(
'
Epics|Add an existing epic as a child epic.
'
),
eventName
:
'
showAddEpicForm
'
,
},
{
title
:
s__
(
'
Epics|Create new epic
'
),
description
:
s__
(
'
Epics|Create an epic within this group and add it as a child epic.
'
),
eventName
:
'
showCreateEpicForm
'
,
},
];
export
default
{
actionItems
,
components
:
{
SplitButton
,
},
methods
:
{
change
(
item
)
{
this
.
$emit
(
item
.
eventName
);
},
},
};
</
script
>
<
template
>
<split-button
:action-items=
"$options.actionItems"
class=
"js-add-epics-button"
menu-class=
"dropdown-menu-large"
right
size=
"sm"
v-on=
"$listeners"
@
change=
"change"
/>
</
template
>
ee/app/assets/javascripts/related_items_tree/components/epic_issue_actions_split_button.vue
0 → 100644
View file @
b38c9bd2
<
script
>
import
{
GlDropdown
,
GlDropdownDivider
,
GlDropdownHeader
,
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
s__
}
from
'
~/locale
'
;
const
epicActionItems
=
[
{
title
:
s__
(
'
Epics|Add an epic
'
),
description
:
s__
(
'
Epics|Add an existing epic as a child epic.
'
),
eventName
:
'
showAddEpicForm
'
,
},
{
title
:
s__
(
'
Epics|Create new epic
'
),
description
:
s__
(
'
Epics|Create an epic within this group and add it as a child epic.
'
),
eventName
:
'
showCreateEpicForm
'
,
},
];
const
issueActionItems
=
[
{
title
:
s__
(
'
Add an issue
'
),
description
:
s__
(
'
Add an existing issue to the epic.
'
),
eventName
:
'
showAddIssueForm
'
,
},
{
title
:
s__
(
'
Create an issue
'
),
description
:
s__
(
'
Create a new issue and add it to the epic.
'
),
eventName
:
'
showCreateIssueForm
'
,
},
];
export
default
{
epicActionItems
,
issueActionItems
,
components
:
{
GlDropdown
,
GlDropdownDivider
,
GlDropdownHeader
,
GlDropdownItem
,
},
props
:
{
allowSubEpics
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
actionItems
()
{
return
this
.
allowSubEpics
?
[...
epicActionItems
,
...
issueActionItems
]
:
issueActionItems
;
},
},
methods
:
{
change
(
item
)
{
this
.
$emit
(
item
.
eventName
);
},
},
};
</
script
>
<
template
>
<gl-dropdown
:menu-class=
"`dropdown-menu-selectable`"
:text=
"s__('Add')"
variant=
"secondary"
data-qa-selector=
"epic_issue_actions_split_button"
v-on=
"$listeners"
>
<gl-dropdown-header>
{{
s__
(
'
Issue
'
)
}}
</gl-dropdown-header>
<template
v-for=
"item in $options.issueActionItems"
>
<gl-dropdown-item
:key=
"item.eventName"
active-class=
"is-active"
@
click=
"change(item)"
>
{{
item
.
title
}}
</gl-dropdown-item>
</
template
>
<
template
v-if=
"allowSubEpics"
>
<gl-dropdown-divider
/>
<gl-dropdown-header>
{{
s__
(
'
Epic
'
)
}}
</gl-dropdown-header>
<template
v-for=
"item in $options.epicActionItems"
>
<gl-dropdown-item
:key=
"item.eventName"
active-class=
"is-active"
@
click=
"change(item)"
>
{{
item
.
title
}}
</gl-dropdown-item>
</
template
>
</template>
</gl-dropdown>
</template>
ee/app/assets/javascripts/related_items_tree/components/issue_actions_split_button.vue
deleted
100644 → 0
View file @
72ec0a48
<
script
>
import
SplitButton
from
'
~/vue_shared/components/split_button.vue
'
;
import
{
__
}
from
'
~/locale
'
;
const
actionItems
=
[
{
title
:
__
(
'
Add an issue
'
),
description
:
__
(
'
Add an existing issue to the epic.
'
),
eventName
:
'
showAddIssueForm
'
,
},
{
title
:
__
(
'
Create an issue
'
),
description
:
__
(
'
Create a new issue and add it to the epic.
'
),
eventName
:
'
showCreateIssueForm
'
,
},
];
export
default
{
actionItems
,
components
:
{
SplitButton
,
},
methods
:
{
change
(
item
)
{
this
.
$emit
(
item
.
eventName
);
},
},
};
</
script
>
<
template
>
<split-button
:action-items=
"$options.actionItems"
class=
"js-issue-actions-split-button"
data-qa-selector=
"issue_actions_split_button"
menu-class=
"dropdown-menu-large"
right
size=
"sm"
v-on=
"$listeners"
@
change=
"change"
/>
</
template
>
ee/app/assets/javascripts/related_items_tree/components/related_items_tree_app.vue
View file @
b38c9bd2
...
...
@@ -3,13 +3,10 @@ import { mapState, mapActions, mapGetters } from 'vuex';
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
{
issuableTypesMap
}
from
'
ee/related_issues/constants
'
;
import
AddItemForm
from
'
ee/related_issues/components/add_issuable_form.vue
'
;
import
SlotSwitch
from
'
~/vue_shared/components/slot_switch.vue
'
;
import
CreateEpicForm
from
'
./create_epic_form.vue
'
;
import
CreateIssueForm
from
'
./create_issue_form.vue
'
;
import
IssueActionsSplitButton
from
'
./issue_actions_split_button.vue
'
;
import
TreeItemRemoveModal
from
'
./tree_item_remove_modal.vue
'
;
import
RelatedItemsTreeHeader
from
'
./related_items_tree_header.vue
'
;
...
...
@@ -34,7 +31,6 @@ export default {
CreateEpicForm
,
TreeItemRemoveModal
,
CreateIssueForm
,
IssueActionsSplitButton
,
SlotSwitch
,
},
computed
:
{
...
...
@@ -133,12 +129,6 @@ export default {
this
.
toggleCreateEpicForm
({
toggleState
:
false
});
this
.
setItemInputValue
(
''
);
},
handleShowAddIssueForm
()
{
this
.
toggleAddItemForm
({
toggleState
:
true
,
issuableType
:
issuableTypesMap
.
ISSUE
});
},
handleShowCreateIssueForm
()
{
this
.
toggleCreateIssueForm
({
toggleState
:
true
});
},
},
};
</
script
>
...
...
@@ -156,14 +146,7 @@ export default {
'overflow-auto': directChildren.length > $options.OVERFLOW_AFTER,
}"
>
<related-items-tree-header
:class=
"
{ 'border-bottom-0': itemsFetchResultEmpty }">
<issue-actions-split-button
slot=
"issueActions"
class=
"ml-0 ml-sm-1"
@
showAddIssueForm=
"handleShowAddIssueForm"
@
showCreateIssueForm=
"handleShowCreateIssueForm"
/>
</related-items-tree-header>
<related-items-tree-header
:class=
"
{ 'border-bottom-0': itemsFetchResultEmpty }" />
<slot-switch
v-if=
"visibleForm"
:active-slot-names=
"[visibleForm]"
...
...
ee/app/assets/javascripts/related_items_tree/components/related_items_tree_header.vue
View file @
b38c9bd2
<
script
>
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
Gl
DeprecatedButton
,
Gl
Tooltip
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
GlTooltip
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
issuableTypesMap
}
from
'
ee/related_issues/constants
'
;
import
EpicActionsSplitButton
from
'
./epic_actions_split_button.vue
'
;
import
EpicActionsSplitButton
from
'
./epic_
issue_
actions_split_button.vue
'
;
import
EpicHealthStatus
from
'
./epic_health_status.vue
'
;
export
default
{
components
:
{
GlDeprecatedButton
,
GlTooltip
,
GlIcon
,
EpicHealthStatus
,
...
...
@@ -26,17 +25,25 @@ export default {
},
},
methods
:
{
...
mapActions
([
'
toggleAddItemForm
'
,
'
toggleCreateEpicForm
'
,
'
setItemInputValue
'
]),
showAddEpicForm
()
{
...
mapActions
([
'
toggleCreateIssueForm
'
,
'
toggleAddItemForm
'
,
'
toggleCreateEpicForm
'
,
'
setItemInputValue
'
,
]),
showAddIssueForm
()
{
this
.
setItemInputValue
(
''
);
this
.
toggleAddItemForm
({
issuableType
:
issuableTypesMap
.
EPIC
,
issuableType
:
issuableTypesMap
.
ISSUE
,
toggleState
:
true
,
});
},
showAddIssueForm
()
{
this
.
setItemInputValue
(
''
);
showCreateIssueForm
()
{
this
.
toggleCreateIssueForm
({
toggleState
:
true
});
},
showAddEpicForm
()
{
this
.
toggleAddItemForm
({
issuableType
:
issuableTypesMap
.
ISSUE
,
issuableType
:
issuableTypesMap
.
EPIC
,
toggleState
:
true
,
});
},
...
...
@@ -91,20 +98,13 @@ export default {
<
div
class
=
"
d-inline-flex flex-column flex-sm-row js-button-container
"
>
<
template
v
-
if
=
"
parentItem.userPermissions.adminEpic
"
>
<
epic
-
actions
-
split
-
button
v
-
if
=
"
allowSubEpics
"
class
=
"
qa-add-epics-button mb-2 mb-sm-0
"
:
allow
-
sub
-
epics
=
"
allowSubEpics
"
class
=
"
js-add-epics-issues-button qa-add-epics-button mb-2 mb-sm-0
"
@
showAddIssueForm
=
"
showAddIssueForm
"
@
showCreateIssueForm
=
"
showCreateIssueForm
"
@
showAddEpicForm
=
"
showAddEpicForm
"
@
showCreateEpicForm
=
"
showCreateEpicForm
"
/>
<
slot
name
=
"
issueActions
"
>
<
gl
-
deprecated
-
button
class
=
"
ml-1 js-add-issues-button qa-add-issues-button
"
size
=
"
sm
"
@
click
=
"
showAddIssueForm
"
>
{{
__
(
'
Add an issue
'
)
}}
<
/gl-deprecated-butto
n
>
<
/slot
>
<
/template
>
<
/div
>
<
/div
>
...
...
ee/changelogs/unreleased/214419-consolidate-epic-tree-buttons-add-create-epics-and-issues.yml
0 → 100644
View file @
b38c9bd2
---
title
:
Consolidate epic tree buttons
merge_request
:
30816
author
:
type
:
changed
ee/spec/features/epics/epic_issues_spec.rb
View file @
b38c9bd2
...
...
@@ -60,7 +60,7 @@ describe 'Epic Issues', :js do
end
it
'user cannot add new epics to the epic'
do
expect
(
page
).
not_to
have_selector
(
'.related-items-tree-container .js-add-epics-button'
)
expect
(
page
).
not_to
have_selector
(
'.related-items-tree-container .js-add-epics-
issues-
button'
)
end
end
...
...
@@ -69,8 +69,9 @@ describe 'Epic Issues', :js do
let
(
:issue_invalid
)
{
create
(
:issue
)
}
let
(
:epic_to_add
)
{
create
(
:epic
,
group:
group
)
}
def
add_issues
(
references
,
button_selector:
'.js-issue-actions-split-button > button:first-child'
)
find
(
".related-items-tree-container
#{
button_selector
}
"
).
click
def
add_issues
(
references
)
find
(
".related-items-tree-container .js-add-epics-issues-button"
).
click
find
(
'.related-items-tree-container .js-add-epics-issues-button .dropdown-item'
,
text:
'Add an issue'
).
click
find
(
'.related-items-tree-container .js-add-issuable-form-input'
).
set
(
references
)
# When adding long references, for some reason the input gets stuck
# waiting for more text. Send a keystroke before clicking the button to
...
...
@@ -82,7 +83,8 @@ describe 'Epic Issues', :js do
end
def
add_epics
(
references
)
find
(
'.related-items-tree-container .js-add-epics-button'
).
click
find
(
'.related-items-tree-container .js-add-epics-issues-button'
).
click
find
(
'.related-items-tree-container .js-add-epics-issues-button .dropdown-item'
,
text:
'Add an epic'
).
click
find
(
'.related-items-tree-container .js-add-issuable-form-input'
).
set
(
references
)
find
(
'.related-items-tree-container .js-add-issuable-form-input'
).
send_keys
(
:tab
)
...
...
@@ -100,8 +102,8 @@ describe 'Epic Issues', :js do
it
'user can display create new epic form by clicking the dropdown item'
do
expect
(
page
).
not_to
have_selector
(
'input[placeholder="New epic title"]'
)
find
(
'.related-items-tree-container .js-add-epics-button .dropdown-toggle'
).
click
find
(
'.related-items-tree-container .js-add-epics-button .dropdown-item'
,
text:
'Create new epic'
).
click
find
(
'.related-items-tree-container .js-add-epics-
issues-
button .dropdown-toggle'
).
click
find
(
'.related-items-tree-container .js-add-epics-
issues-
button .dropdown-item'
,
text:
'Create new epic'
).
click
expect
(
page
).
to
have_selector
(
'input[placeholder="New epic title"]'
)
end
...
...
@@ -222,8 +224,10 @@ describe 'Epic Issues', :js do
stub_licensed_features
(
epics:
true
,
subepics:
false
)
visit_epic
find
(
'.related-items-tree-container .js-add-epics-issues-button'
).
click
expect
(
page
).
not_to
have_selector
(
'.related-items-tree-container .js-add-epics-button'
)
expect
(
page
).
not_to
have_selector
(
'.related-items-tree-container .js-add-epics-issues-button .dropdown-item'
,
text:
'Add an epic'
)
expect
(
page
).
not_to
have_selector
(
'.related-items-tree-container .js-add-epics-issues-button .dropdown-item'
,
text:
'Create new epic'
)
end
end
end
...
...
@@ -231,7 +235,7 @@ describe 'Epic Issues', :js do
it
'user can add new issues to the epic'
do
references
=
"
#{
issue_to_add
.
to_reference
(
full:
true
)
}
"
add_issues
(
references
,
button_selector:
'.js-issue-actions-split-button'
)
add_issues
(
references
)
expect
(
page
).
not_to
have_selector
(
'.gl-field-error'
)
expect
(
page
).
not_to
have_content
(
"Issue cannot be found."
)
...
...
ee/spec/frontend/related_items_tree/components/related_items_tree_app_spec.js
View file @
b38c9bd2
...
...
@@ -6,10 +6,7 @@ import RelatedItemsTreeApp from 'ee/related_items_tree/components/related_items_
import
RelatedItemsTreeHeader
from
'
ee/related_items_tree/components/related_items_tree_header.vue
'
;
import
createDefaultStore
from
'
ee/related_items_tree/store
'
;
import
{
issuableTypesMap
}
from
'
ee/related_issues/constants
'
;
import
AddItemForm
from
'
ee/related_issues/components/add_issuable_form.vue
'
;
import
CreateIssueForm
from
'
ee/related_items_tree/components/create_issue_form.vue
'
;
import
IssueActionsSplitButton
from
'
ee/related_items_tree/components/issue_actions_split_button.vue
'
;
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
import
AxiosMockAdapter
from
'
axios-mock-adapter
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
{
getJSONFixture
}
from
'
helpers/fixtures
'
;
...
...
@@ -41,12 +38,7 @@ describe('RelatedItemsTreeApp', () => {
let
axiosMock
;
let
wrapper
;
const
findAddItemForm
=
()
=>
wrapper
.
find
(
AddItemForm
);
const
findCreateIssueForm
=
()
=>
wrapper
.
find
(
CreateIssueForm
);
const
findIssueActionsSplitButton
=
()
=>
wrapper
.
find
(
IssueActionsSplitButton
);
const
showCreateIssueForm
=
()
=>
{
findIssueActionsSplitButton
().
vm
.
$emit
(
'
showCreateIssueForm
'
);
};
beforeEach
(()
=>
{
axiosMock
=
new
AxiosMockAdapter
(
axios
);
...
...
@@ -249,73 +241,4 @@ describe('RelatedItemsTreeApp', () => {
expect
(
findCreateIssueForm
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
issue actions split button
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
();
wrapper
.
vm
.
$store
.
state
.
itemsFetchInProgress
=
false
;
return
wrapper
.
vm
.
$nextTick
();
});
it
(
'
renders issue actions split button
'
,
()
=>
{
expect
(
findIssueActionsSplitButton
().
exists
()).
toBe
(
true
);
});
describe
(
'
after split button emitted showAddIssueForm event
'
,
()
=>
{
it
(
'
shows add item form
'
,
()
=>
{
expect
(
findAddItemForm
().
exists
()).
toBe
(
false
);
findIssueActionsSplitButton
().
vm
.
$emit
(
'
showAddIssueForm
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
findAddItemForm
().
exists
()).
toBe
(
true
);
});
});
});
describe
(
'
after split button emitted showCreateIssueForm event
'
,
()
=>
{
it
(
'
shows create item form
'
,
()
=>
{
expect
(
findCreateIssueForm
().
exists
()).
toBe
(
false
);
showCreateIssueForm
();
return
wrapper
.
vm
.
$nextTick
(()
=>
{
expect
(
findCreateIssueForm
().
exists
()).
toBe
(
true
);
});
});
});
describe
(
'
after create issue form emitted cancel event
'
,
()
=>
{
beforeEach
(()
=>
showCreateIssueForm
());
it
(
'
hides the form
'
,
()
=>
{
expect
(
findCreateIssueForm
().
exists
()).
toBe
(
true
);
findCreateIssueForm
().
vm
.
$emit
(
'
cancel
'
);
return
wrapper
.
vm
.
$nextTick
().
then
(()
=>
{
expect
(
findCreateIssueForm
().
exists
()).
toBe
(
false
);
});
});
});
describe
(
'
after create issue form emitted submit event
'
,
()
=>
{
beforeEach
(()
=>
showCreateIssueForm
());
it
(
'
dispatches createNewIssue action
'
,
()
=>
{
const
issuesEndpoint
=
`
${
TEST_HOST
}
/issues`
;
axiosMock
.
onPost
(
issuesEndpoint
).
replyOnce
(
200
,
{});
const
params
=
{
issuesEndpoint
,
title
:
'
some new issue
'
,
};
findCreateIssueForm
().
vm
.
$emit
(
'
submit
'
,
params
);
return
axios
.
waitFor
(
issuesEndpoint
).
then
(({
data
})
=>
{
expect
(
JSON
.
parse
(
data
).
title
).
toBe
(
params
.
title
);
});
});
});
});
});
ee/spec/frontend/related_items_tree/components/related_items_tree_header_spec.js
View file @
b38c9bd2
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vuex
from
'
vuex
'
;
import
{
Gl
DeprecatedButton
,
Gl
Tooltip
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
{
GlTooltip
,
GlIcon
}
from
'
@gitlab/ui
'
;
import
RelatedItemsTreeHeader
from
'
ee/related_items_tree/components/related_items_tree_header.vue
'
;
import
createDefaultStore
from
'
ee/related_items_tree/store
'
;
import
*
as
epicUtils
from
'
ee/related_items_tree/utils/epic_utils
'
;
import
{
issuableTypesMap
}
from
'
ee/related_issues/constants
'
;
import
EpicActionsSplitButton
from
'
ee/related_items_tree/components/epic_actions_split_button.vue
'
;
import
EpicActionsSplitButton
from
'
ee/related_items_tree/components/epic_
issue_
actions_split_button.vue
'
;
import
{
mockInitialConfig
,
mockParentItem
,
mockQueryResponse
}
from
'
../mock_data
'
;
...
...
@@ -41,8 +41,7 @@ describe('RelatedItemsTree', () => {
describe
(
'
RelatedItemsTreeHeader
'
,
()
=>
{
let
wrapper
;
const
findAddIssuesButton
=
()
=>
wrapper
.
find
(
GlDeprecatedButton
);
const
findEpicsSplitButton
=
()
=>
wrapper
.
find
(
EpicActionsSplitButton
);
const
findEpicsIssuesSplitButton
=
()
=>
wrapper
.
find
(
EpicActionsSplitButton
);
afterEach
(()
=>
{
wrapper
.
destroy
();
...
...
@@ -64,7 +63,7 @@ describe('RelatedItemsTree', () => {
});
});
describe
(
'
epic actions split button
'
,
()
=>
{
describe
(
'
epic
issue
actions split button
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
();
});
...
...
@@ -82,7 +81,7 @@ describe('RelatedItemsTree', () => {
});
it
(
'
dispatches toggleAddItemForm action
'
,
()
=>
{
findEpicsSplitButton
().
vm
.
$emit
(
'
showAddEpicForm
'
);
findEpics
Issues
SplitButton
().
vm
.
$emit
(
'
showAddEpicForm
'
);
expect
(
toggleAddItemForm
).
toHaveBeenCalled
();
...
...
@@ -108,7 +107,7 @@ describe('RelatedItemsTree', () => {
});
it
(
'
dispatches toggleCreateEpicForm action
'
,
()
=>
{
findEpicsSplitButton
().
vm
.
$emit
(
'
showCreateEpicForm
'
);
findEpics
Issues
SplitButton
().
vm
.
$emit
(
'
showCreateEpicForm
'
);
expect
(
toggleCreateEpicForm
).
toHaveBeenCalled
();
...
...
@@ -118,38 +117,28 @@ describe('RelatedItemsTree', () => {
expect
(
payload
).
toEqual
({
toggleState
:
true
});
});
});
});
describe
(
'
add issues button
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
();
});
describe
(
'
click event
'
,
()
=>
{
describe
(
'
showAddIssueForm event
'
,
()
=>
{
let
toggleAddItemForm
;
let
setItemInputValue
;
beforeEach
(()
=>
{
setItemInputValue
=
jest
.
fn
();
toggleAddItemForm
=
jest
.
fn
();
setItemInputValue
=
jest
.
fn
();
wrapper
.
vm
.
$store
.
hotUpdate
({
actions
:
{
setItemInputValue
,
toggleAddItemForm
,
setItemInputValue
,
},
});
});
it
(
'
dispatches setItemInputValue and toggleAddItemForm action
'
,
()
=>
{
findAddIssuesButton
().
vm
.
$emit
(
'
click
'
);
expect
(
setItemInputValue
).
toHaveBeenCalled
();
expect
(
setItemInputValue
.
mock
.
calls
[
setItemInputValue
.
mock
.
calls
.
length
-
1
][
1
]).
toBe
(
''
);
it
(
'
dispatches toggleAddItemForm action
'
,
()
=>
{
findEpicsIssuesSplitButton
().
vm
.
$emit
(
'
showAddIssueForm
'
);
expect
(
toggleAddItemForm
).
toHaveBeenCalled
();
const
payload
=
toggleAddItemForm
.
mock
.
calls
[
setItemInputValue
.
mock
.
calls
.
length
-
1
][
1
];
const
payload
=
toggleAddItemForm
.
mock
.
calls
[
0
][
1
];
expect
(
payload
).
toEqual
({
issuableType
:
issuableTypesMap
.
ISSUE
,
...
...
@@ -157,6 +146,30 @@ describe('RelatedItemsTree', () => {
});
});
});
describe
(
'
showCreateIssueForm event
'
,
()
=>
{
let
toggleCreateIssueForm
;
beforeEach
(()
=>
{
toggleCreateIssueForm
=
jest
.
fn
();
wrapper
.
vm
.
$store
.
hotUpdate
({
actions
:
{
toggleCreateIssueForm
,
},
});
});
it
(
'
dispatches toggleCreateIssueForm action
'
,
()
=>
{
findEpicsIssuesSplitButton
().
vm
.
$emit
(
'
showCreateIssueForm
'
);
expect
(
toggleCreateIssueForm
).
toHaveBeenCalled
();
const
payload
=
toggleCreateIssueForm
.
mock
.
calls
[
toggleCreateIssueForm
.
mock
.
calls
.
length
-
1
][
1
];
expect
(
payload
).
toEqual
({
toggleState
:
true
});
});
});
});
describe
(
'
template
'
,
()
=>
{
...
...
@@ -170,42 +183,17 @@ describe('RelatedItemsTree', () => {
expect
(
badgesContainerEl
.
isVisible
()).
toBe
(
true
);
});
describe
(
'
when sub-epics feature is available
'
,
()
=>
{
it
(
'
renders epics count and gl-icon
'
,
()
=>
{
const
epicsEl
=
wrapper
.
findAll
(
'
.issue-count-badge > span
'
).
at
(
0
);
const
epicIcon
=
epicsEl
.
find
(
GlIcon
);
expect
(
epicsEl
.
text
().
trim
()).
toContain
(
'
2
'
);
expect
(
epicIcon
.
isVisible
()).
toBe
(
true
);
expect
(
epicIcon
.
props
(
'
name
'
)).
toBe
(
'
epic
'
);
});
it
(
'
renders epics count and gl-icon
'
,
()
=>
{
const
epicsEl
=
wrapper
.
findAll
(
'
.issue-count-badge > span
'
).
at
(
0
);
const
epicIcon
=
epicsEl
.
find
(
GlIcon
);
it
(
'
renders `Add an epic` dropdown button
'
,
()
=>
{
expect
(
findEpicsSplitButton
()
.
isVisible
()).
toBe
(
true
);
}
);
expect
(
epicsEl
.
text
().
trim
()).
toContain
(
'
2
'
);
expect
(
epicIcon
.
isVisible
()).
toBe
(
true
);
expect
(
epicIcon
.
props
(
'
name
'
)).
toBe
(
'
epic
'
);
});
describe
(
'
when sub-epics feature is not available
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
.
vm
.
$store
.
commit
(
'
SET_INITIAL_CONFIG
'
,
{
...
mockInitialConfig
,
allowSubEpics
:
false
,
});
return
wrapper
.
vm
.
$nextTick
();
});
it
(
'
does not render epics count and gl-icon
'
,
()
=>
{
const
countBadgesEl
=
wrapper
.
findAll
(
'
.issue-count-badge > span
'
);
const
badgeIcon
=
countBadgesEl
.
at
(
0
).
find
(
GlIcon
);
expect
(
countBadgesEl
).
toHaveLength
(
1
);
expect
(
badgeIcon
.
props
(
'
name
'
)).
toBe
(
'
issues
'
);
});
it
(
'
does not render `Add an epic` dropdown button
'
,
()
=>
{
expect
(
findEpicsSplitButton
().
exists
()).
toBe
(
false
);
});
it
(
'
renders `Add` dropdown button
'
,
()
=>
{
expect
(
findEpicsIssuesSplitButton
().
isVisible
()).
toBe
(
true
);
});
it
(
'
renders issues count and gl-icon
'
,
()
=>
{
...
...
@@ -216,38 +204,6 @@ describe('RelatedItemsTree', () => {
expect
(
issueIcon
.
isVisible
()).
toBe
(
true
);
expect
(
issueIcon
.
props
(
'
name
'
)).
toBe
(
'
issues
'
);
});
it
(
'
renders `Add an issue` dropdown button
'
,
()
=>
{
const
addIssueBtn
=
findAddIssuesButton
();
expect
(
addIssueBtn
.
isVisible
()).
toBe
(
true
);
expect
(
addIssueBtn
.
text
()).
toBe
(
'
Add an issue
'
);
});
});
describe
(
'
slots
'
,
()
=>
{
describe
(
'
issueActions
'
,
()
=>
{
it
(
'
defaults to button
'
,
()
=>
{
wrapper
=
createComponent
();
expect
(
findAddIssuesButton
().
exists
()).
toBe
(
true
);
});
it
(
'
uses provided slot content
'
,
()
=>
{
const
issueActions
=
{
template
:
'
<p>custom content</p>
'
,
};
wrapper
=
createComponent
({
slots
:
{
issueActions
,
},
});
expect
(
findAddIssuesButton
().
exists
()).
toBe
(
false
);
expect
(
wrapper
.
find
(
issueActions
).
exists
()).
toBe
(
true
);
});
});
});
});
});
qa/qa/ee/page/group/epic/show.rb
View file @
b38c9bd2
...
...
@@ -20,8 +20,8 @@ module QA
element
:add_issue_input
end
view
'ee/app/assets/javascripts/related_items_tree/components/issue_actions_split_button.vue'
do
element
:issue_actions_split_button
view
'ee/app/assets/javascripts/related_items_tree/components/
epic_
issue_actions_split_button.vue'
do
element
:
epic_
issue_actions_split_button
end
view
'ee/app/assets/javascripts/related_items_tree/components/tree_item.vue'
do
...
...
@@ -33,7 +33,7 @@ module QA
end
def
add_issue_to_epic
(
issue_url
)
find_element
(
:issue_actions_split_button
).
find
(
'button'
,
text:
'Add an issue'
).
click
find_element
(
:
epic_
issue_actions_split_button
).
find
(
'button'
,
text:
'Add an issue'
).
click
fill_element
:add_issue_input
,
issue_url
# Clicking the title blurs the input
click_element
:title
...
...
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