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
7b9d0be2
Commit
7b9d0be2
authored
Oct 22, 2018
by
Filipa Lacerda
Committed by
Phil Hughes
Oct 22, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EE port of Frontend: Review app changes
parent
53b14341
Changes
10
Hide 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 @
7b9d0be2
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.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
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
import
LoadingButton
from
'
../../vue_shared/components/loading_button.vue
'
;
...
...
@@ -18,6 +19,7 @@ export default {
StatusIcon
,
Icon
,
TooltipOnTruncate
,
FilteredSearchDropdown
,
},
directives
:
{
tooltip
,
...
...
@@ -30,8 +32,10 @@ export default {
},
},
data
()
{
const
features
=
window
.
gon
.
features
||
{};
return
{
isStopping
:
false
,
enableCiEnvironmentsStatusChanges
:
features
.
ciEnvironmentsStatusChanges
,
};
},
computed
:
{
...
...
@@ -118,18 +122,65 @@ export default {
/>
</div>
<div>
<a
v-if=
"hasExternalUrls"
:href=
"deployment.external_url"
target=
"_blank"
rel=
"noopener noreferrer nofollow"
class=
"deploy-link js-deploy-url btn btn-default btn-sm inline"
>
<span>
View app
<icon
name=
"external-link"
/>
</span>
</a>
<
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
: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"
target=
"_blank"
rel=
"noopener noreferrer nofollow"
class=
"js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inline"
>
<span>
{{ __('View app') }}
<icon
name=
"external-link"
/>
</span>
</a>
</template>
<loading-button
v-if=
"deployment.stop_url"
:loading=
"isStopping"
...
...
app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
View file @
7b9d0be2
...
...
@@ -112,7 +112,8 @@ export default {
eventHub
.
$on
(
'
mr.discussion.updated
'
,
this
.
checkStatus
);
},
mounted
()
{
this
.
handleMounted
();
this
.
setFaviconHelper
();
this
.
initDeploymentsPolling
();
},
beforeDestroy
()
{
eventHub
.
$off
(
'
mr.discussion.updated
'
,
this
.
checkStatus
);
...
...
@@ -251,10 +252,6 @@ export default {
this
.
stopPolling
();
});
},
handleMounted
()
{
this
.
setFaviconHelper
();
this
.
initDeploymentsPolling
();
},
},
};
</
script
>
...
...
app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
0 → 100644
View file @
7b9d0be2
<
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 @
7b9d0be2
...
...
@@ -47,7 +47,6 @@
}
}
.mr-widget-heading
{
position
:
relative
;
border
:
1px
solid
$border-color
;
...
...
@@ -454,7 +453,7 @@
.mr-list
{
.merge-request
{
padding
:
10px
0
10px
15px
;
padding
:
10px
0
10px
15px
;
position
:
relative
;
display
:
-
webkit-flex
;
display
:
flex
;
...
...
@@ -468,7 +467,6 @@
margin-bottom
:
2px
;
.ci-status-link
{
svg
{
height
:
16px
;
width
:
16px
;
...
...
@@ -698,7 +696,6 @@
.table-holder
{
.ci-table
{
th
{
background-color
:
$white-light
;
color
:
$gl-text-color-secondary
;
...
...
@@ -775,7 +772,7 @@
&
.affix
{
left
:
0
;
transition
:
right
.15s
;
transition
:
right
0
.15s
;
@include
media-breakpoint-down
(
xs
)
{
right
:
0
;
...
...
@@ -884,7 +881,7 @@
}
>
*
:not
(
:last-child
)
{
margin-right
:
.3em
;
margin-right
:
0
.3em
;
}
svg
{
...
...
@@ -907,6 +904,10 @@
.btn
svg
{
fill
:
$theme-gray-700
;
}
.dropdown-menu
{
width
:
400px
;
}
}
// Hack alert: we've rewritten `btn` class in a way that
...
...
@@ -917,7 +918,7 @@
&
[
disabled
]
{
cursor
:
not
-
allowed
;
box-shadow
:
none
;
opacity
:
.65
;
opacity
:
0
.65
;
&
:hover
{
color
:
$gl-gray-500
;
...
...
app/controllers/projects/merge_requests_controller.rb
View file @
7b9d0be2
...
...
@@ -17,6 +17,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action
:set_issuables_index
,
only:
[
:index
]
before_action
:authenticate_user!
,
only:
[
:assign_related_issues
]
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
@merge_requests
=
@issuables
...
...
changelogs/unreleased/fe-ac-review-app-changes-33418.yml
0 → 100644
View file @
7b9d0be2
---
title
:
Adds filtered dropdown with changed files in review
merge_request
:
author
:
type
:
changed
locale/gitlab.pot
View file @
7b9d0be2
...
...
@@ -8523,6 +8523,9 @@ msgstr ""
msgid "Version"
msgstr ""
msgid "View app"
msgstr ""
msgid "View epics list"
msgstr ""
...
...
spec/javascripts/vue_mr_widget/components/deployment_spec.js
View file @
7b9d0be2
...
...
@@ -14,6 +14,20 @@ const deploymentMockData = {
external_url_formatted
:
'
diplo.
'
,
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
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
Component
=
Vue
.
extend
(
deploymentComponent
);
...
...
@@ -176,4 +190,42 @@ describe('Deployment component', () => {
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 @
7b9d0be2
...
...
@@ -7,11 +7,12 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
import
mockData
from
'
./mock_data
'
;
import
{
faviconDataUrl
,
overlayDataUrl
,
faviconWithOverlayDataUrl
}
from
'
../lib/utils/mock_data
'
;
const
returnPromise
=
data
=>
new
Promise
((
resolve
)
=>
{
resolve
({
data
,
const
returnPromise
=
data
=>
new
Promise
(
resolve
=>
{
resolve
({
data
,
});
});
});
describe
(
'
mrWidgetOptions
'
,
()
=>
{
let
vm
;
...
...
@@ -135,7 +136,7 @@ describe('mrWidgetOptions', () => {
describe
(
'
methods
'
,
()
=>
{
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
.
mr
,
'
setData
'
);
spyOn
(
vm
,
'
handleNotification
'
);
...
...
@@ -185,7 +186,7 @@ describe('mrWidgetOptions', () => {
});
describe
(
'
fetchDeployments
'
,
()
=>
{
it
(
'
should fetch deployments
'
,
(
done
)
=>
{
it
(
'
should fetch deployments
'
,
done
=>
{
spyOn
(
vm
.
service
,
'
fetchDeployments
'
).
and
.
returnValue
(
returnPromise
([{
id
:
1
}]));
vm
.
fetchDeployments
();
...
...
@@ -200,7 +201,7 @@ describe('mrWidgetOptions', () => {
});
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
'
));
vm
.
fetchActionsContent
();
...
...
@@ -251,7 +252,7 @@ describe('mrWidgetOptions', () => {
};
const
allArgs
=
eventHub
.
$on
.
calls
.
allArgs
();
allArgs
.
forEach
(
(
params
)
=>
{
allArgs
.
forEach
(
params
=>
{
const
eventName
=
params
[
0
];
const
callback
=
params
[
1
];
...
...
@@ -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
'
,
()
=>
{
let
faviconElement
;
...
...
@@ -298,13 +287,14 @@ describe('mrWidgetOptions', () => {
document
.
body
.
removeChild
(
document
.
getElementById
(
'
favicon
'
));
});
it
(
'
should call setFavicon method
'
,
(
done
)
=>
{
it
(
'
should call setFavicon method
'
,
done
=>
{
vm
.
mr
.
ciStatusFaviconPath
=
overlayDataUrl
;
vm
.
setFaviconHelper
().
then
(()
=>
{
expect
(
faviconElement
.
getAttribute
(
'
href
'
)).
toEqual
(
faviconWithOverlayDataUrl
);
done
();
})
.
catch
(
done
.
fail
);
vm
.
setFaviconHelper
()
.
then
(()
=>
{
expect
(
faviconElement
.
getAttribute
(
'
href
'
)).
toEqual
(
faviconWithOverlayDataUrl
);
done
();
})
.
catch
(
done
.
fail
);
});
it
(
'
should not call setFavicon when there is no ciStatusFaviconPath
'
,
()
=>
{
...
...
@@ -379,7 +369,7 @@ describe('mrWidgetOptions', () => {
});
describe
(
'
rendering relatedLinks
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
mr
.
relatedLinks
=
{
assignToMe
:
null
,
closing
:
`
...
...
@@ -396,7 +386,7 @@ describe('mrWidgetOptions', () => {
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
;
Vue
.
nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.close-related-link
'
)).
toBeNull
();
...
...
@@ -406,7 +396,7 @@ describe('mrWidgetOptions', () => {
});
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
.
shouldRemoveSourceBranch
=
true
;
vm
.
mr
.
state
=
'
readyToMerge
'
;
...
...
@@ -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
.
shouldRemoveSourceBranch
=
true
;
vm
.
mr
.
state
=
'
merged
'
;
...
...
@@ -438,6 +428,20 @@ describe('mrWidgetOptions', () => {
});
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
=
{
id
:
15
,
name
:
'
review/diplo
'
,
...
...
@@ -449,15 +453,23 @@ describe('mrWidgetOptions', () => {
external_url_formatted
:
'
diplo.
'
,
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
deployed_at_formatted
:
'
Mar 22, 2017 10:44pm
'
,
changes
,
};
beforeEach
((
done
)
=>
{
vm
.
mr
.
deployments
.
push
({
...
deploymentMockData
,
},
{
...
deploymentMockData
,
id
:
deploymentMockData
.
id
+
1
,
});
beforeEach
(
done
=>
{
window
.
gon
=
window
.
gon
||
{};
window
.
gon
.
features
=
window
.
gon
.
features
||
{};
window
.
gon
.
features
.
ciEnvironmentsStatusChanges
=
true
;
vm
.
mr
.
deployments
.
push
(
{
...
deploymentMockData
,
},
{
...
deploymentMockData
,
id
:
deploymentMockData
.
id
+
1
,
},
);
vm
.
$nextTick
(
done
);
});
...
...
@@ -465,5 +477,13 @@ describe('mrWidgetOptions', () => {
it
(
'
renders multiple deployments
'
,
()
=>
{
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 @
7b9d0be2
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