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
186f2eee
Commit
186f2eee
authored
Apr 22, 2021
by
Sarah Groff Hennigh-Palermo
Committed by
Andrew Fontaine
Apr 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add hover tip for show links toggle
parent
3fb47386
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
246 additions
and
40 deletions
+246
-40
app/assets/javascripts/pipelines/components/graph/graph_component.vue
...avascripts/pipelines/components/graph/graph_component.vue
+1
-1
app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
...ts/pipelines/components/graph/graph_component_wrapper.vue
+35
-0
app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
...cripts/pipelines/components/graph/graph_view_selector.vue
+54
-30
app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue
...pelines/components/notification/pipeline_notification.vue
+2
-2
app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql
...s/graphql/mutations/dismiss_pipeline_notification.graphql
+1
-1
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
.../frontend/pipelines/graph/graph_component_wrapper_spec.js
+64
-4
spec/frontend/pipelines/graph/graph_view_selector_spec.js
spec/frontend/pipelines/graph/graph_view_selector_spec.js
+67
-2
spec/frontend/pipelines/graph/mock_data.js
spec/frontend/pipelines/graph/mock_data.js
+19
-0
No files found.
app/assets/javascripts/pipelines/components/graph/graph_component.vue
View file @
186f2eee
...
@@ -165,7 +165,7 @@ export default {
...
@@ -165,7 +165,7 @@ export default {
<div
class=
"js-pipeline-graph"
>
<div
class=
"js-pipeline-graph"
>
<div
<div
ref=
"mainPipelineContainer"
ref=
"mainPipelineContainer"
class=
"gl-display-flex gl-position-relative gl-bg-gray-10 gl-white-space-nowrap"
class=
"gl-display-flex gl-position-relative gl-bg-gray-10 gl-white-space-nowrap
gl-border-t-solid gl-border-t-1 gl-border-gray-100
"
:class=
"
{ 'gl-pipeline-min-h gl-py-5 gl-overflow-auto': !isLinkedPipeline }"
:class=
"
{ 'gl-pipeline-min-h gl-py-5 gl-overflow-auto': !isLinkedPipeline }"
>
>
<linked-graph-wrapper>
<linked-graph-wrapper>
...
...
app/assets/javascripts/pipelines/components/graph/graph_component_wrapper.vue
View file @
186f2eee
...
@@ -5,6 +5,8 @@ import { __ } from '~/locale';
...
@@ -5,6 +5,8 @@ import { __ } from '~/locale';
import
LocalStorageSync
from
'
~/vue_shared/components/local_storage_sync.vue
'
;
import
LocalStorageSync
from
'
~/vue_shared/components/local_storage_sync.vue
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
{
DEFAULT
,
DRAW_FAILURE
,
LOAD_FAILURE
}
from
'
../../constants
'
;
import
{
DEFAULT
,
DRAW_FAILURE
,
LOAD_FAILURE
}
from
'
../../constants
'
;
import
DismissPipelineGraphCallout
from
'
../../graphql/mutations/dismiss_pipeline_notification.graphql
'
;
import
getUserCallouts
from
'
../../graphql/queries/get_user_callouts.query.graphql
'
;
import
{
reportToSentry
}
from
'
../../utils
'
;
import
{
reportToSentry
}
from
'
../../utils
'
;
import
{
listByLayers
}
from
'
../parsing_utils
'
;
import
{
listByLayers
}
from
'
../parsing_utils
'
;
import
{
IID_FAILURE
,
LAYER_VIEW
,
STAGE_VIEW
,
VIEW_TYPE_KEY
}
from
'
./constants
'
;
import
{
IID_FAILURE
,
LAYER_VIEW
,
STAGE_VIEW
,
VIEW_TYPE_KEY
}
from
'
./constants
'
;
...
@@ -17,6 +19,9 @@ import {
...
@@ -17,6 +19,9 @@ import {
unwrapPipelineData
,
unwrapPipelineData
,
}
from
'
./utils
'
;
}
from
'
./utils
'
;
const
featureName
=
'
pipeline_needs_hover_tip
'
;
const
enumFeatureName
=
featureName
.
toUpperCase
();
export
default
{
export
default
{
name
:
'
PipelineGraphWrapper
'
,
name
:
'
PipelineGraphWrapper
'
,
components
:
{
components
:
{
...
@@ -44,6 +49,7 @@ export default {
...
@@ -44,6 +49,7 @@ export default {
data
()
{
data
()
{
return
{
return
{
alertType
:
null
,
alertType
:
null
,
callouts
:
[],
currentViewType
:
STAGE_VIEW
,
currentViewType
:
STAGE_VIEW
,
pipeline
:
null
,
pipeline
:
null
,
pipelineLayers
:
null
,
pipelineLayers
:
null
,
...
@@ -60,6 +66,18 @@ export default {
...
@@ -60,6 +66,18 @@ export default {
[
DEFAULT
]:
__
(
'
An unknown error occurred while loading this graph.
'
),
[
DEFAULT
]:
__
(
'
An unknown error occurred while loading this graph.
'
),
},
},
apollo
:
{
apollo
:
{
callouts
:
{
query
:
getUserCallouts
,
update
(
data
)
{
return
data
?.
currentUser
?.
callouts
?.
nodes
.
map
((
callout
)
=>
callout
.
featureName
);
},
error
(
err
)
{
reportToSentry
(
this
.
$options
.
name
,
`type: callout_load_failure, info:
${
serializeLoadErrors
(
err
)}
`
,
);
},
},
pipeline
:
{
pipeline
:
{
context
()
{
context
()
{
return
getQueryHeaders
(
this
.
graphqlResourceEtag
);
return
getQueryHeaders
(
this
.
graphqlResourceEtag
);
...
@@ -142,6 +160,9 @@ export default {
...
@@ -142,6 +160,9 @@ export default {
/* This prevents reading view type off the localStorage value if it does not apply. */
/* This prevents reading view type off the localStorage value if it does not apply. */
return
this
.
showGraphViewSelector
?
this
.
currentViewType
:
STAGE_VIEW
;
return
this
.
showGraphViewSelector
?
this
.
currentViewType
:
STAGE_VIEW
;
},
},
hoverTipPreviouslyDismissed
()
{
return
this
.
callouts
.
includes
(
enumFeatureName
);
},
showLoadingIcon
()
{
showLoadingIcon
()
{
/*
/*
Shows the icon only when the graph is empty, not when it is is
Shows the icon only when the graph is empty, not when it is is
...
@@ -171,6 +192,18 @@ export default {
...
@@ -171,6 +192,18 @@ export default {
return
this
.
pipelineLayers
;
return
this
.
pipelineLayers
;
},
},
handleTipDismissal
()
{
try
{
this
.
$apollo
.
mutate
({
mutation
:
DismissPipelineGraphCallout
,
variables
:
{
featureName
,
},
});
}
catch
(
err
)
{
reportToSentry
(
this
.
$options
.
name
,
`type: callout_dismiss_failure, info:
${
err
}
`
);
}
},
hideAlert
()
{
hideAlert
()
{
this
.
showAlert
=
false
;
this
.
showAlert
=
false
;
this
.
alertType
=
null
;
this
.
alertType
=
null
;
...
@@ -211,6 +244,8 @@ export default {
...
@@ -211,6 +244,8 @@ export default {
v-if=
"showGraphViewSelector"
v-if=
"showGraphViewSelector"
:type=
"graphViewType"
:type=
"graphViewType"
:show-links=
"showLinks"
:show-links=
"showLinks"
:tip-previously-dismissed=
"hoverTipPreviouslyDismissed"
@
dismissHoverTip=
"handleTipDismissal"
@
updateViewType=
"updateViewType"
@
updateViewType=
"updateViewType"
@
updateShowLinksState=
"updateShowLinksState"
@
updateShowLinksState=
"updateShowLinksState"
/>
/>
...
...
app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
View file @
186f2eee
<
script
>
<
script
>
import
{
GlLoadingIcon
,
GlSegmentedControl
,
GlToggle
}
from
'
@gitlab/ui
'
;
import
{
Gl
Alert
,
Gl
LoadingIcon
,
GlSegmentedControl
,
GlToggle
}
from
'
@gitlab/ui
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
STAGE_VIEW
,
LAYER_VIEW
}
from
'
./constants
'
;
import
{
STAGE_VIEW
,
LAYER_VIEW
}
from
'
./constants
'
;
export
default
{
export
default
{
name
:
'
GraphViewSelector
'
,
name
:
'
GraphViewSelector
'
,
components
:
{
components
:
{
GlAlert
,
GlLoadingIcon
,
GlLoadingIcon
,
GlSegmentedControl
,
GlSegmentedControl
,
GlToggle
,
GlToggle
,
...
@@ -15,6 +16,10 @@ export default {
...
@@ -15,6 +16,10 @@ export default {
type
:
Boolean
,
type
:
Boolean
,
required
:
true
,
required
:
true
,
},
},
tipPreviouslyDismissed
:
{
type
:
Boolean
,
required
:
true
,
},
type
:
{
type
:
{
type
:
String
,
type
:
String
,
required
:
true
,
required
:
true
,
...
@@ -22,15 +27,17 @@ export default {
...
@@ -22,15 +27,17 @@ export default {
},
},
data
()
{
data
()
{
return
{
return
{
currentViewType
:
this
.
type
,
hoverTipDismissed
:
false
,
showLinksActive
:
false
,
isToggleLoading
:
false
,
isToggleLoading
:
false
,
isSwitcherLoading
:
false
,
isSwitcherLoading
:
false
,
segmentSelectedType
:
this
.
type
,
showLinksActive
:
false
,
};
};
},
},
i18n
:
{
i18n
:
{
viewLabelText
:
__
(
'
Group jobs by
'
),
hoverTipText
:
__
(
'
Tip: Hover over a job to see the jobs it depends on to run.
'
),
linksLabelText
:
__
(
'
Show dependencies
'
),
linksLabelText
:
__
(
'
Show dependencies
'
),
viewLabelText
:
__
(
'
Group jobs by
'
),
},
},
views
:
{
views
:
{
[
STAGE_VIEW
]:
{
[
STAGE_VIEW
]:
{
...
@@ -48,7 +55,15 @@ export default {
...
@@ -48,7 +55,15 @@ export default {
},
},
computed
:
{
computed
:
{
showLinksToggle
()
{
showLinksToggle
()
{
return
this
.
currentViewType
===
LAYER_VIEW
;
return
this
.
segmentSelectedType
===
LAYER_VIEW
;
},
showTip
()
{
return
(
this
.
showLinks
&&
this
.
showLinksActive
&&
!
this
.
tipPreviouslyDismissed
&&
!
this
.
hoverTipDismissed
);
},
},
viewTypesList
()
{
viewTypesList
()
{
return
Object
.
keys
(
this
.
$options
.
views
).
map
((
key
)
=>
{
return
Object
.
keys
(
this
.
$options
.
views
).
map
((
key
)
=>
{
...
@@ -77,6 +92,10 @@ export default {
...
@@ -77,6 +92,10 @@ export default {
},
},
},
},
methods
:
{
methods
:
{
dismissTip
()
{
this
.
hoverTipDismissed
=
true
;
this
.
$emit
(
'
dismissHoverTip
'
);
},
/*
/*
In both toggle methods, we use setTimeout so that the loading indicator displays,
In both toggle methods, we use setTimeout so that the loading indicator displays,
then the work is done to update the DOM. The process is:
then the work is done to update the DOM. The process is:
...
@@ -108,33 +127,38 @@ export default {
...
@@ -108,33 +127,38 @@ export default {
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"gl-relative gl-display-flex gl-align-items-center gl-w-max-content gl-my-4"
>
<div>
<gl-loading-icon
<div
class=
"gl-relative gl-display-flex gl-align-items-center gl-w-max-content gl-my-4"
>
v-if=
"isSwitcherLoading"
<gl-loading-icon
data-testid=
"switcher-loading-state"
v-if=
"isSwitcherLoading"
class=
"gl-absolute gl-w-full gl-bg-white gl-opacity-5 gl-z-index-2"
data-testid=
"switcher-loading-state"
size=
"lg"
class=
"gl-absolute gl-w-full gl-bg-white gl-opacity-5 gl-z-index-2"
/>
size=
"lg"
<span
class=
"gl-font-weight-bold"
>
{{
$options
.
i18n
.
viewLabelText
}}
</span>
/>
<gl-segmented-control
<span
class=
"gl-font-weight-bold"
>
{{
$options
.
i18n
.
viewLabelText
}}
</span>
v-model=
"currentViewType"
<gl-segmented-control
:options=
"viewTypesList"
v-model=
"segmentSelectedType"
:disabled=
"isSwitcherLoading"
:options=
"viewTypesList"
data-testid=
"pipeline-view-selector"
:disabled=
"isSwitcherLoading"
class=
"gl-mx-4"
data-testid=
"pipeline-view-selector"
@
input=
"toggleView"
/>
<div
v-if=
"showLinksToggle"
>
<gl-toggle
v-model=
"showLinksActive"
data-testid=
"show-links-toggle"
class=
"gl-mx-4"
class=
"gl-mx-4"
:label=
"$options.i18n.linksLabelText"
@
input=
"toggleView"
:is-loading=
"isToggleLoading"
label-position=
"left"
@
change=
"toggleShowLinksActive"
/>
/>
<div
v-if=
"showLinksToggle"
class=
"gl-display-flex gl-align-items-center"
>
<gl-toggle
v-model=
"showLinksActive"
data-testid=
"show-links-toggle"
class=
"gl-mx-4"
:label=
"$options.i18n.linksLabelText"
:is-loading=
"isToggleLoading"
label-position=
"left"
@
change=
"toggleShowLinksActive"
/>
</div>
</div>
</div>
<gl-alert
v-if=
"showTip"
class=
"gl-my-5"
variant=
"tip"
@
dismiss=
"dismissTip"
>
{{
$options
.
i18n
.
hoverTipText
}}
</gl-alert>
</div>
</div>
</
template
>
</
template
>
app/assets/javascripts/pipelines/components/notification/pipeline_notification.vue
View file @
186f2eee
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
import
{
GlBanner
,
GlLink
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
GlBanner
,
GlLink
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
createFlash
from
'
~/flash
'
;
import
createFlash
from
'
~/flash
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
DismissPipeline
Notification
from
'
../../graphql/mutations/dismiss_pipeline_notification.graphql
'
;
import
DismissPipeline
GraphCallout
from
'
../../graphql/mutations/dismiss_pipeline_notification.graphql
'
;
import
getUserCallouts
from
'
../../graphql/queries/get_user_callouts.query.graphql
'
;
import
getUserCallouts
from
'
../../graphql/queries/get_user_callouts.query.graphql
'
;
const
featureName
=
'
pipeline_needs_banner
'
;
const
featureName
=
'
pipeline_needs_banner
'
;
...
@@ -55,7 +55,7 @@ export default {
...
@@ -55,7 +55,7 @@ export default {
this
.
dismissedAlert
=
true
;
this
.
dismissedAlert
=
true
;
try
{
try
{
this
.
$apollo
.
mutate
({
this
.
$apollo
.
mutate
({
mutation
:
DismissPipeline
Notification
,
mutation
:
DismissPipeline
GraphCallout
,
variables
:
{
variables
:
{
featureName
,
featureName
,
},
},
...
...
app/assets/javascripts/pipelines/graphql/mutations/dismiss_pipeline_notification.graphql
View file @
186f2eee
mutation
DismissPipeline
Notification
(
$featureName
:
String
!)
{
mutation
DismissPipeline
GraphCallout
(
$featureName
:
String
!)
{
userCalloutCreate
(
input
:
{
featureName
:
$featureName
})
{
userCalloutCreate
(
input
:
{
featureName
:
$featureName
})
{
errors
errors
}
}
...
...
locale/gitlab.pot
View file @
186f2eee
...
@@ -32974,6 +32974,9 @@ msgstr ""
...
@@ -32974,6 +32974,9 @@ msgstr ""
msgid "Tip:"
msgid "Tip:"
msgstr ""
msgstr ""
msgid "Tip: Hover over a job to see the jobs it depends on to run."
msgstr ""
msgid "Tip: add a"
msgid "Tip: add a"
msgstr ""
msgstr ""
...
...
spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
View file @
186f2eee
...
@@ -17,7 +17,8 @@ import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.
...
@@ -17,7 +17,8 @@ import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.
import
StageColumnComponent
from
'
~/pipelines/components/graph/stage_column_component.vue
'
;
import
StageColumnComponent
from
'
~/pipelines/components/graph/stage_column_component.vue
'
;
import
LinksLayer
from
'
~/pipelines/components/graph_shared/links_layer.vue
'
;
import
LinksLayer
from
'
~/pipelines/components/graph_shared/links_layer.vue
'
;
import
*
as
parsingUtils
from
'
~/pipelines/components/parsing_utils
'
;
import
*
as
parsingUtils
from
'
~/pipelines/components/parsing_utils
'
;
import
{
mockPipelineResponse
}
from
'
./mock_data
'
;
import
getUserCallouts
from
'
~/pipelines/graphql/queries/get_user_callouts.query.graphql
'
;
import
{
mapCallouts
,
mockCalloutsResponse
,
mockPipelineResponse
}
from
'
./mock_data
'
;
const
defaultProvide
=
{
const
defaultProvide
=
{
graphqlResourceEtag
:
'
frog/amphibirama/etag/
'
,
graphqlResourceEtag
:
'
frog/amphibirama/etag/
'
,
...
@@ -31,15 +32,16 @@ describe('Pipeline graph wrapper', () => {
...
@@ -31,15 +32,16 @@ describe('Pipeline graph wrapper', () => {
useLocalStorageSpy
();
useLocalStorageSpy
();
let
wrapper
;
let
wrapper
;
const
getAlert
=
()
=>
wrapper
.
find
(
GlAlert
);
const
getAlert
=
()
=>
wrapper
.
find
Component
(
GlAlert
);
const
getDependenciesToggle
=
()
=>
wrapper
.
find
(
'
[data-testid="show-links-toggle"]
'
);
const
getDependenciesToggle
=
()
=>
wrapper
.
find
(
'
[data-testid="show-links-toggle"]
'
);
const
getLoadingIcon
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
const
getLoadingIcon
=
()
=>
wrapper
.
find
Component
(
GlLoadingIcon
);
const
getLinksLayer
=
()
=>
wrapper
.
findComponent
(
LinksLayer
);
const
getLinksLayer
=
()
=>
wrapper
.
findComponent
(
LinksLayer
);
const
getGraph
=
()
=>
wrapper
.
find
(
PipelineGraph
);
const
getGraph
=
()
=>
wrapper
.
find
(
PipelineGraph
);
const
getStageColumnTitle
=
()
=>
wrapper
.
find
(
'
[data-testid="stage-column-title"]
'
);
const
getStageColumnTitle
=
()
=>
wrapper
.
find
(
'
[data-testid="stage-column-title"]
'
);
const
getAllStageColumnGroupsInColumn
=
()
=>
const
getAllStageColumnGroupsInColumn
=
()
=>
wrapper
.
find
(
StageColumnComponent
).
findAll
(
'
[data-testid="stage-column-group"]
'
);
wrapper
.
find
(
StageColumnComponent
).
findAll
(
'
[data-testid="stage-column-group"]
'
);
const
getViewSelector
=
()
=>
wrapper
.
find
(
GraphViewSelector
);
const
getViewSelector
=
()
=>
wrapper
.
find
(
GraphViewSelector
);
const
getViewSelectorTrip
=
()
=>
getViewSelector
().
findComponent
(
GlAlert
);
const
createComponent
=
({
const
createComponent
=
({
apolloProvider
,
apolloProvider
,
...
@@ -62,12 +64,19 @@ describe('Pipeline graph wrapper', () => {
...
@@ -62,12 +64,19 @@ describe('Pipeline graph wrapper', () => {
};
};
const
createComponentWithApollo
=
({
const
createComponentWithApollo
=
({
calloutsList
=
[],
data
=
{},
data
=
{},
getPipelineDetailsHandler
=
jest
.
fn
().
mockResolvedValue
(
mockPipelineResponse
),
getPipelineDetailsHandler
=
jest
.
fn
().
mockResolvedValue
(
mockPipelineResponse
),
mountFn
=
shallowMount
,
mountFn
=
shallowMount
,
provide
=
{},
provide
=
{},
}
=
{})
=>
{
}
=
{})
=>
{
const
requestHandlers
=
[[
getPipelineDetails
,
getPipelineDetailsHandler
]];
const
callouts
=
mapCallouts
(
calloutsList
);
const
getUserCalloutsHandler
=
jest
.
fn
().
mockResolvedValue
(
mockCalloutsResponse
(
callouts
));
const
requestHandlers
=
[
[
getPipelineDetails
,
getPipelineDetailsHandler
],
[
getUserCallouts
,
getUserCalloutsHandler
],
];
const
apolloProvider
=
createMockApollo
(
requestHandlers
);
const
apolloProvider
=
createMockApollo
(
requestHandlers
);
createComponent
({
apolloProvider
,
data
,
provide
,
mountFn
});
createComponent
({
apolloProvider
,
data
,
provide
,
mountFn
});
...
@@ -325,6 +334,57 @@ describe('Pipeline graph wrapper', () => {
...
@@ -325,6 +334,57 @@ describe('Pipeline graph wrapper', () => {
});
});
});
});
describe
(
'
when pipelineGraphLayersView feature flag is on, layers view is selected, and links are active
'
,
()
=>
{
beforeEach
(
async
()
=>
{
createComponentWithApollo
({
provide
:
{
glFeatures
:
{
pipelineGraphLayersView
:
true
,
},
},
data
:
{
currentViewType
:
LAYER_VIEW
,
showLinks
:
true
,
},
mountFn
:
mount
,
});
jest
.
runOnlyPendingTimers
();
await
wrapper
.
vm
.
$nextTick
();
});
it
(
'
shows the hover tip in the view selector
'
,
async
()
=>
{
await
getViewSelector
().
setData
({
showLinksActive
:
true
});
expect
(
getViewSelectorTrip
().
exists
()).
toBe
(
true
);
});
});
describe
(
'
when hover tip would otherwise show, but it has been previously dismissed
'
,
()
=>
{
beforeEach
(
async
()
=>
{
createComponentWithApollo
({
provide
:
{
glFeatures
:
{
pipelineGraphLayersView
:
true
,
},
},
data
:
{
currentViewType
:
LAYER_VIEW
,
showLinks
:
true
,
},
mountFn
:
mount
,
calloutsList
:
[
'
pipeline_needs_hover_tip
'
.
toUpperCase
()],
});
jest
.
runOnlyPendingTimers
();
await
wrapper
.
vm
.
$nextTick
();
});
it
(
'
does not show the hover tip
'
,
async
()
=>
{
await
getViewSelector
().
setData
({
showLinksActive
:
true
});
expect
(
getViewSelectorTrip
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
when feature flag is on and local storage is set
'
,
()
=>
{
describe
(
'
when feature flag is on and local storage is set
'
,
()
=>
{
beforeEach
(
async
()
=>
{
beforeEach
(
async
()
=>
{
localStorage
.
setItem
(
VIEW_TYPE_KEY
,
LAYER_VIEW
);
localStorage
.
setItem
(
VIEW_TYPE_KEY
,
LAYER_VIEW
);
...
...
spec/frontend/pipelines/graph/graph_view_selector_spec.js
View file @
186f2eee
import
{
GlLoadingIcon
,
GlSegmentedControl
}
from
'
@gitlab/ui
'
;
import
{
Gl
Alert
,
Gl
LoadingIcon
,
GlSegmentedControl
}
from
'
@gitlab/ui
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
mount
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
LAYER_VIEW
,
STAGE_VIEW
}
from
'
~/pipelines/components/graph/constants
'
;
import
{
LAYER_VIEW
,
STAGE_VIEW
}
from
'
~/pipelines/components/graph/constants
'
;
import
GraphViewSelector
from
'
~/pipelines/components/graph/graph_view_selector.vue
'
;
import
GraphViewSelector
from
'
~/pipelines/components/graph/graph_view_selector.vue
'
;
...
@@ -12,16 +12,19 @@ describe('the graph view selector component', () => {
...
@@ -12,16 +12,19 @@ describe('the graph view selector component', () => {
const
findLayersViewLabel
=
()
=>
findViewTypeSelector
().
findAll
(
'
label
'
).
at
(
1
);
const
findLayersViewLabel
=
()
=>
findViewTypeSelector
().
findAll
(
'
label
'
).
at
(
1
);
const
findSwitcherLoader
=
()
=>
wrapper
.
find
(
'
[data-testid="switcher-loading-state"]
'
);
const
findSwitcherLoader
=
()
=>
wrapper
.
find
(
'
[data-testid="switcher-loading-state"]
'
);
const
findToggleLoader
=
()
=>
findDependenciesToggle
().
find
(
GlLoadingIcon
);
const
findToggleLoader
=
()
=>
findDependenciesToggle
().
find
(
GlLoadingIcon
);
const
findHoverTip
=
()
=>
wrapper
.
findComponent
(
GlAlert
);
const
defaultProps
=
{
const
defaultProps
=
{
showLinks
:
false
,
showLinks
:
false
,
tipPreviouslyDismissed
:
false
,
type
:
STAGE_VIEW
,
type
:
STAGE_VIEW
,
};
};
const
defaultData
=
{
const
defaultData
=
{
showLinksActive
:
false
,
hoverTipDismissed
:
false
,
isToggleLoading
:
false
,
isToggleLoading
:
false
,
isSwitcherLoading
:
false
,
isSwitcherLoading
:
false
,
showLinksActive
:
false
,
};
};
const
createComponent
=
({
data
=
{},
mountFn
=
shallowMount
,
props
=
{}
}
=
{})
=>
{
const
createComponent
=
({
data
=
{},
mountFn
=
shallowMount
,
props
=
{}
}
=
{})
=>
{
...
@@ -121,4 +124,66 @@ describe('the graph view selector component', () => {
...
@@ -121,4 +124,66 @@ describe('the graph view selector component', () => {
expect
(
wrapper
.
emitted
().
updateShowLinksState
).
toEqual
([[
true
]]);
expect
(
wrapper
.
emitted
().
updateShowLinksState
).
toEqual
([[
true
]]);
});
});
});
});
describe
(
'
hover tip callout
'
,
()
=>
{
describe
(
'
when links are live and it has not been previously dismissed
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
showLinks
:
true
,
},
data
:
{
showLinksActive
:
true
,
},
mountFn
:
mount
,
});
});
it
(
'
is displayed
'
,
()
=>
{
expect
(
findHoverTip
().
exists
()).
toBe
(
true
);
expect
(
findHoverTip
().
text
()).
toBe
(
wrapper
.
vm
.
$options
.
i18n
.
hoverTipText
);
});
it
(
'
emits dismissHoverTip event when the tip is dismissed
'
,
async
()
=>
{
expect
(
wrapper
.
emitted
().
dismissHoverTip
).
toBeUndefined
();
await
findHoverTip
().
find
(
'
button
'
).
trigger
(
'
click
'
);
expect
(
wrapper
.
emitted
().
dismissHoverTip
).
toHaveLength
(
1
);
});
});
describe
(
'
when links are live and it has been previously dismissed
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
showLinks
:
true
,
tipPreviouslyDismissed
:
true
,
},
data
:
{
showLinksActive
:
true
,
},
});
});
it
(
'
is not displayed
'
,
()
=>
{
expect
(
findHoverTip
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
when links are not live
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
showLinks
:
true
,
},
data
:
{
showLinksActive
:
false
,
},
});
});
it
(
'
is not displayed
'
,
()
=>
{
expect
(
findHoverTip
().
exists
()).
toBe
(
false
);
});
});
});
});
});
spec/frontend/pipelines/graph/mock_data.js
View file @
186f2eee
...
@@ -669,3 +669,22 @@ export const pipelineWithUpstreamDownstream = (base) => {
...
@@ -669,3 +669,22 @@ export const pipelineWithUpstreamDownstream = (base) => {
return
generateResponse
(
pip
,
'
root/abcd-dag
'
);
return
generateResponse
(
pip
,
'
root/abcd-dag
'
);
};
};
export
const
mapCallouts
=
(
callouts
)
=>
callouts
.
map
((
callout
)
=>
{
return
{
featureName
:
callout
,
__typename
:
'
UserCallout
'
};
});
export
const
mockCalloutsResponse
=
(
mappedCallouts
)
=>
({
data
:
{
currentUser
:
{
id
:
45
,
__typename
:
'
User
'
,
callouts
:
{
id
:
5
,
__typename
:
'
UserCalloutConnection
'
,
nodes
:
mappedCallouts
,
},
},
},
});
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