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
8c3210bc
Commit
8c3210bc
authored
Apr 13, 2018
by
Luke Bennett
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
merge ce
parent
eddaeba1
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
401 additions
and
219 deletions
+401
-219
app/assets/javascripts/feature_highlight/feature_highlight.js
...assets/javascripts/feature_highlight/feature_highlight.js
+6
-6
app/assets/javascripts/feature_highlight/feature_highlight_helper.js
...javascripts/feature_highlight/feature_highlight_helper.js
+1
-28
app/assets/javascripts/milestone.js
app/assets/javascripts/milestone.js
+22
-0
app/assets/javascripts/pages/dashboard/milestones/show/index.js
...sets/javascripts/pages/dashboard/milestones/show/index.js
+2
-0
app/assets/javascripts/pages/groups/milestones/show/index.js
app/assets/javascripts/pages/groups/milestones/show/index.js
+6
-1
app/assets/javascripts/shared/popover.js
app/assets/javascripts/shared/popover.js
+33
-0
app/assets/stylesheets/framework/banner.scss
app/assets/stylesheets/framework/banner.scss
+17
-2
app/assets/stylesheets/framework/buttons.scss
app/assets/stylesheets/framework/buttons.scss
+30
-12
app/assets/stylesheets/pages/milestone.scss
app/assets/stylesheets/pages/milestone.scss
+36
-0
app/views/shared/_auto_devops_callout.html.haml
app/views/shared/_auto_devops_callout.html.haml
+4
-4
app/views/shared/milestones/_deprecation_message.html.haml
app/views/shared/milestones/_deprecation_message.html.haml
+14
-0
app/views/shared/milestones/_top.html.haml
app/views/shared/milestones/_top.html.haml
+8
-5
changelogs/unreleased/deprecation-warning-for-dynamic-milestones.yml
...unreleased/deprecation-warning-for-dynamic-milestones.yml
+5
-0
spec/features/milestone_spec.rb
spec/features/milestone_spec.rb
+14
-0
spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
...cripts/feature_highlight/feature_highlight_helper_spec.js
+2
-157
spec/javascripts/feature_highlight/feature_highlight_spec.js
spec/javascripts/feature_highlight/feature_highlight_spec.js
+4
-4
spec/javascripts/shared/popover_spec.js
spec/javascripts/shared/popover_spec.js
+162
-0
spec/views/shared/milestones/_top.html.haml.rb
spec/views/shared/milestones/_top.html.haml.rb
+35
-0
No files found.
app/assets/javascripts/feature_highlight/feature_highlight.js
View file @
8c3210bc
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
import
{
getSelector
,
togglePopover
,
inserted
,
mouseenter
,
mouseleave
,
}
from
'
./feature_highlight_helper
'
;
import
{
togglePopover
,
mouseenter
,
debouncedMouseleave
,
}
from
'
../shared/popover
'
;
export
function
setupFeatureHighlightPopover
(
id
,
debounceTimeout
=
300
)
{
const
$selector
=
$
(
getSelector
(
id
));
const
$parent
=
$selector
.
parent
();
const
$popoverContent
=
$parent
.
siblings
(
'
.feature-highlight-popover-content
'
);
const
hideOnScroll
=
togglePopover
.
bind
(
$selector
,
false
);
const
debouncedMouseleave
=
_
.
debounce
(
mouseleave
,
debounceTimeout
);
$selector
// Setup popover
...
...
@@ -29,7 +29,7 @@ export function setupFeatureHighlightPopover(id, debounceTimeout = 300) {
`
,
})
.
on
(
'
mouseenter
'
,
mouseenter
)
.
on
(
'
mouseleave
'
,
debouncedMouseleave
)
.
on
(
'
mouseleave
'
,
debouncedMouseleave
(
debounceTimeout
)
)
.
on
(
'
inserted.bs.popover
'
,
inserted
)
.
on
(
'
show.bs.popover
'
,
()
=>
{
window
.
addEventListener
(
'
scroll
'
,
hideOnScroll
);
...
...
app/assets/javascripts/feature_highlight/feature_highlight_helper.js
View file @
8c3210bc
...
...
@@ -3,20 +3,10 @@ import axios from '../lib/utils/axios_utils';
import
{
__
}
from
'
../locale
'
;
import
Flash
from
'
../flash
'
;
import
LazyLoader
from
'
../lazy_loader
'
;
import
{
togglePopover
}
from
'
../shared/popover
'
;
export
const
getSelector
=
highlightId
=>
`.js-feature-highlight[data-highlight=
${
highlightId
}
]`
;
export
function
togglePopover
(
show
)
{
const
isAlreadyShown
=
this
.
hasClass
(
'
js-popover-show
'
);
if
((
show
&&
isAlreadyShown
)
||
(
!
show
&&
!
isAlreadyShown
))
{
return
false
;
}
this
.
popover
(
show
?
'
show
'
:
'
hide
'
);
this
.
toggleClass
(
'
disable-animation js-popover-show
'
,
show
);
return
true
;
}
export
function
dismiss
(
highlightId
)
{
axios
.
post
(
this
.
attr
(
'
data-dismiss-endpoint
'
),
{
feature_name
:
highlightId
,
...
...
@@ -27,23 +17,6 @@ export function dismiss(highlightId) {
this
.
hide
();
}
export
function
mouseleave
()
{
if
(
!
$
(
'
.popover:hover
'
).
length
>
0
)
{
const
$featureHighlight
=
$
(
this
);
togglePopover
.
call
(
$featureHighlight
,
false
);
}
}
export
function
mouseenter
()
{
const
$featureHighlight
=
$
(
this
);
const
showedPopover
=
togglePopover
.
call
(
$featureHighlight
,
true
);
if
(
showedPopover
)
{
$
(
'
.popover
'
)
.
on
(
'
mouseleave
'
,
mouseleave
.
bind
(
$featureHighlight
));
}
}
export
function
inserted
()
{
const
popoverId
=
this
.
getAttribute
(
'
aria-describedby
'
);
const
highlightId
=
this
.
dataset
.
highlight
;
...
...
app/assets/javascripts/milestone.js
View file @
8c3210bc
import
$
from
'
jquery
'
;
import
axios
from
'
./lib/utils/axios_utils
'
;
import
flash
from
'
./flash
'
;
import
{
mouseenter
,
debouncedMouseleave
,
togglePopover
}
from
'
./shared/popover
'
;
export
default
class
Milestone
{
constructor
()
{
...
...
@@ -43,4 +44,25 @@ export default class Milestone {
.
catch
(()
=>
flash
(
'
Error loading milestone tab
'
));
}
}
static
initDeprecationMessage
()
{
const
deprecationMesssageContainer
=
document
.
querySelector
(
'
.js-milestone-deprecation-message
'
);
if
(
!
deprecationMesssageContainer
)
return
;
const
deprecationMessage
=
deprecationMesssageContainer
.
querySelector
(
'
.js-milestone-deprecation-message-template
'
).
innerHTML
;
const
$popover
=
$
(
'
.js-popover-link
'
,
deprecationMesssageContainer
);
const
hideOnScroll
=
togglePopover
.
bind
(
$popover
,
false
);
$popover
.
popover
({
content
:
deprecationMessage
,
html
:
true
,
placement
:
'
bottom
'
,
})
.
on
(
'
mouseenter
'
,
mouseenter
)
.
on
(
'
mouseleave
'
,
debouncedMouseleave
())
.
one
(
'
show.bs.popover
'
,
()
=>
{
window
.
addEventListener
(
'
scroll
'
,
hideOnScroll
);
});
}
}
app/assets/javascripts/pages/dashboard/milestones/show/index.js
View file @
8c3210bc
...
...
@@ -6,4 +6,6 @@ document.addEventListener('DOMContentLoaded', () => {
new
Milestone
();
// eslint-disable-line no-new
new
Sidebar
();
// eslint-disable-line no-new
new
MountMilestoneSidebar
();
// eslint-disable-line no-new
Milestone
.
initDeprecationMessage
();
});
app/assets/javascripts/pages/groups/milestones/show/index.js
View file @
8c3210bc
import
initMilestonesShow
from
'
~/pages/milestones/shared/init_milestones_show
'
;
import
Milestone
from
'
~/milestone
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
initMilestonesShow
);
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
initMilestonesShow
();
Milestone
.
initDeprecationMessage
();
});
app/assets/javascripts/shared/popover.js
0 → 100644
View file @
8c3210bc
import
$
from
'
jquery
'
;
import
_
from
'
underscore
'
;
export
function
togglePopover
(
show
)
{
const
isAlreadyShown
=
this
.
hasClass
(
'
js-popover-show
'
);
if
((
show
&&
isAlreadyShown
)
||
(
!
show
&&
!
isAlreadyShown
))
{
return
false
;
}
this
.
popover
(
show
?
'
show
'
:
'
hide
'
);
this
.
toggleClass
(
'
disable-animation js-popover-show
'
,
show
);
return
true
;
}
export
function
mouseleave
()
{
if
(
!
$
(
'
.popover:hover
'
).
length
>
0
)
{
const
$popover
=
$
(
this
);
togglePopover
.
call
(
$popover
,
false
);
}
}
export
function
mouseenter
()
{
const
$popover
=
$
(
this
);
const
showedPopover
=
togglePopover
.
call
(
$popover
,
true
);
if
(
showedPopover
)
{
$
(
'
.popover
'
).
on
(
'
mouseleave
'
,
mouseleave
.
bind
(
$popover
));
}
}
export
function
debouncedMouseleave
(
debounceTimeout
=
300
)
{
return
_
.
debounce
(
mouseleave
,
debounceTimeout
);
}
app/assets/stylesheets/framework/banner.scss
View file @
8c3210bc
.banner-callout
{
display
:
flex
;
position
:
relative
;
flex-wrap
:
wrap
;
align-items
:
start
;
.banner-close
{
position
:
absolute
;
...
...
@@ -16,10 +16,25 @@
}
.banner-graphic
{
margin
:
20px
auto
;
margin
:
0
$gl-padding
$gl-padding
0
;
}
&
.banner-non-empty-state
{
border-bottom
:
1px
solid
$border-color
;
}
@media
(
max-width
:
$screen-xs-max
)
{
justify-content
:
center
;
flex-direction
:
column
;
align-items
:
center
;
.banner-title
,
.banner-buttons
{
text-align
:
center
;
}
.banner-graphic
{
margin-left
:
$gl-padding
;
}
}
}
app/assets/stylesheets/framework/buttons.scss
View file @
8c3210bc
...
...
@@ -422,25 +422,43 @@
}
}
.btn-link.btn-secondary-hover-link
{
color
:
$gl-text-color-secondary
;
.btn-link
{
padding
:
0
;
background-color
:
transparent
;
color
:
$blue-600
;
font-weight
:
normal
;
border-radius
:
0
;
border-color
:
transparent
;
&
:hover
,
&
:active
,
&
:focus
{
color
:
$gl-link-color
;
text-decoration
:
none
;
color
:
$blue-800
;
text-decoration
:
underline
;
background-color
:
transparent
;
border-color
:
transparent
;
}
}
.btn-link.btn-prim
ary-hover-link
{
color
:
inherit
;
&
.btn-second
ary-hover-link
{
color
:
$gl-text-color-secondary
;
&
:hover
,
&
:active
,
&
:focus
{
color
:
$gl-link-color
;
text-decoration
:
none
;
&
:hover
,
&
:active
,
&
:focus
{
color
:
$gl-link-color
;
text-decoration
:
none
;
}
}
&
.btn-primary-hover-link
{
color
:
inherit
;
&
:hover
,
&
:active
,
&
:focus
{
color
:
$gl-link-color
;
text-decoration
:
none
;
}
}
}
...
...
app/assets/stylesheets/pages/milestone.scss
View file @
8c3210bc
...
...
@@ -195,6 +195,42 @@
background-color
:
$white-light
;
}
.milestone-deprecation-message
{
.popover
{
padding
:
0
;
}
.popover-content
{
padding
:
0
;
}
}
.milestone-popover-body
{
padding
:
$gl-padding-8
;
background-color
:
$gray-light
;
}
.milestone-popover-footer
{
padding
:
$gl-padding-8
$gl-padding
;
border-top
:
1px
solid
$white-dark
;
}
.milestone-popover-instructions-list
{
padding-left
:
2em
;
>
li
{
padding-left
:
1em
;
}
}
@media
(
max-width
:
$screen-xs-max
)
{
.milestone-banner-text
,
.milestone-banner-link
{
display
:
inline
;
}
}
// EE-only
.burndown-hint.container-fluid
{
...
...
app/views/shared/_auto_devops_callout.html.haml
View file @
8c3210bc
.js-autodevops-banner.banner-callout.banner-non-empty-state.append-bottom-20
{
data:
{
uid:
'auto_devops_settings_dismissed'
,
project_path:
project_path
(
@project
)
}
}
.js-autodevops-banner.banner-callout.banner-non-empty-state.append-bottom-20
.prepend-top-10
{
data:
{
uid:
'auto_devops_settings_dismissed'
,
project_path:
project_path
(
@project
)
}
}
.banner-graphic
=
custom_icon
(
'icon_autodevops'
)
.
prepend-top-10
.prepend-left-10.append-bottom-10
%h5
=
s_
(
'AutoDevOps|Auto DevOps (Beta)'
)
.
banner-body
.prepend-left-10.append-bottom-10
%h5
.banner-title
=
s_
(
'AutoDevOps|Auto DevOps (Beta)'
)
%p
=
s_
(
'AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration.'
)
%p
-
link
=
link_to
(
s_
(
'AutoDevOps|Auto DevOps documentation'
),
help_page_path
(
'topics/autodevops/index.md'
),
target:
'_blank'
,
rel:
'noopener noreferrer'
)
=
s_
(
'AutoDevOps|Learn more in the %{link_to_documentation}'
).
html_safe
%
{
link_to_documentation:
link
}
.
prepend-top-10
.
banner-buttons
=
link_to
s_
(
'AutoDevOps|Enable in settings'
),
project_settings_ci_cd_path
(
@project
,
anchor:
'js-general-pipeline-settings'
),
class:
'btn js-close-callout'
%button
.btn-transparent.banner-close.close.js-close-callout
{
type:
'button'
,
...
...
app/views/shared/milestones/_deprecation_message.html.haml
0 → 100644
View file @
8c3210bc
.banner-callout.compact.milestone-deprecation-message.js-milestone-deprecation-message.prepend-top-20
.banner-graphic
=
image_tag
'illustrations/milestone_removing-page.svg'
.banner-body.prepend-left-10.append-right-10
%h5
.banner-title.prepend-top-0
=
_
(
'This page will be removed in a future release.'
)
%p
.milestone-banner-text
=
_
(
'Use group milestones to manage issues from multiple projects in the same milestone.'
)
=
button_tag
_
(
'Promote these project milestones into a group milestone.'
),
class:
'btn btn-link js-popover-link text-align-left milestone-banner-link'
.milestone-banner-buttons.prepend-top-20
=
link_to
_
(
'Learn more'
),
help_page_url
(
'user/project/milestones/index'
,
anchor:
'promoting-project-milestones-to-group-milestones'
),
class:
'btn btn-default'
,
target:
'_blank'
%template
.js-milestone-deprecation-message-template
.milestone-popover-body
%ol
.milestone-popover-instructions-list.append-bottom-0
%li
=
_
(
'Click any <strong>project name</strong> in the project list below to navigate to the project milestone.'
).
html_safe
%li
=
_
(
'Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone.'
).
html_safe
.milestone-popover-footer
=
link_to
_
(
'Learn more'
),
help_page_url
(
'user/project/milestones/index'
,
anchor:
'promoting-project-milestones-to-group-milestones'
),
class:
'btn btn-link prepend-left-0'
,
target:
'_blank'
app/views/shared/milestones/_top.html.haml
View file @
8c3210bc
-
page_title
@
milestone
.
title
-
page_title
milestone
.
title
-
@breadcrumb_link
=
dashboard_milestone_path
(
milestone
.
safe_title
,
title:
milestone
.
title
)
-
group
=
local_assigns
[
:group
]
-
is_dynamic_milestone
=
milestone
.
legacy_group_milestone?
||
milestone
.
dashboard_milestone?
.detail-page-header
%a
.btn.btn-default.btn-grouped.pull-right.visible-xs-block.js-sidebar-toggle
{
href:
"#"
}
...
...
@@ -31,21 +32,23 @@
-
else
=
link_to
'Reopen Milestone'
,
group_milestone_route
(
milestone
,
{
state_event: :activate
}),
method: :put
,
class:
"btn btn-grouped btn-reopen"
=
render
'shared/milestones/deprecation_message'
if
is_dynamic_milestone
.detail-page-description.milestone-detail
%h2
.title
=
markdown_field
(
milestone
,
:title
)
-
if
@milestone
.
group_milestone?
&&
@
milestone
.
description
.
present?
-
if
milestone
.
group_milestone?
&&
milestone
.
description
.
present?
%div
.description
.wiki
=
markdown_field
(
@
milestone
,
:description
)
=
markdown_field
(
milestone
,
:description
)
-
if
milestone
.
complete?
(
current_user
)
&&
milestone
.
active?
.alert.alert-success.prepend-top-default
-
close_msg
=
group
?
'You may close the milestone now.'
:
'Navigate to the project to close the milestone.'
%span
All issues for this milestone are closed.
#{
close_msg
}
-
if
@milestone
.
legacy_group_milestone?
||
@milestone
.
dashboard_milestone?
-
if
is_dynamic_milestone
.table-holder
%table
.table
%thead
...
...
@@ -68,7 +71,7 @@
Open
%td
=
ms
.
expires_at
-
elsif
@
milestone
.
group_milestone?
-
elsif
milestone
.
group_milestone?
%br
View
=
link_to
'Issues'
,
issues_group_path
(
@group
,
milestone_title:
milestone
.
title
)
...
...
changelogs/unreleased/deprecation-warning-for-dynamic-milestones.yml
0 → 100644
View file @
8c3210bc
---
title
:
Add deprecation message to dynamic milestone pages
merge_request
:
17505
author
:
type
:
added
spec/features/milestone_spec.rb
View file @
8c3210bc
...
...
@@ -108,4 +108,18 @@ feature 'Milestone' do
expect
(
page
).
to
have_selector
(
'.js-delete-milestone-button'
,
count:
0
)
end
end
feature
'deprecation popover'
,
:js
do
it
'opens deprecation popover'
do
milestone
=
create
(
:milestone
,
project:
project
)
visit
group_milestone_path
(
group
,
milestone
,
title:
milestone
.
title
)
expect
(
page
).
to
have_selector
(
'.milestone-deprecation-message'
)
find
(
'.milestone-deprecation-message .js-popover-link'
).
click
expect
(
page
).
to
have_selector
(
'.milestone-deprecation-message .popover'
)
end
end
end
spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
View file @
8c3210bc
...
...
@@ -3,12 +3,11 @@ import MockAdapter from 'axios-mock-adapter';
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
{
getSelector
,
togglePopover
,
dismiss
,
mouseleave
,
mouseenter
,
inserted
,
}
from
'
~/feature_highlight/feature_highlight_helper
'
;
import
{
togglePopover
}
from
'
~/shared/popover
'
;
import
getSetTimeoutPromise
from
'
spec/helpers/set_timeout_promise_helper
'
;
describe
(
'
feature highlight helper
'
,
()
=>
{
...
...
@@ -19,110 +18,6 @@ describe('feature highlight helper', () => {
});
});
describe
(
'
togglePopover
'
,
()
=>
{
describe
(
'
togglePopover(true)
'
,
()
=>
{
it
(
'
returns true when popover is shown
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
expect
(
togglePopover
.
call
(
context
,
true
)).
toEqual
(
true
);
});
it
(
'
returns false when popover is already shown
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
};
expect
(
togglePopover
.
call
(
context
,
true
)).
toEqual
(
false
);
});
it
(
'
shows popover
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
popover
'
).
and
.
callFake
((
method
)
=>
{
expect
(
method
).
toEqual
(
'
show
'
);
done
();
});
togglePopover
.
call
(
context
,
true
);
});
it
(
'
adds disable-animation and js-popover-show class
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
toggleClass
'
).
and
.
callFake
((
classNames
,
show
)
=>
{
expect
(
classNames
).
toEqual
(
'
disable-animation js-popover-show
'
);
expect
(
show
).
toEqual
(
true
);
done
();
});
togglePopover
.
call
(
context
,
true
);
});
});
describe
(
'
togglePopover(false)
'
,
()
=>
{
it
(
'
returns true when popover is hidden
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
expect
(
togglePopover
.
call
(
context
,
false
)).
toEqual
(
true
);
});
it
(
'
returns false when popover is already hidden
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
};
expect
(
togglePopover
.
call
(
context
,
false
)).
toEqual
(
false
);
});
it
(
'
hides popover
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
popover
'
).
and
.
callFake
((
method
)
=>
{
expect
(
method
).
toEqual
(
'
hide
'
);
done
();
});
togglePopover
.
call
(
context
,
false
);
});
it
(
'
removes disable-animation and js-popover-show class
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
toggleClass
'
).
and
.
callFake
((
classNames
,
show
)
=>
{
expect
(
classNames
).
toEqual
(
'
disable-animation js-popover-show
'
);
expect
(
show
).
toEqual
(
false
);
done
();
});
togglePopover
.
call
(
context
,
false
);
});
});
});
describe
(
'
dismiss
'
,
()
=>
{
let
mock
;
const
context
=
{
...
...
@@ -163,56 +58,6 @@ describe('feature highlight helper', () => {
});
});
describe
(
'
mouseleave
'
,
()
=>
{
it
(
'
calls hide popover if .popover:hover is false
'
,
()
=>
{
const
fakeJquery
=
{
length
:
0
,
};
spyOn
(
$
.
fn
,
'
init
'
).
and
.
callFake
(
selector
=>
(
selector
===
'
.popover:hover
'
?
fakeJquery
:
$
.
fn
));
spyOn
(
togglePopover
,
'
call
'
);
mouseleave
();
expect
(
togglePopover
.
call
).
toHaveBeenCalledWith
(
jasmine
.
any
(
Object
),
false
);
});
it
(
'
does not call hide popover if .popover:hover is true
'
,
()
=>
{
const
fakeJquery
=
{
length
:
1
,
};
spyOn
(
$
.
fn
,
'
init
'
).
and
.
callFake
(
selector
=>
(
selector
===
'
.popover:hover
'
?
fakeJquery
:
$
.
fn
));
spyOn
(
togglePopover
,
'
call
'
);
mouseleave
();
expect
(
togglePopover
.
call
).
not
.
toHaveBeenCalledWith
(
false
);
});
});
describe
(
'
mouseenter
'
,
()
=>
{
const
context
=
{};
it
(
'
shows popover
'
,
()
=>
{
spyOn
(
togglePopover
,
'
call
'
).
and
.
returnValue
(
false
);
mouseenter
.
call
(
context
);
expect
(
togglePopover
.
call
).
toHaveBeenCalledWith
(
jasmine
.
any
(
Object
),
true
);
});
it
(
'
registers mouseleave event if popover is showed
'
,
(
done
)
=>
{
spyOn
(
togglePopover
,
'
call
'
).
and
.
returnValue
(
true
);
spyOn
(
$
.
fn
,
'
on
'
).
and
.
callFake
((
eventName
)
=>
{
expect
(
eventName
).
toEqual
(
'
mouseleave
'
);
done
();
});
mouseenter
.
call
(
context
);
});
it
(
'
does not register mouseleave event if popover is not showed
'
,
()
=>
{
spyOn
(
togglePopover
,
'
call
'
).
and
.
returnValue
(
false
);
const
spy
=
spyOn
(
$
.
fn
,
'
on
'
).
and
.
callFake
(()
=>
{});
mouseenter
.
call
(
context
);
expect
(
spy
).
not
.
toHaveBeenCalled
();
});
});
describe
(
'
inserted
'
,
()
=>
{
it
(
'
registers click event callback
'
,
(
done
)
=>
{
const
context
=
{
...
...
spec/javascripts/feature_highlight/feature_highlight_spec.js
View file @
8c3210bc
import
$
from
'
jquery
'
;
import
*
as
featureHighlightHelper
from
'
~/feature_highlight/feature_highlight_helper
'
;
import
*
as
featureHighlight
from
'
~/feature_highlight/feature_highlight
'
;
import
*
as
popover
from
'
~/shared/popover
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
MockAdapter
from
'
axios-mock-adapter
'
;
...
...
@@ -45,14 +45,14 @@ describe('feature highlight', () => {
});
it
(
'
setup mouseenter
'
,
()
=>
{
const
toggleSpy
=
spyOn
(
featureHighlightHelp
er
.
togglePopover
,
'
call
'
);
const
toggleSpy
=
spyOn
(
popov
er
.
togglePopover
,
'
call
'
);
$
(
selector
).
trigger
(
'
mouseenter
'
);
expect
(
toggleSpy
).
toHaveBeenCalledWith
(
jasmine
.
any
(
Object
),
true
);
});
it
(
'
setup debounced mouseleave
'
,
(
done
)
=>
{
const
toggleSpy
=
spyOn
(
featureHighlightHelp
er
.
togglePopover
,
'
call
'
);
const
toggleSpy
=
spyOn
(
popov
er
.
togglePopover
,
'
call
'
);
$
(
selector
).
trigger
(
'
mouseleave
'
);
// Even though we've set the debounce to 0ms, setTimeout is needed for the debounce
...
...
@@ -85,7 +85,7 @@ describe('feature highlight', () => {
it
(
'
toggles when clicked
'
,
()
=>
{
$
(
selector
).
trigger
(
'
mouseenter
'
);
const
popoverId
=
$
(
selector
).
attr
(
'
aria-describedby
'
);
const
toggleSpy
=
spyOn
(
featureHighlightHelp
er
.
togglePopover
,
'
call
'
);
const
toggleSpy
=
spyOn
(
popov
er
.
togglePopover
,
'
call
'
);
$
(
`#
${
popoverId
}
.dismiss-feature-highlight`
).
click
();
...
...
spec/javascripts/shared/popover_spec.js
0 → 100644
View file @
8c3210bc
import
$
from
'
jquery
'
;
import
{
togglePopover
,
mouseleave
,
mouseenter
,
}
from
'
~/shared/popover
'
;
describe
(
'
popover
'
,
()
=>
{
describe
(
'
togglePopover
'
,
()
=>
{
describe
(
'
togglePopover(true)
'
,
()
=>
{
it
(
'
returns true when popover is shown
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
expect
(
togglePopover
.
call
(
context
,
true
)).
toEqual
(
true
);
});
it
(
'
returns false when popover is already shown
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
};
expect
(
togglePopover
.
call
(
context
,
true
)).
toEqual
(
false
);
});
it
(
'
shows popover
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
popover
'
).
and
.
callFake
((
method
)
=>
{
expect
(
method
).
toEqual
(
'
show
'
);
done
();
});
togglePopover
.
call
(
context
,
true
);
});
it
(
'
adds disable-animation and js-popover-show class
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
toggleClass
'
).
and
.
callFake
((
classNames
,
show
)
=>
{
expect
(
classNames
).
toEqual
(
'
disable-animation js-popover-show
'
);
expect
(
show
).
toEqual
(
true
);
done
();
});
togglePopover
.
call
(
context
,
true
);
});
});
describe
(
'
togglePopover(false)
'
,
()
=>
{
it
(
'
returns true when popover is hidden
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
expect
(
togglePopover
.
call
(
context
,
false
)).
toEqual
(
true
);
});
it
(
'
returns false when popover is already hidden
'
,
()
=>
{
const
context
=
{
hasClass
:
()
=>
false
,
};
expect
(
togglePopover
.
call
(
context
,
false
)).
toEqual
(
false
);
});
it
(
'
hides popover
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
popover
'
).
and
.
callFake
((
method
)
=>
{
expect
(
method
).
toEqual
(
'
hide
'
);
done
();
});
togglePopover
.
call
(
context
,
false
);
});
it
(
'
removes disable-animation and js-popover-show class
'
,
(
done
)
=>
{
const
context
=
{
hasClass
:
()
=>
true
,
popover
:
()
=>
{},
toggleClass
:
()
=>
{},
};
spyOn
(
context
,
'
toggleClass
'
).
and
.
callFake
((
classNames
,
show
)
=>
{
expect
(
classNames
).
toEqual
(
'
disable-animation js-popover-show
'
);
expect
(
show
).
toEqual
(
false
);
done
();
});
togglePopover
.
call
(
context
,
false
);
});
});
});
describe
(
'
mouseleave
'
,
()
=>
{
it
(
'
calls hide popover if .popover:hover is false
'
,
()
=>
{
const
fakeJquery
=
{
length
:
0
,
};
spyOn
(
$
.
fn
,
'
init
'
).
and
.
callFake
(
selector
=>
(
selector
===
'
.popover:hover
'
?
fakeJquery
:
$
.
fn
));
spyOn
(
togglePopover
,
'
call
'
);
mouseleave
();
expect
(
togglePopover
.
call
).
toHaveBeenCalledWith
(
jasmine
.
any
(
Object
),
false
);
});
it
(
'
does not call hide popover if .popover:hover is true
'
,
()
=>
{
const
fakeJquery
=
{
length
:
1
,
};
spyOn
(
$
.
fn
,
'
init
'
).
and
.
callFake
(
selector
=>
(
selector
===
'
.popover:hover
'
?
fakeJquery
:
$
.
fn
));
spyOn
(
togglePopover
,
'
call
'
);
mouseleave
();
expect
(
togglePopover
.
call
).
not
.
toHaveBeenCalledWith
(
false
);
});
});
describe
(
'
mouseenter
'
,
()
=>
{
const
context
=
{};
it
(
'
shows popover
'
,
()
=>
{
spyOn
(
togglePopover
,
'
call
'
).
and
.
returnValue
(
false
);
mouseenter
.
call
(
context
);
expect
(
togglePopover
.
call
).
toHaveBeenCalledWith
(
jasmine
.
any
(
Object
),
true
);
});
it
(
'
registers mouseleave event if popover is showed
'
,
(
done
)
=>
{
spyOn
(
togglePopover
,
'
call
'
).
and
.
returnValue
(
true
);
spyOn
(
$
.
fn
,
'
on
'
).
and
.
callFake
((
eventName
)
=>
{
expect
(
eventName
).
toEqual
(
'
mouseleave
'
);
done
();
});
mouseenter
.
call
(
context
);
});
it
(
'
does not register mouseleave event if popover is not showed
'
,
()
=>
{
spyOn
(
togglePopover
,
'
call
'
).
and
.
returnValue
(
false
);
const
spy
=
spyOn
(
$
.
fn
,
'
on
'
).
and
.
callFake
(()
=>
{});
mouseenter
.
call
(
context
);
expect
(
spy
).
not
.
toHaveBeenCalled
();
});
});
});
spec/views/shared/milestones/_top.html.haml.rb
0 → 100644
View file @
8c3210bc
require
'spec_helper'
describe
'shared/milestones/_top.html.haml'
do
set
(
:group
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
group:
group
)
}
let
(
:milestone
)
{
create
(
:milestone
,
project:
project
)
}
before
do
allow
(
milestone
).
to
receive
(
:milestones
)
{
[]
}
end
it
'renders a deprecation message for a legacy milestone'
do
allow
(
milestone
).
to
receive
(
:legacy_group_milestone?
)
{
true
}
render
'shared/milestones/top'
,
milestone:
milestone
expect
(
rendered
).
to
have_css
(
'.milestone-deprecation-message'
)
end
it
'renders a deprecation message for a dashboard milestone'
do
allow
(
milestone
).
to
receive
(
:dashboard_milestone?
)
{
true
}
render
'shared/milestones/top'
,
milestone:
milestone
expect
(
rendered
).
to
have_css
(
'.milestone-deprecation-message'
)
end
it
'does not render a deprecation message for a non-legacy and non-dashboard milestone'
do
assign
:group
,
group
render
'shared/milestones/top'
,
milestone:
milestone
expect
(
rendered
).
not_to
have_css
(
'.milestone-deprecation-message'
)
end
end
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