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
da8c9e8a
Commit
da8c9e8a
authored
Nov 10, 2020
by
Dylan Griffith
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Merge branch '241691-left-side-facets' into 'master'"
This reverts merge request !46595
parent
7721a229
Changes
20
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
487 additions
and
247 deletions
+487
-247
app/assets/javascripts/search/dropdown_filter/components/dropdown_filter.vue
...pts/search/dropdown_filter/components/dropdown_filter.vue
+108
-0
app/assets/javascripts/search/dropdown_filter/constants/confidential_filter_data.js
...rch/dropdown_filter/constants/confidential_filter_data.js
+36
-0
app/assets/javascripts/search/dropdown_filter/constants/state_filter_data.js
...pts/search/dropdown_filter/constants/state_filter_data.js
+42
-0
app/assets/javascripts/search/dropdown_filter/index.js
app/assets/javascripts/search/dropdown_filter/index.js
+38
-0
app/assets/javascripts/search/index.js
app/assets/javascripts/search/index.js
+7
-1
app/assets/javascripts/search/sidebar/components/app.vue
app/assets/javascripts/search/sidebar/components/app.vue
+0
-41
app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue
...ipts/search/sidebar/components/confidentiality_filter.vue
+0
-1
app/assets/javascripts/search/sidebar/components/status_filter.vue
...s/javascripts/search/sidebar/components/status_filter.vue
+0
-1
app/assets/javascripts/search/sidebar/index.js
app/assets/javascripts/search/sidebar/index.js
+19
-4
app/assets/javascripts/search/store/actions.js
app/assets/javascripts/search/store/actions.js
+0
-9
app/controllers/search_controller.rb
app/controllers/search_controller.rb
+4
-0
app/views/search/_results.html.haml
app/views/search/_results.html.haml
+17
-22
app/views/search/results/_filters.html.haml
app/views/search/results/_filters.html.haml
+6
-0
changelogs/unreleased/241691-left-side-facets.yml
changelogs/unreleased/241691-left-side-facets.yml
+0
-5
config/feature_flags/development/search_facets.yml
config/feature_flags/development/search_facets.yml
+7
-0
locale/gitlab.pot
locale/gitlab.pot
+0
-3
spec/frontend/search/dropdown_filter/components/dropdown_filter_spec.js
...search/dropdown_filter/components/dropdown_filter_spec.js
+198
-0
spec/frontend/search/sidebar/components/app_spec.js
spec/frontend/search/sidebar/components/app_spec.js
+0
-99
spec/frontend/search/store/actions_spec.js
spec/frontend/search/store/actions_spec.js
+0
-42
spec/views/search/_results.html.haml_spec.rb
spec/views/search/_results.html.haml_spec.rb
+5
-19
No files found.
app/assets/javascripts/search/dropdown_filter/components/dropdown_filter.vue
0 → 100644
View file @
da8c9e8a
<
script
>
import
{
mapState
}
from
'
vuex
'
;
import
{
GlDropdown
,
GlDropdownItem
,
GlDropdownDivider
}
from
'
@gitlab/ui
'
;
import
{
setUrlParams
,
visitUrl
}
from
'
~/lib/utils/url_utility
'
;
import
{
sprintf
,
s__
}
from
'
~/locale
'
;
export
default
{
name
:
'
DropdownFilter
'
,
components
:
{
GlDropdown
,
GlDropdownItem
,
GlDropdownDivider
,
},
props
:
{
filterData
:
{
type
:
Object
,
required
:
true
,
},
},
computed
:
{
...
mapState
([
'
query
'
]),
scope
()
{
return
this
.
query
.
scope
;
},
supportedScopes
()
{
return
Object
.
values
(
this
.
filterData
.
scopes
);
},
initialFilter
()
{
return
this
.
query
[
this
.
filterData
.
filterParam
];
},
filter
()
{
return
this
.
initialFilter
||
this
.
filterData
.
filters
.
ANY
.
value
;
},
filtersArray
()
{
return
this
.
filterData
.
filterByScope
[
this
.
scope
];
},
selectedFilter
:
{
get
()
{
if
(
this
.
filtersArray
.
some
(({
value
})
=>
value
===
this
.
filter
))
{
return
this
.
filter
;
}
return
this
.
filterData
.
filters
.
ANY
.
value
;
},
set
(
filter
)
{
// we need to remove the pagination cursor to ensure the
// relevancy of the new results
visitUrl
(
setUrlParams
({
page
:
null
,
[
this
.
filterData
.
filterParam
]:
filter
,
}),
);
},
},
selectedFilterText
()
{
const
f
=
this
.
filtersArray
.
find
(({
value
})
=>
value
===
this
.
selectedFilter
);
if
(
!
f
||
f
===
this
.
filterData
.
filters
.
ANY
)
{
return
sprintf
(
s__
(
'
Any %{header}
'
),
{
header
:
this
.
filterData
.
header
});
}
return
f
.
label
;
},
showDropdown
()
{
return
this
.
supportedScopes
.
includes
(
this
.
scope
);
},
},
methods
:
{
dropDownItemClass
(
filter
)
{
return
{
'
gl-border-b-solid gl-border-b-gray-100 gl-border-b-1 gl-pb-2! gl-mb-2
'
:
filter
===
this
.
filterData
.
filters
.
ANY
,
};
},
isFilterSelected
(
filter
)
{
return
filter
===
this
.
selectedFilter
;
},
handleFilterChange
(
filter
)
{
this
.
selectedFilter
=
filter
;
},
},
};
</
script
>
<
template
>
<gl-dropdown
v-if=
"showDropdown"
:text=
"selectedFilterText"
class=
"col-3 gl-pt-4 gl-pl-0 gl-pr-0 gl-mr-4"
menu-class=
"gl-w-full! gl-pl-0"
>
<header
class=
"gl-text-center gl-font-weight-bold gl-font-lg"
>
{{
filterData
.
header
}}
</header>
<gl-dropdown-divider
/>
<gl-dropdown-item
v-for=
"f in filtersArray"
:key=
"f.value"
:is-check-item=
"true"
:is-checked=
"isFilterSelected(f.value)"
:class=
"dropDownItemClass(f)"
@
click=
"handleFilterChange(f.value)"
>
{{
f
.
label
}}
</gl-dropdown-item>
</gl-dropdown>
</
template
>
app/assets/javascripts/search/dropdown_filter/constants/confidential_filter_data.js
0 → 100644
View file @
da8c9e8a
import
{
__
}
from
'
~/locale
'
;
const
header
=
__
(
'
Confidentiality
'
);
const
filters
=
{
ANY
:
{
label
:
__
(
'
Any
'
),
value
:
null
,
},
CONFIDENTIAL
:
{
label
:
__
(
'
Confidential
'
),
value
:
'
yes
'
,
},
NOT_CONFIDENTIAL
:
{
label
:
__
(
'
Not confidential
'
),
value
:
'
no
'
,
},
};
const
scopes
=
{
ISSUES
:
'
issues
'
,
};
const
filterByScope
=
{
[
scopes
.
ISSUES
]:
[
filters
.
ANY
,
filters
.
CONFIDENTIAL
,
filters
.
NOT_CONFIDENTIAL
],
};
const
filterParam
=
'
confidential
'
;
export
default
{
header
,
filters
,
scopes
,
filterByScope
,
filterParam
,
};
app/assets/javascripts/search/dropdown_filter/constants/state_filter_data.js
0 → 100644
View file @
da8c9e8a
import
{
__
}
from
'
~/locale
'
;
const
header
=
__
(
'
Status
'
);
const
filters
=
{
ANY
:
{
label
:
__
(
'
Any
'
),
value
:
'
all
'
,
},
OPEN
:
{
label
:
__
(
'
Open
'
),
value
:
'
opened
'
,
},
CLOSED
:
{
label
:
__
(
'
Closed
'
),
value
:
'
closed
'
,
},
MERGED
:
{
label
:
__
(
'
Merged
'
),
value
:
'
merged
'
,
},
};
const
scopes
=
{
ISSUES
:
'
issues
'
,
MERGE_REQUESTS
:
'
merge_requests
'
,
};
const
filterByScope
=
{
[
scopes
.
ISSUES
]:
[
filters
.
ANY
,
filters
.
OPEN
,
filters
.
CLOSED
],
[
scopes
.
MERGE_REQUESTS
]:
[
filters
.
ANY
,
filters
.
OPEN
,
filters
.
MERGED
,
filters
.
CLOSED
],
};
const
filterParam
=
'
state
'
;
export
default
{
header
,
filters
,
scopes
,
filterByScope
,
filterParam
,
};
app/assets/javascripts/search/dropdown_filter/index.js
0 → 100644
View file @
da8c9e8a
import
Vue
from
'
vue
'
;
import
Translate
from
'
~/vue_shared/translate
'
;
import
DropdownFilter
from
'
./components/dropdown_filter.vue
'
;
import
stateFilterData
from
'
./constants/state_filter_data
'
;
import
confidentialFilterData
from
'
./constants/confidential_filter_data
'
;
Vue
.
use
(
Translate
);
const
mountDropdownFilter
=
(
store
,
{
id
,
filterData
})
=>
{
const
el
=
document
.
getElementById
(
id
);
if
(
!
el
)
return
false
;
return
new
Vue
({
el
,
store
,
render
(
createElement
)
{
return
createElement
(
DropdownFilter
,
{
props
:
{
filterData
,
},
});
},
});
};
const
dropdownFilters
=
[
{
id
:
'
js-search-filter-by-state
'
,
filterData
:
stateFilterData
,
},
{
id
:
'
js-search-filter-by-confidential
'
,
filterData
:
confidentialFilterData
,
},
];
export
default
store
=>
[...
dropdownFilters
].
map
(
filter
=>
mountDropdownFilter
(
store
,
filter
));
app/assets/javascripts/search/index.js
View file @
da8c9e8a
import
{
queryToObject
}
from
'
~/lib/utils/url_utility
'
;
import
createStore
from
'
./store
'
;
import
initDropdownFilters
from
'
./dropdown_filter
'
;
import
{
initSidebar
}
from
'
./sidebar
'
;
import
initGroupFilter
from
'
./group_filter
'
;
export
default
()
=>
{
const
store
=
createStore
({
query
:
queryToObject
(
window
.
location
.
search
)
});
if
(
gon
.
features
.
searchFacets
)
{
initSidebar
(
store
);
}
else
{
initDropdownFilters
(
store
);
}
initGroupFilter
(
store
);
};
app/assets/javascripts/search/sidebar/components/app.vue
deleted
100644 → 0
View file @
7721a229
<
script
>
import
{
mapActions
,
mapState
}
from
'
vuex
'
;
import
{
GlButton
,
GlLink
}
from
'
@gitlab/ui
'
;
import
StatusFilter
from
'
./status_filter.vue
'
;
import
ConfidentialityFilter
from
'
./confidentiality_filter.vue
'
;
export
default
{
name
:
'
GlobalSearchSidebar
'
,
components
:
{
GlButton
,
GlLink
,
StatusFilter
,
ConfidentialityFilter
,
},
computed
:
{
...
mapState
([
'
query
'
]),
showReset
()
{
return
this
.
query
.
state
||
this
.
query
.
confidential
;
},
},
methods
:
{
...
mapActions
([
'
applyQuery
'
,
'
resetQuery
'
]),
},
};
</
script
>
<
template
>
<form
class=
"gl-display-flex gl-flex-direction-column col-md-3 gl-mr-4 gl-mb-6 gl-mb gl-mt-5"
@
submit.prevent=
"applyQuery"
>
<status-filter
/>
<confidentiality-filter
/>
<div
class=
"gl-display-flex gl-align-items-center gl-mt-3"
>
<gl-button
variant=
"success"
type=
"submit"
>
{{
__
(
'
Apply
'
)
}}
</gl-button>
<gl-link
v-if=
"showReset"
class=
"gl-ml-auto"
@
click=
"resetQuery"
>
{{
__
(
'
Reset filters
'
)
}}
</gl-link>
</div>
</form>
</
template
>
app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue
View file @
da8c9e8a
...
...
@@ -21,6 +21,5 @@ export default {
<
template
>
<div
v-if=
"showDropdown"
>
<radio-filter
:filter-data=
"$options.confidentialFilterData"
/>
<hr
class=
"gl-my-5 gl-border-gray-100"
/>
</div>
</
template
>
app/assets/javascripts/search/sidebar/components/status_filter.vue
View file @
da8c9e8a
...
...
@@ -21,6 +21,5 @@ export default {
<
template
>
<div
v-if=
"showDropdown"
>
<radio-filter
:filter-data=
"$options.stateFilterData"
/>
<hr
class=
"gl-my-5 gl-border-gray-100"
/>
</div>
</
template
>
app/assets/javascripts/search/sidebar/index.js
View file @
da8c9e8a
import
Vue
from
'
vue
'
;
import
Translate
from
'
~/vue_shared/translate
'
;
import
GlobalSearchSidebar
from
'
./components/app.vue
'
;
import
StatusFilter
from
'
./components/status_filter.vue
'
;
import
ConfidentialityFilter
from
'
./components/confidentiality_filter.vue
'
;
Vue
.
use
(
Translate
);
export
const
initSidebar
=
store
=>
{
const
el
=
document
.
getElementById
(
'
js-search-sidebar
'
);
const
mountRadioFilters
=
(
store
,
{
id
,
component
})
=>
{
const
el
=
document
.
getElementById
(
id
);
if
(
!
el
)
return
false
;
...
...
@@ -13,7 +14,21 @@ export const initSidebar = store => {
el
,
store
,
render
(
createElement
)
{
return
createElement
(
GlobalSearchSidebar
);
return
createElement
(
component
);
},
});
};
const
radioFilters
=
[
{
id
:
'
js-search-filter-by-state
'
,
component
:
StatusFilter
,
},
{
id
:
'
js-search-filter-by-confidential
'
,
component
:
ConfidentialityFilter
,
},
];
export
const
initSidebar
=
store
=>
[...
radioFilters
].
map
(
filter
=>
mountRadioFilters
(
store
,
filter
));
app/assets/javascripts/search/store/actions.js
View file @
da8c9e8a
import
Api
from
'
~/api
'
;
import
createFlash
from
'
~/flash
'
;
import
{
__
}
from
'
~/locale
'
;
import
{
visitUrl
,
setUrlParams
}
from
'
~/lib/utils/url_utility
'
;
import
*
as
types
from
'
./mutation_types
'
;
export
const
fetchGroups
=
({
commit
},
search
)
=>
{
...
...
@@ -19,11 +18,3 @@ export const fetchGroups = ({ commit }, search) => {
export
const
setQuery
=
({
commit
},
{
key
,
value
})
=>
{
commit
(
types
.
SET_QUERY
,
{
key
,
value
});
};
export
const
applyQuery
=
({
state
})
=>
{
visitUrl
(
setUrlParams
({
...
state
.
query
,
page
:
null
}));
};
export
const
resetQuery
=
({
state
})
=>
{
visitUrl
(
setUrlParams
({
...
state
.
query
,
page
:
null
,
state
:
null
,
confidential
:
null
}));
};
app/controllers/search_controller.rb
View file @
da8c9e8a
...
...
@@ -24,6 +24,10 @@ class SearchController < ApplicationController
search_term_present
&&
!
params
[
:project_id
].
present?
end
before_action
do
push_frontend_feature_flag
(
:search_facets
)
end
layout
'search'
feature_category
:global_search
...
...
app/views/search/_results.html.haml
View file @
da8c9e8a
-
if
@search_objects
.
to_a
.
empty?
.gl-display-md-flex
-
if
%w(issues merge_requests)
.
include?
(
@scope
)
#js-search-sidebar
.gl-display-flex.gl-flex-direction-column.col-md-3.gl-mr-4
{
}
.gl-w-full
=
render
partial:
"search/results/filters"
=
render
partial:
"search/results/empty"
=
render_if_exists
'shared/promotions/promote_advanced_search'
-
else
...
...
@@ -27,11 +24,9 @@
.gl-display-md-flex.gl-flex-direction-column
=
render
partial:
'search/sort_dropdown'
=
render_if_exists
'shared/promotions/promote_advanced_search'
=
render
partial:
"search/results/filters"
.results.gl-display-md-flex.gl-mt-3
-
if
%w(issues merge_requests)
.
include?
(
@scope
)
#js-search-sidebar
{
}
.gl-w-full
.results.gl-mt-3
-
if
@scope
==
'commits'
%ul
.content-list.commit-list
=
render
partial:
"search/results/commit"
,
collection:
@search_objects
...
...
app/views/search/results/_filters.html.haml
0 → 100644
View file @
da8c9e8a
.d-lg-flex.align-items-end
#js-search-filter-by-state
{
'v-cloak'
:
true
}
#js-search-filter-by-confidential
{
'v-cloak'
:
true
}
-
if
%w(issues merge_requests)
.
include?
(
@scope
)
%hr
.gl-mt-4.gl-mb-4
changelogs/unreleased/241691-left-side-facets.yml
deleted
100644 → 0
View file @
7721a229
---
title
:
Global Search - Left Sidebar
merge_request
:
46595
author
:
type
:
added
config/feature_flags/development/search_facets.yml
0 → 100644
View file @
da8c9e8a
---
name
:
search_facets
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46809
rollout_issue_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46595
group
:
group::global search
type
:
development
default_enabled
:
false
locale/gitlab.pot
View file @
da8c9e8a
...
...
@@ -22986,9 +22986,6 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
msgid "Reset filters"
msgstr ""
msgid "Reset health check access token"
msgstr ""
...
...
spec/frontend/search/dropdown_filter/components/dropdown_filter_spec.js
0 → 100644
View file @
da8c9e8a
import
Vuex
from
'
vuex
'
;
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlDropdown
,
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
MOCK_QUERY
}
from
'
jest/search/mock_data
'
;
import
*
as
urlUtils
from
'
~/lib/utils/url_utility
'
;
import
initStore
from
'
~/search/store
'
;
import
DropdownFilter
from
'
~/search/dropdown_filter/components/dropdown_filter.vue
'
;
import
stateFilterData
from
'
~/search/dropdown_filter/constants/state_filter_data
'
;
import
confidentialFilterData
from
'
~/search/dropdown_filter/constants/confidential_filter_data
'
;
jest
.
mock
(
'
~/lib/utils/url_utility
'
,
()
=>
({
visitUrl
:
jest
.
fn
(),
setUrlParams
:
jest
.
fn
(),
}));
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
describe
(
'
DropdownFilter
'
,
()
=>
{
let
wrapper
;
let
store
;
const
createStore
=
options
=>
{
store
=
initStore
({
query
:
MOCK_QUERY
,
...
options
});
};
const
createComponent
=
(
props
=
{
filterData
:
stateFilterData
})
=>
{
wrapper
=
shallowMount
(
DropdownFilter
,
{
localVue
,
store
,
propsData
:
{
...
props
,
},
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
store
=
null
;
});
const
findGlDropdown
=
()
=>
wrapper
.
find
(
GlDropdown
);
const
findGlDropdownItems
=
()
=>
findGlDropdown
().
findAll
(
GlDropdownItem
);
const
findDropdownItemsText
=
()
=>
findGlDropdownItems
().
wrappers
.
map
(
w
=>
w
.
text
());
const
firstDropDownItem
=
()
=>
findGlDropdownItems
().
at
(
0
);
describe
(
'
StatusFilter
'
,
()
=>
{
describe
(
'
template
'
,
()
=>
{
describe
.
each
`
scope | showDropdown
${
'
issues
'
}
|
${
true
}
${
'
merge_requests
'
}
|
${
true
}
${
'
projects
'
}
|
${
false
}
${
'
milestones
'
}
|
${
false
}
${
'
users
'
}
|
${
false
}
${
'
notes
'
}
|
${
false
}
${
'
wiki_blobs
'
}
|
${
false
}
${
'
blobs
'
}
|
${
false
}
`
(
`dropdown`
,
({
scope
,
showDropdown
})
=>
{
beforeEach
(()
=>
{
createStore
({
query
:
{
...
MOCK_QUERY
,
scope
}
});
createComponent
();
});
it
(
`does
${
showDropdown
?
''
:
'
not
'
}
render when scope is
${
scope
}
`
,
()
=>
{
expect
(
findGlDropdown
().
exists
()).
toBe
(
showDropdown
);
});
});
describe
.
each
`
initialFilter | label
${
stateFilterData
.
filters
.
ANY
.
value
}
|
${
`Any
${
stateFilterData
.
header
}
`
}
${
stateFilterData
.
filters
.
OPEN
.
value
}
|
${
stateFilterData
.
filters
.
OPEN
.
label
}
${
stateFilterData
.
filters
.
CLOSED
.
value
}
|
${
stateFilterData
.
filters
.
CLOSED
.
label
}
`
(
`filter text`
,
({
initialFilter
,
label
})
=>
{
describe
(
`when initialFilter is
${
initialFilter
}
`
,
()
=>
{
beforeEach
(()
=>
{
createStore
({
query
:
{
...
MOCK_QUERY
,
[
stateFilterData
.
filterParam
]:
initialFilter
}
});
createComponent
();
});
it
(
`sets dropdown label to
${
label
}
`
,
()
=>
{
expect
(
findGlDropdown
().
attributes
(
'
text
'
)).
toBe
(
label
);
});
});
});
});
describe
(
'
Filter options
'
,
()
=>
{
beforeEach
(()
=>
{
createStore
();
createComponent
();
});
it
(
'
renders a dropdown item for each filterOption
'
,
()
=>
{
expect
(
findDropdownItemsText
()).
toStrictEqual
(
stateFilterData
.
filterByScope
[
stateFilterData
.
scopes
.
ISSUES
].
map
(
v
=>
{
return
v
.
label
;
}),
);
});
it
(
'
clicking a dropdown item calls setUrlParams
'
,
()
=>
{
const
filter
=
stateFilterData
.
filters
[
Object
.
keys
(
stateFilterData
.
filters
)[
0
]].
value
;
firstDropDownItem
().
vm
.
$emit
(
'
click
'
);
expect
(
urlUtils
.
setUrlParams
).
toHaveBeenCalledWith
({
page
:
null
,
[
stateFilterData
.
filterParam
]:
filter
,
});
});
it
(
'
clicking a dropdown item calls visitUrl
'
,
()
=>
{
firstDropDownItem
().
vm
.
$emit
(
'
click
'
);
expect
(
urlUtils
.
visitUrl
).
toHaveBeenCalled
();
});
});
});
describe
(
'
ConfidentialFilter
'
,
()
=>
{
describe
(
'
template
'
,
()
=>
{
describe
.
each
`
scope | showDropdown
${
'
issues
'
}
|
${
true
}
${
'
merge_requests
'
}
|
${
false
}
${
'
projects
'
}
|
${
false
}
${
'
milestones
'
}
|
${
false
}
${
'
users
'
}
|
${
false
}
${
'
notes
'
}
|
${
false
}
${
'
wiki_blobs
'
}
|
${
false
}
${
'
blobs
'
}
|
${
false
}
`
(
`dropdown`
,
({
scope
,
showDropdown
})
=>
{
beforeEach
(()
=>
{
createStore
({
query
:
{
...
MOCK_QUERY
,
scope
}
});
createComponent
({
filterData
:
confidentialFilterData
});
});
it
(
`does
${
showDropdown
?
''
:
'
not
'
}
render when scope is
${
scope
}
`
,
()
=>
{
expect
(
findGlDropdown
().
exists
()).
toBe
(
showDropdown
);
});
});
describe
.
each
`
initialFilter | label
${
confidentialFilterData
.
filters
.
ANY
.
value
}
|
${
`Any
${
confidentialFilterData
.
header
}
`
}
${
confidentialFilterData
.
filters
.
CONFIDENTIAL
.
value
}
|
${
confidentialFilterData
.
filters
.
CONFIDENTIAL
.
label
}
${
confidentialFilterData
.
filters
.
NOT_CONFIDENTIAL
.
value
}
|
${
confidentialFilterData
.
filters
.
NOT_CONFIDENTIAL
.
label
}
`
(
`filter text`
,
({
initialFilter
,
label
})
=>
{
describe
(
`when initialFilter is
${
initialFilter
}
`
,
()
=>
{
beforeEach
(()
=>
{
createStore
({
query
:
{
...
MOCK_QUERY
,
[
confidentialFilterData
.
filterParam
]:
initialFilter
},
});
createComponent
({
filterData
:
confidentialFilterData
});
});
it
(
`sets dropdown label to
${
label
}
`
,
()
=>
{
expect
(
findGlDropdown
().
attributes
(
'
text
'
)).
toBe
(
label
);
});
});
});
});
});
describe
(
'
Filter options
'
,
()
=>
{
beforeEach
(()
=>
{
createStore
();
createComponent
({
filterData
:
confidentialFilterData
});
});
it
(
'
renders a dropdown item for each filterOption
'
,
()
=>
{
expect
(
findDropdownItemsText
()).
toStrictEqual
(
confidentialFilterData
.
filterByScope
[
confidentialFilterData
.
scopes
.
ISSUES
].
map
(
v
=>
{
return
v
.
label
;
}),
);
});
it
(
'
clicking a dropdown item calls setUrlParams
'
,
()
=>
{
const
filter
=
confidentialFilterData
.
filters
[
Object
.
keys
(
confidentialFilterData
.
filters
)[
0
]].
value
;
firstDropDownItem
().
vm
.
$emit
(
'
click
'
);
expect
(
urlUtils
.
setUrlParams
).
toHaveBeenCalledWith
({
page
:
null
,
[
confidentialFilterData
.
filterParam
]:
filter
,
});
});
it
(
'
clicking a dropdown item calls visitUrl
'
,
()
=>
{
firstDropDownItem
().
vm
.
$emit
(
'
click
'
);
expect
(
urlUtils
.
visitUrl
).
toHaveBeenCalled
();
});
});
});
spec/frontend/search/sidebar/components/app_spec.js
deleted
100644 → 0
View file @
7721a229
import
Vuex
from
'
vuex
'
;
import
{
createLocalVue
,
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
GlButton
,
GlLink
}
from
'
@gitlab/ui
'
;
import
{
MOCK_QUERY
}
from
'
jest/search/mock_data
'
;
import
GlobalSearchSidebar
from
'
~/search/sidebar/components/app.vue
'
;
import
ConfidentialityFilter
from
'
~/search/sidebar/components/confidentiality_filter.vue
'
;
import
StatusFilter
from
'
~/search/sidebar/components/status_filter.vue
'
;
const
localVue
=
createLocalVue
();
localVue
.
use
(
Vuex
);
describe
(
'
GlobalSearchSidebar
'
,
()
=>
{
let
wrapper
;
const
actionSpies
=
{
applyQuery
:
jest
.
fn
(),
resetQuery
:
jest
.
fn
(),
};
const
createComponent
=
initialState
=>
{
const
store
=
new
Vuex
.
Store
({
state
:
{
query
:
MOCK_QUERY
,
...
initialState
,
},
actions
:
actionSpies
,
});
wrapper
=
shallowMount
(
GlobalSearchSidebar
,
{
localVue
,
store
,
});
};
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
const
findSidebarForm
=
()
=>
wrapper
.
find
(
'
form
'
);
const
findStatusFilter
=
()
=>
wrapper
.
find
(
StatusFilter
);
const
findConfidentialityFilter
=
()
=>
wrapper
.
find
(
ConfidentialityFilter
);
const
findApplyButton
=
()
=>
wrapper
.
find
(
GlButton
);
const
findResetLinkButton
=
()
=>
wrapper
.
find
(
GlLink
);
describe
(
'
template
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
renders StatusFilter always
'
,
()
=>
{
expect
(
findStatusFilter
().
exists
()).
toBe
(
true
);
});
it
(
'
renders ConfidentialityFilter always
'
,
()
=>
{
expect
(
findConfidentialityFilter
().
exists
()).
toBe
(
true
);
});
it
(
'
renders ApplyButton always
'
,
()
=>
{
expect
(
findApplyButton
().
exists
()).
toBe
(
true
);
});
describe
(
'
ResetLinkButton
'
,
()
=>
{
describe
(
'
with no filter selected
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
query
:
{}
});
});
it
(
'
does not render
'
,
()
=>
{
expect
(
findResetLinkButton
().
exists
()).
toBe
(
false
);
});
});
describe
(
'
with filter selected
'
,
()
=>
{
it
(
'
does render when a filter selected
'
,
()
=>
{
expect
(
findResetLinkButton
().
exists
()).
toBe
(
true
);
});
});
});
});
describe
(
'
actions
'
,
()
=>
{
beforeEach
(()
=>
{
createComponent
();
});
it
(
'
clicking ApplyButton calls applyQuery
'
,
()
=>
{
findSidebarForm
().
trigger
(
'
submit
'
);
expect
(
actionSpies
.
applyQuery
).
toHaveBeenCalled
();
});
it
(
'
clicking ResetLinkButton calls resetQuery
'
,
()
=>
{
findResetLinkButton
().
vm
.
$emit
(
'
click
'
);
expect
(
actionSpies
.
resetQuery
).
toHaveBeenCalled
();
});
});
});
spec/frontend/search/store/actions_spec.js
View file @
da8c9e8a
...
...
@@ -2,7 +2,6 @@ import MockAdapter from 'axios-mock-adapter';
import
testAction
from
'
helpers/vuex_action_helper
'
;
import
*
as
actions
from
'
~/search/store/actions
'
;
import
*
as
types
from
'
~/search/store/mutation_types
'
;
import
*
as
urlUtils
from
'
~/lib/utils/url_utility
'
;
import
state
from
'
~/search/store/state
'
;
import
axios
from
'
~/lib/utils/axios_utils
'
;
import
createFlash
from
'
~/flash
'
;
...
...
@@ -43,47 +42,6 @@ describe('Global Search Store Actions', () => {
});
});
});
describe
(
'
setQuery
'
,
()
=>
{
const
payload
=
{
key
:
'
key1
'
,
value
:
'
value1
'
};
it
(
'
calls the SET_QUERY mutation
'
,
done
=>
{
testAction
(
actions
.
setQuery
,
payload
,
state
,
[{
type
:
types
.
SET_QUERY
,
payload
}],
[],
done
);
});
});
describe
(
'
applyQuery
'
,
()
=>
{
beforeEach
(()
=>
{
urlUtils
.
setUrlParams
=
jest
.
fn
();
urlUtils
.
visitUrl
=
jest
.
fn
();
});
it
(
'
calls visitUrl and setParams with the state.query
'
,
()
=>
{
testAction
(
actions
.
applyQuery
,
null
,
state
,
[],
[],
()
=>
{
expect
(
urlUtils
.
setUrlParams
).
toHaveBeenCalledWith
({
...
state
.
query
,
page
:
null
});
expect
(
urlUtils
.
visitUrl
).
toHaveBeenCalled
();
});
});
});
describe
(
'
resetQuery
'
,
()
=>
{
beforeEach
(()
=>
{
urlUtils
.
setUrlParams
=
jest
.
fn
();
urlUtils
.
visitUrl
=
jest
.
fn
();
});
it
(
'
calls visitUrl and setParams with empty values
'
,
()
=>
{
testAction
(
actions
.
resetQuery
,
null
,
state
,
[],
[],
()
=>
{
expect
(
urlUtils
.
setUrlParams
).
toHaveBeenCalledWith
({
...
state
.
query
,
page
:
null
,
state
:
null
,
confidential
:
null
,
});
expect
(
urlUtils
.
visitUrl
).
toHaveBeenCalled
();
});
});
});
});
describe
(
'
setQuery
'
,
()
=>
{
...
...
spec/views/search/_results.html.haml_spec.rb
View file @
da8c9e8a
...
...
@@ -43,7 +43,7 @@ RSpec.describe 'search/_results' do
let_it_be
(
:wiki_blob
)
{
create
(
:wiki_page
,
project:
project
,
content:
'*'
)
}
let_it_be
(
:user
)
{
create
(
:admin
)
}
%w[issues
merge_request
s]
.
each
do
|
search_scope
|
%w[issues
blobs notes wiki_blobs merge_requests milestone
s]
.
each
do
|
search_scope
|
context
"when scope is
#{
search_scope
}
"
do
let
(
:scope
)
{
search_scope
}
let
(
:search_objects
)
{
Gitlab
::
ProjectSearchResults
.
new
(
user
,
'*'
,
project:
project
).
objects
(
scope
)
}
...
...
@@ -55,30 +55,16 @@ RSpec.describe 'search/_results' do
expect
(
rendered
).
to
have_selector
(
'[data-track-property=search_result]'
)
end
it
'
does render the sidebar
'
do
it
'
renders the state filter drop down
'
do
render
expect
(
rendered
).
to
have_selector
(
'#js-search-sidebar'
)
end
end
end
%w[blobs notes wiki_blobs milestones]
.
each
do
|
search_scope
|
context
"when scope is
#{
search_scope
}
"
do
let
(
:scope
)
{
search_scope
}
let
(
:search_objects
)
{
Gitlab
::
ProjectSearchResults
.
new
(
user
,
'*'
,
project:
project
).
objects
(
scope
)
}
it
'renders the click text event tracking attributes'
do
render
expect
(
rendered
).
to
have_selector
(
'[data-track-event=click_text]'
)
expect
(
rendered
).
to
have_selector
(
'[data-track-property=search_result]'
)
expect
(
rendered
).
to
have_selector
(
'#js-search-filter-by-state'
)
end
it
'
does not render the sidebar
'
do
it
'
renders the confidential drop down
'
do
render
expect
(
rendered
).
not_to
have_selector
(
'#js-search-sidebar
'
)
expect
(
rendered
).
to
have_selector
(
'#js-search-filter-by-confidential
'
)
end
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