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
0
Merge Requests
0
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
Boxiang Sun
gitlab-ce
Commits
25170fbe
Commit
25170fbe
authored
Oct 22, 2018
by
Filipa Lacerda
Committed by
Phil Hughes
Oct 22, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Frontend: Review app changes
parent
1438e322
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
427 additions
and
61 deletions
+427
-61
app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
...cripts/vue_merge_request_widget/components/deployment.vue
+63
-12
app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
...avascripts/vue_merge_request_widget/mr_widget_options.vue
+2
-5
app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
...cripts/vue_shared/components/filtered_search_dropdown.vue
+143
-0
app/assets/stylesheets/pages/merge_requests.scss
app/assets/stylesheets/pages/merge_requests.scss
+8
-7
app/controllers/projects/merge_requests_controller.rb
app/controllers/projects/merge_requests_controller.rb
+3
-0
changelogs/unreleased/fe-ac-review-app-changes-33418.yml
changelogs/unreleased/fe-ac-review-app-changes-33418.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/javascripts/vue_mr_widget/components/deployment_spec.js
spec/javascripts/vue_mr_widget/components/deployment_spec.js
+52
-0
spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+57
-37
spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
...ts/vue_shared/components/filtered_search_dropdown_spec.js
+91
-0
No files found.
app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
View file @
25170fbe
<
script
>
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
import
TooltipOnTruncate
from
'
~/vue_shared/components/tooltip_on_truncate.vue
'
;
import
FilteredSearchDropdown
from
'
~/vue_shared/components/filtered_search_dropdown.vue
'
;
import
timeagoMixin
from
'
../../vue_shared/mixins/timeago
'
;
import
timeagoMixin
from
'
../../vue_shared/mixins/timeago
'
;
import
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
import
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
import
LoadingButton
from
'
../../vue_shared/components/loading_button.vue
'
;
import
LoadingButton
from
'
../../vue_shared/components/loading_button.vue
'
;
...
@@ -18,6 +19,7 @@ export default {
...
@@ -18,6 +19,7 @@ export default {
StatusIcon
,
StatusIcon
,
Icon
,
Icon
,
TooltipOnTruncate
,
TooltipOnTruncate
,
FilteredSearchDropdown
,
},
},
directives
:
{
directives
:
{
tooltip
,
tooltip
,
...
@@ -30,8 +32,10 @@ export default {
...
@@ -30,8 +32,10 @@ export default {
},
},
},
},
data
()
{
data
()
{
const
features
=
window
.
gon
.
features
||
{};
return
{
return
{
isStopping
:
false
,
isStopping
:
false
,
enableCiEnvironmentsStatusChanges
:
features
.
ciEnvironmentsStatusChanges
,
};
};
},
},
computed
:
{
computed
:
{
...
@@ -118,18 +122,65 @@ export default {
...
@@ -118,18 +122,65 @@ export default {
/>
/>
</div>
</div>
<div>
<div>
<
template
v-if=
"hasExternalUrls"
>
<filtered-search-dropdown
v-if=
"enableCiEnvironmentsStatusChanges"
class=
"js-mr-wigdet-deployment-dropdown inline"
:items=
"deployment.changes"
:main-action-link=
"deployment.external_url"
filter-key=
"path"
>
<template
slot=
"mainAction"
slot-scope=
"slotProps"
>
<a
:href=
"deployment.external_url"
target=
"_blank"
rel=
"noopener noreferrer nofollow"
class=
"deploy-link js-deploy-url inline"
:class=
"slotProps.className"
>
<span>
{{
__
(
'
View app
'
)
}}
<icon
name=
"external-link"
/>
</span>
</a>
</
template
>
<
template
slot=
"result"
slot-scope=
"slotProps"
>
<a
<a
v-if=
"hasExternalUrls"
:href=
"slotProps.result.external_url"
target=
"_blank"
rel=
"noopener noreferrer nofollow"
class=
"menu-item"
>
<strong
class=
"str-truncated-100 append-bottom-0 d-block"
>
{{
slotProps
.
result
.
path
}}
</strong>
<p
class=
"text-secondary str-truncated-100 append-bottom-0 d-block"
>
{{
slotProps
.
result
.
external_url
}}
</p>
</a>
</
template
>
</filtered-search-dropdown>
<a
v-else
:href=
"deployment.external_url"
:href=
"deployment.external_url"
target=
"_blank"
target=
"_blank"
rel=
"noopener noreferrer nofollow"
rel=
"noopener noreferrer nofollow"
class=
"deploy-link js-deploy-url
btn btn-default btn-sm inline"
class=
"js-deploy-url js-deploy-url-feature-flag deploy-link
btn btn-default btn-sm inline"
>
>
<span>
<span>
View app
{{ __('View app') }}
<icon
name=
"external-link"
/>
<icon
name=
"external-link"
/>
</span>
</span>
</a>
</a>
</template>
<loading-button
<loading-button
v-if=
"deployment.stop_url"
v-if=
"deployment.stop_url"
:loading=
"isStopping"
:loading=
"isStopping"
...
...
app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
View file @
25170fbe
...
@@ -112,7 +112,8 @@ export default {
...
@@ -112,7 +112,8 @@ export default {
eventHub
.
$on
(
'
mr.discussion.updated
'
,
this
.
checkStatus
);
eventHub
.
$on
(
'
mr.discussion.updated
'
,
this
.
checkStatus
);
},
},
mounted
()
{
mounted
()
{
this
.
handleMounted
();
this
.
setFaviconHelper
();
this
.
initDeploymentsPolling
();
},
},
beforeDestroy
()
{
beforeDestroy
()
{
eventHub
.
$off
(
'
mr.discussion.updated
'
,
this
.
checkStatus
);
eventHub
.
$off
(
'
mr.discussion.updated
'
,
this
.
checkStatus
);
...
@@ -250,10 +251,6 @@ export default {
...
@@ -250,10 +251,6 @@ export default {
this
.
stopPolling
();
this
.
stopPolling
();
});
});
},
},
handleMounted
()
{
this
.
setFaviconHelper
();
this
.
initDeploymentsPolling
();
},
},
},
};
};
</
script
>
</
script
>
...
...
app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
0 → 100644
View file @
25170fbe
<
script
>
import
$
from
'
jquery
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
/**
* Renders a split dropdown with
* an input that allows to search through the given
* array of options.
*/
export
default
{
name
:
'
FilteredSearchDropdown
'
,
components
:
{
Icon
,
},
props
:
{
title
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
buttonType
:
{
required
:
false
,
validator
:
value
=>
[
'
primary
'
,
'
default
'
,
'
secondary
'
,
'
success
'
,
'
info
'
,
'
warning
'
,
'
danger
'
].
indexOf
(
value
,
)
!==
-
1
,
default
:
'
default
'
,
},
size
:
{
required
:
false
,
type
:
String
,
default
:
'
sm
'
,
},
items
:
{
type
:
Array
,
required
:
true
,
},
visibleItems
:
{
type
:
Number
,
required
:
false
,
default
:
5
,
},
filterKey
:
{
type
:
String
,
required
:
true
,
},
},
data
()
{
return
{
filter
:
''
,
};
},
computed
:
{
className
()
{
return
`btn btn-
${
this
.
buttonType
}
btn-
${
this
.
size
}
`
;
},
filteredResults
()
{
if
(
this
.
filter
!==
''
)
{
return
this
.
items
.
filter
(
item
=>
item
[
this
.
filterKey
]
&&
item
[
this
.
filterKey
].
toLowerCase
().
includes
(
this
.
filter
.
toLowerCase
()),
);
}
return
this
.
items
.
slice
(
0
,
this
.
visibleItems
);
}
},
mounted
()
{
/**
* Resets the filter every time the user closes the dropdown
*/
$
(
this
.
$el
)
.
on
(
'
shown.bs.dropdown
'
,
()
=>
{
this
.
$nextTick
(()
=>
this
.
$refs
.
searchInput
.
focus
());
})
.
on
(
'
hidden.bs.dropdown
'
,
()
=>
{
this
.
filter
=
''
;
});
},
};
</
script
>
<
template
>
<div
class=
"dropdown"
>
<div
class=
"btn-group"
>
<slot
name=
"mainAction"
:class-name=
"className"
>
<button
type=
"button"
:class=
"className"
>
{{
title
}}
</button>
</slot>
<button
type=
"button"
:class=
"className"
class=
"dropdown-toggle dropdown-toggle-split"
data-toggle=
"dropdown"
aria-haspopup=
"true"
aria-expanded=
"false"
aria-label=
"Expand dropdown"
>
<icon
name=
"angle-down"
:size=
"12"
/>
</button>
<div
class=
"dropdown-menu dropdown-menu-right"
>
<div
class=
"dropdown-input"
>
<input
ref=
"searchInput"
v-model=
"filter"
type=
"search"
placeholder=
"Filter"
class=
"js-filtered-dropdown-input dropdown-input-field"
/>
<icon
class=
"dropdown-input-search"
name=
"search"
/>
</div>
<div
class=
"dropdown-content"
>
<ul>
<li
v-for=
"(result, i) in filteredResults"
:key=
"i"
class=
"js-filtered-dropdown-result"
>
<slot
name=
"result"
:result=
"result"
>
{{
result
[
filterKey
]
}}
</slot>
</li>
</ul>
</div>
</div>
</div>
</div>
</
template
>
app/assets/stylesheets/pages/merge_requests.scss
View file @
25170fbe
...
@@ -47,7 +47,6 @@
...
@@ -47,7 +47,6 @@
}
}
}
}
.mr-widget-heading
{
.mr-widget-heading
{
position
:
relative
;
position
:
relative
;
border
:
1px
solid
$border-color
;
border
:
1px
solid
$border-color
;
...
@@ -468,7 +467,6 @@
...
@@ -468,7 +467,6 @@
margin-bottom
:
2px
;
margin-bottom
:
2px
;
.ci-status-link
{
.ci-status-link
{
svg
{
svg
{
height
:
16px
;
height
:
16px
;
width
:
16px
;
width
:
16px
;
...
@@ -698,7 +696,6 @@
...
@@ -698,7 +696,6 @@
.table-holder
{
.table-holder
{
.ci-table
{
.ci-table
{
th
{
th
{
background-color
:
$white-light
;
background-color
:
$white-light
;
color
:
$gl-text-color-secondary
;
color
:
$gl-text-color-secondary
;
...
@@ -775,7 +772,7 @@
...
@@ -775,7 +772,7 @@
&
.affix
{
&
.affix
{
left
:
0
;
left
:
0
;
transition
:
right
.15s
;
transition
:
right
0
.15s
;
@include
media-breakpoint-down
(
xs
)
{
@include
media-breakpoint-down
(
xs
)
{
right
:
0
;
right
:
0
;
...
@@ -884,7 +881,7 @@
...
@@ -884,7 +881,7 @@
}
}
>
*
:not
(
:last-child
)
{
>
*
:not
(
:last-child
)
{
margin-right
:
.3em
;
margin-right
:
0
.3em
;
}
}
svg
{
svg
{
...
@@ -907,6 +904,10 @@
...
@@ -907,6 +904,10 @@
.btn
svg
{
.btn
svg
{
fill
:
$theme-gray-700
;
fill
:
$theme-gray-700
;
}
}
.dropdown-menu
{
width
:
400px
;
}
}
}
// Hack alert: we've rewritten `btn` class in a way that
// Hack alert: we've rewritten `btn` class in a way that
...
@@ -917,7 +918,7 @@
...
@@ -917,7 +918,7 @@
&
[
disabled
]
{
&
[
disabled
]
{
cursor
:
not
-
allowed
;
cursor
:
not
-
allowed
;
box-shadow
:
none
;
box-shadow
:
none
;
opacity
:
.65
;
opacity
:
0
.65
;
&
:hover
{
&
:hover
{
color
:
$gl-gray-500
;
color
:
$gl-gray-500
;
...
...
app/controllers/projects/merge_requests_controller.rb
View file @
25170fbe
...
@@ -14,6 +14,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
...
@@ -14,6 +14,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action
:set_issuables_index
,
only:
[
:index
]
before_action
:set_issuables_index
,
only:
[
:index
]
before_action
:authenticate_user!
,
only:
[
:assign_related_issues
]
before_action
:authenticate_user!
,
only:
[
:assign_related_issues
]
before_action
:check_user_can_push_to_source_branch!
,
only:
[
:rebase
]
before_action
:check_user_can_push_to_source_branch!
,
only:
[
:rebase
]
before_action
do
push_frontend_feature_flag
(
:ci_environments_status_changes
)
end
def
index
def
index
@merge_requests
=
@issuables
@merge_requests
=
@issuables
...
...
changelogs/unreleased/fe-ac-review-app-changes-33418.yml
0 → 100644
View file @
25170fbe
---
title
:
Adds filtered dropdown with changed files in review
merge_request
:
author
:
type
:
changed
locale/gitlab.pot
View file @
25170fbe
...
@@ -6717,6 +6717,9 @@ msgstr ""
...
@@ -6717,6 +6717,9 @@ msgstr ""
msgid "Version"
msgid "Version"
msgstr ""
msgstr ""
msgid "View app"
msgstr ""
msgid "View file @ "
msgid "View file @ "
msgstr ""
msgstr ""
...
...
spec/javascripts/vue_mr_widget/components/deployment_spec.js
View file @
25170fbe
...
@@ -14,6 +14,20 @@ const deploymentMockData = {
...
@@ -14,6 +14,20 @@ const deploymentMockData = {
external_url_formatted
:
'
diplo.
'
,
external_url_formatted
:
'
diplo.
'
,
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
deployed_at_formatted
:
'
Mar 22, 2017 10:44pm
'
,
deployed_at_formatted
:
'
Mar 22, 2017 10:44pm
'
,
changes
:
[
{
path
:
'
index.html
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/index.html
'
,
},
{
path
:
'
imgs/gallery.html
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html
'
,
},
{
path
:
'
about/
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/about/
'
,
},
],
};
};
const
createComponent
=
()
=>
{
const
createComponent
=
()
=>
{
const
Component
=
Vue
.
extend
(
deploymentComponent
);
const
Component
=
Vue
.
extend
(
deploymentComponent
);
...
@@ -176,4 +190,42 @@ describe('Deployment component', () => {
...
@@ -176,4 +190,42 @@ describe('Deployment component', () => {
expect
(
el
.
querySelector
(
'
.js-mr-memory-usage
'
)).
not
.
toBeNull
();
expect
(
el
.
querySelector
(
'
.js-mr-memory-usage
'
)).
not
.
toBeNull
();
});
});
});
});
describe
(
'
with `features.ciEnvironmentsStatusChanges` enabled
'
,
()
=>
{
beforeEach
(()
=>
{
window
.
gon
=
window
.
gon
||
{};
window
.
gon
.
features
=
window
.
gon
.
features
||
{};
window
.
gon
.
features
.
ciEnvironmentsStatusChanges
=
true
;
vm
=
createComponent
(
deploymentMockData
);
});
afterEach
(()
=>
{
window
.
gon
.
features
=
{};
});
it
(
'
renders dropdown with changes
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-mr-wigdet-deployment-dropdown
'
)).
not
.
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.js-deploy-url-feature-flag
'
)).
toBeNull
();
});
});
describe
(
'
with `features.ciEnvironmentsStatusChanges` disabled
'
,
()
=>
{
beforeEach
(()
=>
{
window
.
gon
=
window
.
gon
||
{};
window
.
gon
.
features
=
window
.
gon
.
features
||
{};
window
.
gon
.
features
.
ciEnvironmentsStatusChanges
=
false
;
vm
=
createComponent
(
deploymentMockData
);
});
afterEach
(()
=>
{
delete
window
.
gon
.
features
.
ciEnvironmentsStatusChanges
;
});
it
(
'
renders the old link to the review app
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-mr-wigdet-deployment-dropdown
'
)).
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.js-deploy-url-feature-flag
'
)).
not
.
toBeNull
();
});
});
});
});
spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
View file @
25170fbe
...
@@ -7,11 +7,12 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
...
@@ -7,11 +7,12 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
import
mockData
from
'
./mock_data
'
;
import
mockData
from
'
./mock_data
'
;
import
{
faviconDataUrl
,
overlayDataUrl
,
faviconWithOverlayDataUrl
}
from
'
../lib/utils/mock_data
'
;
import
{
faviconDataUrl
,
overlayDataUrl
,
faviconWithOverlayDataUrl
}
from
'
../lib/utils/mock_data
'
;
const
returnPromise
=
data
=>
new
Promise
((
resolve
)
=>
{
const
returnPromise
=
data
=>
new
Promise
(
resolve
=>
{
resolve
({
resolve
({
data
,
data
,
});
});
});
});
describe
(
'
mrWidgetOptions
'
,
()
=>
{
describe
(
'
mrWidgetOptions
'
,
()
=>
{
let
vm
;
let
vm
;
...
@@ -135,7 +136,7 @@ describe('mrWidgetOptions', () => {
...
@@ -135,7 +136,7 @@ describe('mrWidgetOptions', () => {
describe
(
'
methods
'
,
()
=>
{
describe
(
'
methods
'
,
()
=>
{
describe
(
'
checkStatus
'
,
()
=>
{
describe
(
'
checkStatus
'
,
()
=>
{
it
(
'
should tell service to check status
'
,
(
done
)
=>
{
it
(
'
should tell service to check status
'
,
done
=>
{
spyOn
(
vm
.
service
,
'
checkStatus
'
).
and
.
returnValue
(
returnPromise
(
mockData
));
spyOn
(
vm
.
service
,
'
checkStatus
'
).
and
.
returnValue
(
returnPromise
(
mockData
));
spyOn
(
vm
.
mr
,
'
setData
'
);
spyOn
(
vm
.
mr
,
'
setData
'
);
spyOn
(
vm
,
'
handleNotification
'
);
spyOn
(
vm
,
'
handleNotification
'
);
...
@@ -185,7 +186,7 @@ describe('mrWidgetOptions', () => {
...
@@ -185,7 +186,7 @@ describe('mrWidgetOptions', () => {
});
});
describe
(
'
fetchDeployments
'
,
()
=>
{
describe
(
'
fetchDeployments
'
,
()
=>
{
it
(
'
should fetch deployments
'
,
(
done
)
=>
{
it
(
'
should fetch deployments
'
,
done
=>
{
spyOn
(
vm
.
service
,
'
fetchDeployments
'
).
and
.
returnValue
(
returnPromise
([{
id
:
1
}]));
spyOn
(
vm
.
service
,
'
fetchDeployments
'
).
and
.
returnValue
(
returnPromise
([{
id
:
1
}]));
vm
.
fetchDeployments
();
vm
.
fetchDeployments
();
...
@@ -200,7 +201,7 @@ describe('mrWidgetOptions', () => {
...
@@ -200,7 +201,7 @@ describe('mrWidgetOptions', () => {
});
});
describe
(
'
fetchActionsContent
'
,
()
=>
{
describe
(
'
fetchActionsContent
'
,
()
=>
{
it
(
'
should fetch content of Cherry Pick and Revert modals
'
,
(
done
)
=>
{
it
(
'
should fetch content of Cherry Pick and Revert modals
'
,
done
=>
{
spyOn
(
vm
.
service
,
'
fetchMergeActionsContent
'
).
and
.
returnValue
(
returnPromise
(
'
hello world
'
));
spyOn
(
vm
.
service
,
'
fetchMergeActionsContent
'
).
and
.
returnValue
(
returnPromise
(
'
hello world
'
));
vm
.
fetchActionsContent
();
vm
.
fetchActionsContent
();
...
@@ -251,7 +252,7 @@ describe('mrWidgetOptions', () => {
...
@@ -251,7 +252,7 @@ describe('mrWidgetOptions', () => {
};
};
const
allArgs
=
eventHub
.
$on
.
calls
.
allArgs
();
const
allArgs
=
eventHub
.
$on
.
calls
.
allArgs
();
allArgs
.
forEach
(
(
params
)
=>
{
allArgs
.
forEach
(
params
=>
{
const
eventName
=
params
[
0
];
const
eventName
=
params
[
0
];
const
callback
=
params
[
1
];
const
callback
=
params
[
1
];
...
@@ -270,18 +271,6 @@ describe('mrWidgetOptions', () => {
...
@@ -270,18 +271,6 @@ describe('mrWidgetOptions', () => {
});
});
});
});
describe
(
'
handleMounted
'
,
()
=>
{
it
(
'
should call required methods to do the initial kick-off
'
,
()
=>
{
spyOn
(
vm
,
'
initDeploymentsPolling
'
);
spyOn
(
vm
,
'
setFaviconHelper
'
);
vm
.
handleMounted
();
expect
(
vm
.
setFaviconHelper
).
toHaveBeenCalled
();
expect
(
vm
.
initDeploymentsPolling
).
toHaveBeenCalled
();
});
});
describe
(
'
setFavicon
'
,
()
=>
{
describe
(
'
setFavicon
'
,
()
=>
{
let
faviconElement
;
let
faviconElement
;
...
@@ -298,9 +287,10 @@ describe('mrWidgetOptions', () => {
...
@@ -298,9 +287,10 @@ describe('mrWidgetOptions', () => {
document
.
body
.
removeChild
(
document
.
getElementById
(
'
favicon
'
));
document
.
body
.
removeChild
(
document
.
getElementById
(
'
favicon
'
));
});
});
it
(
'
should call setFavicon method
'
,
(
done
)
=>
{
it
(
'
should call setFavicon method
'
,
done
=>
{
vm
.
mr
.
ciStatusFaviconPath
=
overlayDataUrl
;
vm
.
mr
.
ciStatusFaviconPath
=
overlayDataUrl
;
vm
.
setFaviconHelper
().
then
(()
=>
{
vm
.
setFaviconHelper
()
.
then
(()
=>
{
expect
(
faviconElement
.
getAttribute
(
'
href
'
)).
toEqual
(
faviconWithOverlayDataUrl
);
expect
(
faviconElement
.
getAttribute
(
'
href
'
)).
toEqual
(
faviconWithOverlayDataUrl
);
done
();
done
();
})
})
...
@@ -379,7 +369,7 @@ describe('mrWidgetOptions', () => {
...
@@ -379,7 +369,7 @@ describe('mrWidgetOptions', () => {
});
});
describe
(
'
rendering relatedLinks
'
,
()
=>
{
describe
(
'
rendering relatedLinks
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
mr
.
relatedLinks
=
{
vm
.
mr
.
relatedLinks
=
{
assignToMe
:
null
,
assignToMe
:
null
,
closing
:
`
closing
:
`
...
@@ -396,7 +386,7 @@ describe('mrWidgetOptions', () => {
...
@@ -396,7 +386,7 @@ describe('mrWidgetOptions', () => {
expect
(
vm
.
$el
.
querySelector
(
'
.close-related-link
'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelector
(
'
.close-related-link
'
)).
toBeDefined
();
});
});
it
(
'
does not render if state is nothingToMerge
'
,
(
done
)
=>
{
it
(
'
does not render if state is nothingToMerge
'
,
done
=>
{
vm
.
mr
.
state
=
stateKey
.
nothingToMerge
;
vm
.
mr
.
state
=
stateKey
.
nothingToMerge
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.close-related-link
'
)).
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.close-related-link
'
)).
toBeNull
();
...
@@ -406,7 +396,7 @@ describe('mrWidgetOptions', () => {
...
@@ -406,7 +396,7 @@ describe('mrWidgetOptions', () => {
});
});
describe
(
'
rendering source branch removal status
'
,
()
=>
{
describe
(
'
rendering source branch removal status
'
,
()
=>
{
it
(
'
renders when user cannot remove branch and branch should be removed
'
,
(
done
)
=>
{
it
(
'
renders when user cannot remove branch and branch should be removed
'
,
done
=>
{
vm
.
mr
.
canRemoveSourceBranch
=
false
;
vm
.
mr
.
canRemoveSourceBranch
=
false
;
vm
.
mr
.
shouldRemoveSourceBranch
=
true
;
vm
.
mr
.
shouldRemoveSourceBranch
=
true
;
vm
.
mr
.
state
=
'
readyToMerge
'
;
vm
.
mr
.
state
=
'
readyToMerge
'
;
...
@@ -423,7 +413,7 @@ describe('mrWidgetOptions', () => {
...
@@ -423,7 +413,7 @@ describe('mrWidgetOptions', () => {
});
});
});
});
it
(
'
does not render in merged state
'
,
(
done
)
=>
{
it
(
'
does not render in merged state
'
,
done
=>
{
vm
.
mr
.
canRemoveSourceBranch
=
false
;
vm
.
mr
.
canRemoveSourceBranch
=
false
;
vm
.
mr
.
shouldRemoveSourceBranch
=
true
;
vm
.
mr
.
shouldRemoveSourceBranch
=
true
;
vm
.
mr
.
state
=
'
merged
'
;
vm
.
mr
.
state
=
'
merged
'
;
...
@@ -438,6 +428,20 @@ describe('mrWidgetOptions', () => {
...
@@ -438,6 +428,20 @@ describe('mrWidgetOptions', () => {
});
});
describe
(
'
rendering deployments
'
,
()
=>
{
describe
(
'
rendering deployments
'
,
()
=>
{
const
changes
=
[
{
path
:
'
index.html
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/index.html
'
,
},
{
path
:
'
imgs/gallery.html
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html
'
,
},
{
path
:
'
about/
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/about/
'
,
},
];
const
deploymentMockData
=
{
const
deploymentMockData
=
{
id
:
15
,
id
:
15
,
name
:
'
review/diplo
'
,
name
:
'
review/diplo
'
,
...
@@ -449,15 +453,23 @@ describe('mrWidgetOptions', () => {
...
@@ -449,15 +453,23 @@ describe('mrWidgetOptions', () => {
external_url_formatted
:
'
diplo.
'
,
external_url_formatted
:
'
diplo.
'
,
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
deployed_at_formatted
:
'
Mar 22, 2017 10:44pm
'
,
deployed_at_formatted
:
'
Mar 22, 2017 10:44pm
'
,
changes
,
};
};
beforeEach
((
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
mr
.
deployments
.
push
({
window
.
gon
=
window
.
gon
||
{};
window
.
gon
.
features
=
window
.
gon
.
features
||
{};
window
.
gon
.
features
.
ciEnvironmentsStatusChanges
=
true
;
vm
.
mr
.
deployments
.
push
(
{
...
deploymentMockData
,
...
deploymentMockData
,
},
{
},
{
...
deploymentMockData
,
...
deploymentMockData
,
id
:
deploymentMockData
.
id
+
1
,
id
:
deploymentMockData
.
id
+
1
,
});
},
);
vm
.
$nextTick
(
done
);
vm
.
$nextTick
(
done
);
});
});
...
@@ -465,5 +477,13 @@ describe('mrWidgetOptions', () => {
...
@@ -465,5 +477,13 @@ describe('mrWidgetOptions', () => {
it
(
'
renders multiple deployments
'
,
()
=>
{
it
(
'
renders multiple deployments
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.deploy-heading
'
).
length
).
toBe
(
2
);
expect
(
vm
.
$el
.
querySelectorAll
(
'
.deploy-heading
'
).
length
).
toBe
(
2
);
});
});
it
(
'
renders dropdpown with multiple file changes
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-mr-wigdet-deployment-dropdown
'
)
.
querySelectorAll
(
'
.js-filtered-dropdown-result
'
).
length
,
).
toEqual
(
changes
.
length
);
});
});
});
});
});
spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
0 → 100644
View file @
25170fbe
import
Vue
from
'
vue
'
;
import
component
from
'
~/vue_shared/components/filtered_search_dropdown.vue
'
;
import
mountComponent
from
'
spec/helpers/vue_mount_component_helper
'
;
describe
(
'
Filtered search dropdown
'
,
()
=>
{
const
Component
=
Vue
.
extend
(
component
);
let
vm
;
afterEach
(()
=>
{
vm
.
$destroy
();
});
describe
(
'
with an empty array of items
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
items
:
[],
filterKey
:
''
,
});
});
it
(
'
renders empty list
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-filtered-dropdown-result
'
).
length
).
toEqual
(
0
);
});
it
(
'
renders filter input
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-filtered-dropdown-input
'
)).
not
.
toBeNull
();
});
});
describe
(
'
when visible numbers is less than the items length
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
items
:
[{
title
:
'
One
'
},
{
title
:
'
Two
'
},
{
title
:
'
Three
'
}],
visibleItems
:
2
,
filterKey
:
'
title
'
,
});
});
it
(
'
it renders only the maximum number provided
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-filtered-dropdown-result
'
).
length
).
toEqual
(
2
);
});
});
describe
(
'
when visible number is bigger than the items lenght
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
items
:
[{
title
:
'
One
'
},
{
title
:
'
Two
'
},
{
title
:
'
Three
'
}],
filterKey
:
'
title
'
,
});
});
it
(
'
it renders the full list of items the maximum number provided
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-filtered-dropdown-result
'
).
length
).
toEqual
(
3
);
});
});
describe
(
'
while filtering
'
,
()
=>
{
beforeEach
(()
=>
{
vm
=
mountComponent
(
Component
,
{
items
:
[
{
title
:
'
One
'
},
{
title
:
'
Two/three
'
},
{
title
:
'
Three four
'
},
{
title
:
'
Five
'
},
],
filterKey
:
'
title
'
,
});
});
it
(
'
updates the results to match the typed value
'
,
done
=>
{
vm
.
$el
.
querySelector
(
'
.js-filtered-dropdown-input
'
).
value
=
'
three
'
;
vm
.
$el
.
querySelector
(
'
.js-filtered-dropdown-input
'
).
dispatchEvent
(
new
Event
(
'
input
'
));
vm
.
$nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-filtered-dropdown-result
'
).
length
).
toEqual
(
2
);
done
();
});
});
describe
(
'
when no value matches the typed one
'
,
()
=>
{
it
(
'
does not render any result
'
,
done
=>
{
vm
.
$el
.
querySelector
(
'
.js-filtered-dropdown-input
'
).
value
=
'
six
'
;
vm
.
$el
.
querySelector
(
'
.js-filtered-dropdown-input
'
).
dispatchEvent
(
new
Event
(
'
input
'
));
vm
.
$nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.js-filtered-dropdown-result
'
).
length
).
toEqual
(
0
);
done
();
});
});
});
});
});
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