@gitlab/ui 36.0.0 → 36.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/components/base/filtered_search/filtered_search.documentation.js +6 -0
- package/dist/components/base/filtered_search/filtered_search.js +12 -2
- package/dist/components/base/filtered_search/filtered_search_term.documentation.js +6 -0
- package/dist/components/base/filtered_search/filtered_search_term.js +11 -1
- package/dist/components/base/filtered_search/filtered_search_token_segment.documentation.js +6 -0
- package/dist/components/base/filtered_search/filtered_search_token_segment.js +11 -1
- package/dist/components/base/search_box_by_click/search_box_by_click.documentation.js +3 -0
- package/dist/components/base/search_box_by_click/search_box_by_click.js +6 -1
- package/package.json +1 -1
- package/src/components/base/filtered_search/filtered_search.documentation.js +6 -0
- package/src/components/base/filtered_search/filtered_search.spec.js +81 -47
- package/src/components/base/filtered_search/filtered_search.vue +13 -0
- package/src/components/base/filtered_search/filtered_search_term.documentation.js +6 -0
- package/src/components/base/filtered_search/filtered_search_term.spec.js +42 -9
- package/src/components/base/filtered_search/filtered_search_term.vue +13 -0
- package/src/components/base/filtered_search/filtered_search_token_segment.documentation.js +6 -0
- package/src/components/base/filtered_search/filtered_search_token_segment.spec.js +53 -0
- package/src/components/base/filtered_search/filtered_search_token_segment.vue +12 -0
- package/src/components/base/search_box_by_click/search_box_by_click.documentation.js +3 -0
- package/src/components/base/search_box_by_click/search_box_by_click.spec.js +14 -3
- package/src/components/base/search_box_by_click/search_box_by_click.vue +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [36.1.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v36.0.0...v36.1.0) (2022-02-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **GlFilteredSearch:** add props for adding additional HTML attributes ([b26ea14](https://gitlab.com/gitlab-org/gitlab-ui/commit/b26ea14b818cef389c48617cb3443ae493cc49aa))
|
|
7
|
+
|
|
1
8
|
# [36.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v35.1.0...v36.0.0) (2022-02-07)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -39,6 +39,12 @@ var filtered_search_documentation = {
|
|
|
39
39
|
},
|
|
40
40
|
suggestionsListClass: {
|
|
41
41
|
additionalInfo: 'Additional classes to add to the suggestion list menu. NOTE: this not reactive, and the value must be available and fixed when the component is instantiated'
|
|
42
|
+
},
|
|
43
|
+
searchButtonAttributes: {
|
|
44
|
+
additionalInfo: 'HTML attributes to add to the search button'
|
|
45
|
+
},
|
|
46
|
+
searchInputAttributes: {
|
|
47
|
+
additionalInfo: 'HTML attributes to add to the search input'
|
|
42
48
|
}
|
|
43
49
|
},
|
|
44
50
|
events: [{
|
|
@@ -83,6 +83,16 @@ var script = {
|
|
|
83
83
|
type: Boolean,
|
|
84
84
|
required: false,
|
|
85
85
|
default: false
|
|
86
|
+
},
|
|
87
|
+
searchButtonAttributes: {
|
|
88
|
+
type: Object,
|
|
89
|
+
required: false,
|
|
90
|
+
default: () => ({})
|
|
91
|
+
},
|
|
92
|
+
searchInputAttributes: {
|
|
93
|
+
type: Object,
|
|
94
|
+
required: false,
|
|
95
|
+
default: () => ({})
|
|
86
96
|
}
|
|
87
97
|
},
|
|
88
98
|
|
|
@@ -269,9 +279,9 @@ var script = {
|
|
|
269
279
|
const __vue_script__ = script;
|
|
270
280
|
|
|
271
281
|
/* template */
|
|
272
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-search-box-by-click',_vm._b({attrs:{"value":_vm.tokens,"history-items":_vm.historyItems,"clearable":_vm.hasValue,"data-testid":"filtered-search-input"},on:{"submit":_vm.submit,"input":_vm.applyNewValue,"history-item-selected":function($event){return _vm.$emit('history-item-selected', $event)},"clear":function($event){return _vm.$emit('clear')},"clear-history":function($event){return _vm.$emit('clear-history')}},scopedSlots:_vm._u([{key:"history-item",fn:function(slotScope){return [_vm._t("history-item",null,null,slotScope)]}},{key:"input",fn:function(){return [_c('div',{staticClass:"gl-filtered-search-scrollable"},[_vm._l((_vm.tokens),function(token,idx){return [_c(_vm.getTokenComponent(token.type),{key:((token.type) + "-" + idx),ref:"tokens",refInFor:true,tag:"component",staticClass:"gl-filtered-search-item",class:{
|
|
282
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-search-box-by-click',_vm._b({attrs:{"value":_vm.tokens,"history-items":_vm.historyItems,"clearable":_vm.hasValue,"search-button-attributes":_vm.searchButtonAttributes,"data-testid":"filtered-search-input"},on:{"submit":_vm.submit,"input":_vm.applyNewValue,"history-item-selected":function($event){return _vm.$emit('history-item-selected', $event)},"clear":function($event){return _vm.$emit('clear')},"clear-history":function($event){return _vm.$emit('clear-history')}},scopedSlots:_vm._u([{key:"history-item",fn:function(slotScope){return [_vm._t("history-item",null,null,slotScope)]}},{key:"input",fn:function(){return [_c('div',{staticClass:"gl-filtered-search-scrollable"},[_vm._l((_vm.tokens),function(token,idx){return [_c(_vm.getTokenComponent(token.type),{key:((token.type) + "-" + idx),ref:"tokens",refInFor:true,tag:"component",staticClass:"gl-filtered-search-item",class:{
|
|
273
283
|
'gl-filtered-search-last-item': _vm.isLastToken(idx),
|
|
274
|
-
},attrs:{"config":_vm.getTokenEntry(token.type),"active":_vm.activeTokenIdx === idx,"available-tokens":_vm.currentAvailableTokens,"current-value":_vm.tokens,"index":idx,"placeholder":_vm.termPlaceholder,"show-friendly-text":_vm.showFriendlyText},on:{"activate":function($event){return _vm.activate(idx)},"deactivate":function($event){return _vm.deactivate(token)},"destroy":function($event){return _vm.destroyToken(idx)},"replace":function($event){return _vm.replaceToken(idx, $event)},"complete":_vm.completeToken,"submit":_vm.submit,"split":function($event){return _vm.createTokens(idx, $event)}},model:{value:(token.value),callback:function ($$v) {_vm.$set(token, "value", $$v);},expression:"token.value"}})]})],2),_vm._v(" "),_c('portal-target',{key:_vm.activeTokenIdx,ref:"menu",style:(_vm.suggestionsStyle),attrs:{"name":_vm.portalName,"slim":""}})]},proxy:true}],null,true)},'gl-search-box-by-click',_vm.$attrs,false))};
|
|
284
|
+
},attrs:{"config":_vm.getTokenEntry(token.type),"active":_vm.activeTokenIdx === idx,"available-tokens":_vm.currentAvailableTokens,"current-value":_vm.tokens,"index":idx,"placeholder":_vm.termPlaceholder,"show-friendly-text":_vm.showFriendlyText,"search-input-attributes":_vm.searchInputAttributes,"is-last-token":_vm.isLastToken(idx)},on:{"activate":function($event){return _vm.activate(idx)},"deactivate":function($event){return _vm.deactivate(token)},"destroy":function($event){return _vm.destroyToken(idx)},"replace":function($event){return _vm.replaceToken(idx, $event)},"complete":_vm.completeToken,"submit":_vm.submit,"split":function($event){return _vm.createTokens(idx, $event)}},model:{value:(token.value),callback:function ($$v) {_vm.$set(token, "value", $$v);},expression:"token.value"}})]})],2),_vm._v(" "),_c('portal-target',{key:_vm.activeTokenIdx,ref:"menu",style:(_vm.suggestionsStyle),attrs:{"name":_vm.portalName,"slim":""}})]},proxy:true}],null,true)},'gl-search-box-by-click',_vm.$attrs,false))};
|
|
275
285
|
var __vue_staticRenderFns__ = [];
|
|
276
286
|
|
|
277
287
|
/* style */
|
|
@@ -17,6 +17,12 @@ var filtered_search_term_documentation = {
|
|
|
17
17
|
},
|
|
18
18
|
value: {
|
|
19
19
|
additionalInfo: 'Current term value'
|
|
20
|
+
},
|
|
21
|
+
searchInputAttributes: {
|
|
22
|
+
additionalInfo: 'HTML attributes to add to the search input'
|
|
23
|
+
},
|
|
24
|
+
isLastToken: {
|
|
25
|
+
additionalInfo: 'If this is the last token'
|
|
20
26
|
}
|
|
21
27
|
},
|
|
22
28
|
events: [{
|
|
@@ -29,6 +29,16 @@ var script = {
|
|
|
29
29
|
type: String,
|
|
30
30
|
required: false,
|
|
31
31
|
default: ''
|
|
32
|
+
},
|
|
33
|
+
searchInputAttributes: {
|
|
34
|
+
type: Object,
|
|
35
|
+
required: false,
|
|
36
|
+
default: () => ({})
|
|
37
|
+
},
|
|
38
|
+
isLastToken: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
required: false,
|
|
41
|
+
default: false
|
|
32
42
|
}
|
|
33
43
|
},
|
|
34
44
|
computed: {
|
|
@@ -55,7 +65,7 @@ var script = {
|
|
|
55
65
|
const __vue_script__ = script;
|
|
56
66
|
|
|
57
67
|
/* template */
|
|
58
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-h-auto gl-filtered-search-term"},[_c('gl-filtered-search-token-segment',{staticClass:"gl-filtered-search-term-token",class:{ 'gl-w-full': _vm.placeholder },attrs:{"active":_vm.active},on:{"activate":function($event){return _vm.$emit('activate')},"deactivate":function($event){return _vm.$emit('deactivate')},"complete":function($event){return _vm.$emit('replace', { type: $event })},"backspace":function($event){return _vm.$emit('destroy')},"submit":function($event){return _vm.$emit('submit')},"split":function($event){return _vm.$emit('split', $event)}},scopedSlots:_vm._u([{key:"suggestions",fn:function(){return _vm._l((_vm.suggestedTokens),function(item,idx){return _c('gl-filtered-search-suggestion',{key:idx,attrs:{"value":item.type,"icon-name":item.icon}},[_vm._v("\n "+_vm._s(item.title)+"\n ")])})},proxy:true},{key:"view",fn:function(){return [(_vm.placeholder)?_c('input',{staticClass:"gl-filtered-search-term-input",attrs:{"placeholder":_vm.placeholder,"aria-label":_vm.placeholder}}):[_vm._v(_vm._s(_vm.value.data))]]},proxy:true}]),model:{value:(_vm.internalValue),callback:function ($$v) {_vm.internalValue=$$v;},expression:"internalValue"}})],1)};
|
|
68
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-h-auto gl-filtered-search-term"},[_c('gl-filtered-search-token-segment',{staticClass:"gl-filtered-search-term-token",class:{ 'gl-w-full': _vm.placeholder },attrs:{"active":_vm.active,"search-input-attributes":_vm.searchInputAttributes,"is-last-token":_vm.isLastToken},on:{"activate":function($event){return _vm.$emit('activate')},"deactivate":function($event){return _vm.$emit('deactivate')},"complete":function($event){return _vm.$emit('replace', { type: $event })},"backspace":function($event){return _vm.$emit('destroy')},"submit":function($event){return _vm.$emit('submit')},"split":function($event){return _vm.$emit('split', $event)}},scopedSlots:_vm._u([{key:"suggestions",fn:function(){return _vm._l((_vm.suggestedTokens),function(item,idx){return _c('gl-filtered-search-suggestion',{key:idx,attrs:{"value":item.type,"icon-name":item.icon}},[_vm._v("\n "+_vm._s(item.title)+"\n ")])})},proxy:true},{key:"view",fn:function(){return [(_vm.placeholder)?_c('input',_vm._b({staticClass:"gl-filtered-search-term-input",attrs:{"placeholder":_vm.placeholder,"aria-label":_vm.placeholder}},'input',_vm.searchInputAttributes,false)):[_vm._v(_vm._s(_vm.value.data))]]},proxy:true}]),model:{value:(_vm.internalValue),callback:function ($$v) {_vm.internalValue=$$v;},expression:"internalValue"}})],1)};
|
|
59
69
|
var __vue_staticRenderFns__ = [];
|
|
60
70
|
|
|
61
71
|
/* style */
|
|
@@ -23,6 +23,12 @@ var filtered_search_token_segment_documentation = {
|
|
|
23
23
|
},
|
|
24
24
|
value: {
|
|
25
25
|
additionalInfo: 'Current term value'
|
|
26
|
+
},
|
|
27
|
+
searchInputAttributes: {
|
|
28
|
+
additionalInfo: 'HTML attributes to add to the search input'
|
|
29
|
+
},
|
|
30
|
+
isLastToken: {
|
|
31
|
+
additionalInfo: 'If this is the last token'
|
|
26
32
|
}
|
|
27
33
|
},
|
|
28
34
|
events: [{
|
|
@@ -48,6 +48,16 @@ var script = {
|
|
|
48
48
|
value: {
|
|
49
49
|
required: true,
|
|
50
50
|
validator: () => true
|
|
51
|
+
},
|
|
52
|
+
searchInputAttributes: {
|
|
53
|
+
type: Object,
|
|
54
|
+
required: false,
|
|
55
|
+
default: () => ({})
|
|
56
|
+
},
|
|
57
|
+
isLastToken: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
required: false,
|
|
60
|
+
default: false
|
|
51
61
|
}
|
|
52
62
|
},
|
|
53
63
|
|
|
@@ -274,7 +284,7 @@ var script = {
|
|
|
274
284
|
const __vue_script__ = script;
|
|
275
285
|
|
|
276
286
|
/* template */
|
|
277
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-filtered-search-token-segment",class:{ 'gl-filtered-search-token-segment-active': _vm.active },attrs:{"data-testid":"filtered-search-token-segment"},on:{"mousedown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"left",37,$event.key,["Left","ArrowLeft"])){ return null; }if('button' in $event && $event.button !== 0){ return null; }return _vm.emitIfInactive($event)}}},[(_vm.active)?[_c('input',{directives:[{name:"model",rawName:"v-model",value:(_vm.inputValue),expression:"inputValue"}],ref:"input",staticClass:"gl-filtered-search-token-segment-input",attrs:{"aria-label":_vm.label},domProps:{"value":(_vm.inputValue)},on:{"keydown":_vm.handleInputKeydown,"blur":_vm.handleBlur,"input":function($event){if($event.target.composing){ return; }_vm.inputValue=$event.target.value;}}}),_vm._v(" "),_c('portal',{key:("operator-" + _vm._uid),attrs:{"to":_vm.portalName}},[(_vm.hasOptionsOrSuggestions)?_c('gl-filtered-search-suggestion-list',{key:("operator-" + _vm._uid),ref:"suggestions",attrs:{"initial-value":_vm.defaultSuggestedValue},on:{"suggestion":_vm.applySuggestion}},[(_vm.options)?_vm._l((_vm.options),function(option,idx){return _c('gl-filtered-search-suggestion',{key:((option.value) + "-" + idx),attrs:{"value":option.value,"icon-name":option.icon}},[_vm._t("option",[_vm._v("\n "+_vm._s(option[_vm.optionTextField])+"\n ")],null,{ option: option })],2)}):_vm._t("suggestions")],2):_vm._e()],1)]:_vm._t("view",[_vm._v(_vm._s(_vm.inputValue))],null,{ inputValue: _vm.inputValue })],2)};
|
|
287
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',_vm._b({staticClass:"gl-filtered-search-token-segment",class:{ 'gl-filtered-search-token-segment-active': _vm.active },attrs:{"data-testid":"filtered-search-token-segment"},on:{"mousedown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"left",37,$event.key,["Left","ArrowLeft"])){ return null; }if('button' in $event && $event.button !== 0){ return null; }return _vm.emitIfInactive($event)}}},'div',_vm.isLastToken && !_vm.active && _vm.searchInputAttributes,false),[(_vm.active)?[(((_vm.searchInputAttributes).type)==='checkbox')?_c('input',_vm._b({directives:[{name:"model",rawName:"v-model",value:(_vm.inputValue),expression:"inputValue"}],ref:"input",staticClass:"gl-filtered-search-token-segment-input",attrs:{"aria-label":_vm.label,"type":"checkbox"},domProps:{"checked":Array.isArray(_vm.inputValue)?_vm._i(_vm.inputValue,null)>-1:(_vm.inputValue)},on:{"keydown":_vm.handleInputKeydown,"blur":_vm.handleBlur,"change":function($event){var $$a=_vm.inputValue,$$el=$event.target,$$c=$$el.checked?(true):(false);if(Array.isArray($$a)){var $$v=null,$$i=_vm._i($$a,$$v);if($$el.checked){$$i<0&&(_vm.inputValue=$$a.concat([$$v]));}else {$$i>-1&&(_vm.inputValue=$$a.slice(0,$$i).concat($$a.slice($$i+1)));}}else {_vm.inputValue=$$c;}}}},'input',_vm.searchInputAttributes,false)):(((_vm.searchInputAttributes).type)==='radio')?_c('input',_vm._b({directives:[{name:"model",rawName:"v-model",value:(_vm.inputValue),expression:"inputValue"}],ref:"input",staticClass:"gl-filtered-search-token-segment-input",attrs:{"aria-label":_vm.label,"type":"radio"},domProps:{"checked":_vm._q(_vm.inputValue,null)},on:{"keydown":_vm.handleInputKeydown,"blur":_vm.handleBlur,"change":function($event){_vm.inputValue=null;}}},'input',_vm.searchInputAttributes,false)):_c('input',_vm._b({directives:[{name:"model",rawName:"v-model",value:(_vm.inputValue),expression:"inputValue"}],ref:"input",staticClass:"gl-filtered-search-token-segment-input",attrs:{"aria-label":_vm.label,"type":(_vm.searchInputAttributes).type},domProps:{"value":(_vm.inputValue)},on:{"keydown":_vm.handleInputKeydown,"blur":_vm.handleBlur,"input":function($event){if($event.target.composing){ return; }_vm.inputValue=$event.target.value;}}},'input',_vm.searchInputAttributes,false)),_vm._v(" "),_c('portal',{key:("operator-" + _vm._uid),attrs:{"to":_vm.portalName}},[(_vm.hasOptionsOrSuggestions)?_c('gl-filtered-search-suggestion-list',{key:("operator-" + _vm._uid),ref:"suggestions",attrs:{"initial-value":_vm.defaultSuggestedValue},on:{"suggestion":_vm.applySuggestion}},[(_vm.options)?_vm._l((_vm.options),function(option,idx){return _c('gl-filtered-search-suggestion',{key:((option.value) + "-" + idx),attrs:{"value":option.value,"icon-name":option.icon}},[_vm._t("option",[_vm._v("\n "+_vm._s(option[_vm.optionTextField])+"\n ")],null,{ option: option })],2)}):_vm._t("suggestions")],2):_vm._e()],1)]:_vm._t("view",[_vm._v(_vm._s(_vm.inputValue))],null,{ inputValue: _vm.inputValue })],2)};
|
|
278
288
|
var __vue_staticRenderFns__ = [];
|
|
279
289
|
|
|
280
290
|
/* style */
|
|
@@ -51,6 +51,9 @@ var search_box_by_click_documentation = {
|
|
|
51
51
|
},
|
|
52
52
|
tooltipContainer: {
|
|
53
53
|
additionalInfo: 'Container for tooltip. Valid values: DOM node, selector string or `false` for default'
|
|
54
|
+
},
|
|
55
|
+
searchButtonAttributes: {
|
|
56
|
+
additionalInfo: 'HTML attributes to add to the search button'
|
|
54
57
|
}
|
|
55
58
|
},
|
|
56
59
|
events: [{
|
|
@@ -82,6 +82,11 @@ var script = {
|
|
|
82
82
|
required: false,
|
|
83
83
|
default: false,
|
|
84
84
|
validator: value => value === false || typeof value === 'string' || value instanceof HTMLElement
|
|
85
|
+
},
|
|
86
|
+
searchButtonAttributes: {
|
|
87
|
+
type: Object,
|
|
88
|
+
required: false,
|
|
89
|
+
default: () => ({})
|
|
85
90
|
}
|
|
86
91
|
},
|
|
87
92
|
|
|
@@ -159,7 +164,7 @@ var script = {
|
|
|
159
164
|
const __vue_script__ = script;
|
|
160
165
|
|
|
161
166
|
/* template */
|
|
162
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-form-input-group',{staticClass:"gl-search-box-by-click",scopedSlots:_vm._u([(_vm.historyItems)?{key:"prepend",fn:function(){return [_c('gl-dropdown',{ref:"historyDropdown",staticClass:"gl-search-box-by-click-history",attrs:{"menu-class":"gl-search-box-by-click-menu","category":"secondary","disabled":_vm.disabled},scopedSlots:_vm._u([{key:"button-content",fn:function(){return [_c('gl-icon',{staticClass:"gl-search-box-by-click-history-icon",attrs:{"name":"history"}}),_vm._v(" "),_c('gl-icon',{staticClass:"gl-search-box-by-click-history-icon-chevron",attrs:{"name":"chevron-down"}}),_vm._v(" "),_c('span',{staticClass:"gl-sr-only"},[_vm._v("Toggle history")])]},proxy:true}],null,false,2220989388)},[_vm._v(" "),_c('gl-dropdown-text',{staticClass:"gl-search-box-by-click-history-header"},[_vm._v("\n "+_vm._s(_vm.recentSearchesHeader)+"\n "),_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip.hover",value:({ container: _vm.tooltipContainer }),expression:"{ container: tooltipContainer }",modifiers:{"hover":true}}],ref:"closeHistory",staticClass:"gl-search-box-by-click-close-history-button",attrs:{"title":_vm.closeButtonTitle,"aria-label":_vm.closeButtonTitle,"category":"tertiary","name":"close","icon":"close"},on:{"click":_vm.closeHistoryDropdown}})],1),_vm._v(" "),_c('gl-dropdown-divider'),_vm._v(" "),(_vm.historyItems.length)?[_vm._l((_vm.historyItems),function(item,idx){return _c('gl-dropdown-item',{key:idx,staticClass:"gl-search-box-by-click-history-item",on:{"click":function($event){return _vm.selectHistoryItem(item)}}},[_vm._t("history-item",[_vm._v(_vm._s(item))],{"historyItem":item})],2)}),_vm._v(" "),_c('gl-dropdown-divider'),_vm._v(" "),_c('gl-dropdown-item',{ref:"clearHistory",on:{"click":function($event){return _vm.$emit('clear-history')}}},[_vm._v(_vm._s(_vm.clearRecentSearchesText))])]:_c('gl-dropdown-text',{staticClass:"gl-search-box-by-click-history-no-searches"},[_vm._v(_vm._s(_vm.noRecentSearchesText))])],2)]},proxy:true}:null,{key:"append",fn:function(){return [_c('gl-button',{ref:"searchButton",staticClass:"gl-search-box-by-click-search-button",attrs:{"icon":"search","disabled":_vm.disabled,"aria-label":"Search"},on:{"click":function($event){return _vm.search(_vm.currentValue)}}})]},proxy:true}],null,true)},[_vm._v(" "),_vm._t("input",[_c('gl-form-input',_vm._b({ref:"input",staticClass:"gl-search-box-by-click-input",attrs:{"disabled":_vm.disabled},on:{"focus":function($event){_vm.isFocused = true;},"blur":function($event){_vm.isFocused = false;},"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }return _vm.search(_vm.currentValue)}},model:{value:(_vm.currentValue),callback:function ($$v) {_vm.currentValue=$$v;},expression:"currentValue"}},'gl-form-input',_vm.inputAttributes,false))]),_vm._v(" "),(_vm.clearable && _vm.hasValue && !_vm.disabled)?_c('gl-clear-icon-button',{staticClass:"gl-search-box-by-click-icon-button gl-search-box-by-click-clear-button gl-clear-icon-button",attrs:{"title":_vm.clearButtonTitle,"tooltip-container":_vm.tooltipContainer,"data-testid":"filtered-search-clear-button"},on:{"click":_vm.clearInput}}):_vm._e()],2)};
|
|
167
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-form-input-group',{staticClass:"gl-search-box-by-click",scopedSlots:_vm._u([(_vm.historyItems)?{key:"prepend",fn:function(){return [_c('gl-dropdown',{ref:"historyDropdown",staticClass:"gl-search-box-by-click-history",attrs:{"menu-class":"gl-search-box-by-click-menu","category":"secondary","disabled":_vm.disabled},scopedSlots:_vm._u([{key:"button-content",fn:function(){return [_c('gl-icon',{staticClass:"gl-search-box-by-click-history-icon",attrs:{"name":"history"}}),_vm._v(" "),_c('gl-icon',{staticClass:"gl-search-box-by-click-history-icon-chevron",attrs:{"name":"chevron-down"}}),_vm._v(" "),_c('span',{staticClass:"gl-sr-only"},[_vm._v("Toggle history")])]},proxy:true}],null,false,2220989388)},[_vm._v(" "),_c('gl-dropdown-text',{staticClass:"gl-search-box-by-click-history-header"},[_vm._v("\n "+_vm._s(_vm.recentSearchesHeader)+"\n "),_c('gl-button',{directives:[{name:"gl-tooltip",rawName:"v-gl-tooltip.hover",value:({ container: _vm.tooltipContainer }),expression:"{ container: tooltipContainer }",modifiers:{"hover":true}}],ref:"closeHistory",staticClass:"gl-search-box-by-click-close-history-button",attrs:{"title":_vm.closeButtonTitle,"aria-label":_vm.closeButtonTitle,"category":"tertiary","name":"close","icon":"close"},on:{"click":_vm.closeHistoryDropdown}})],1),_vm._v(" "),_c('gl-dropdown-divider'),_vm._v(" "),(_vm.historyItems.length)?[_vm._l((_vm.historyItems),function(item,idx){return _c('gl-dropdown-item',{key:idx,staticClass:"gl-search-box-by-click-history-item",on:{"click":function($event){return _vm.selectHistoryItem(item)}}},[_vm._t("history-item",[_vm._v(_vm._s(item))],{"historyItem":item})],2)}),_vm._v(" "),_c('gl-dropdown-divider'),_vm._v(" "),_c('gl-dropdown-item',{ref:"clearHistory",on:{"click":function($event){return _vm.$emit('clear-history')}}},[_vm._v(_vm._s(_vm.clearRecentSearchesText))])]:_c('gl-dropdown-text',{staticClass:"gl-search-box-by-click-history-no-searches"},[_vm._v(_vm._s(_vm.noRecentSearchesText))])],2)]},proxy:true}:null,{key:"append",fn:function(){return [_c('gl-button',_vm._b({ref:"searchButton",staticClass:"gl-search-box-by-click-search-button",attrs:{"icon":"search","disabled":_vm.disabled,"aria-label":"Search","data-testid":"search-button"},on:{"click":function($event){return _vm.search(_vm.currentValue)}}},'gl-button',_vm.searchButtonAttributes,false))]},proxy:true}],null,true)},[_vm._v(" "),_vm._t("input",[_c('gl-form-input',_vm._b({ref:"input",staticClass:"gl-search-box-by-click-input",attrs:{"disabled":_vm.disabled},on:{"focus":function($event){_vm.isFocused = true;},"blur":function($event){_vm.isFocused = false;},"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }return _vm.search(_vm.currentValue)}},model:{value:(_vm.currentValue),callback:function ($$v) {_vm.currentValue=$$v;},expression:"currentValue"}},'gl-form-input',_vm.inputAttributes,false))]),_vm._v(" "),(_vm.clearable && _vm.hasValue && !_vm.disabled)?_c('gl-clear-icon-button',{staticClass:"gl-search-box-by-click-icon-button gl-search-box-by-click-clear-button gl-clear-icon-button",attrs:{"title":_vm.clearButtonTitle,"tooltip-container":_vm.tooltipContainer,"data-testid":"filtered-search-clear-button"},on:{"click":_vm.clearInput}}):_vm._e()],2)};
|
|
163
168
|
var __vue_staticRenderFns__ = [];
|
|
164
169
|
|
|
165
170
|
/* style */
|
package/package.json
CHANGED
|
@@ -35,6 +35,12 @@ export default {
|
|
|
35
35
|
additionalInfo:
|
|
36
36
|
'Additional classes to add to the suggestion list menu. NOTE: this not reactive, and the value must be available and fixed when the component is instantiated',
|
|
37
37
|
},
|
|
38
|
+
searchButtonAttributes: {
|
|
39
|
+
additionalInfo: 'HTML attributes to add to the search button',
|
|
40
|
+
},
|
|
41
|
+
searchInputAttributes: {
|
|
42
|
+
additionalInfo: 'HTML attributes to add to the search input',
|
|
43
|
+
},
|
|
38
44
|
},
|
|
39
45
|
events: [
|
|
40
46
|
{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Vue from 'vue';
|
|
1
|
+
import Vue, { nextTick } from 'vue';
|
|
2
2
|
import { shallowMount, mount } from '@vue/test-utils';
|
|
3
3
|
import GlFilteredSearch from './filtered_search.vue';
|
|
4
4
|
import GlFilteredSearchSuggestion from './filtered_search_suggestion.vue';
|
|
@@ -31,7 +31,7 @@ describe('Filtered search', () => {
|
|
|
31
31
|
stubs: {
|
|
32
32
|
GlSearchBoxByClick: {
|
|
33
33
|
name: 'GlSearchBoxByClickStub',
|
|
34
|
-
props: ['clearable'],
|
|
34
|
+
props: ['clearable', 'searchButtonAttributes'],
|
|
35
35
|
template: '<div><slot name="input"></slot></div>',
|
|
36
36
|
},
|
|
37
37
|
},
|
|
@@ -66,7 +66,7 @@ describe('Filtered search', () => {
|
|
|
66
66
|
createComponent({
|
|
67
67
|
value: [{ type: 'faketoken', value: { data: '' } }],
|
|
68
68
|
});
|
|
69
|
-
await
|
|
69
|
+
await nextTick();
|
|
70
70
|
|
|
71
71
|
expect(findSearchBox().props('clearable')).toBe(true);
|
|
72
72
|
});
|
|
@@ -75,7 +75,7 @@ describe('Filtered search', () => {
|
|
|
75
75
|
createComponent({
|
|
76
76
|
value: ['one', 'two'],
|
|
77
77
|
});
|
|
78
|
-
await
|
|
78
|
+
await nextTick();
|
|
79
79
|
|
|
80
80
|
const inputEventArgs = wrapper.emitted().input[1][0];
|
|
81
81
|
expect(inputEventArgs.every((t) => t.type === TERM_TOKEN_TYPE)).toBe(true);
|
|
@@ -86,7 +86,7 @@ describe('Filtered search', () => {
|
|
|
86
86
|
createComponent({
|
|
87
87
|
value: ['one two'],
|
|
88
88
|
});
|
|
89
|
-
await
|
|
89
|
+
await nextTick();
|
|
90
90
|
|
|
91
91
|
const inputEventArgs = wrapper.emitted().input[1][0];
|
|
92
92
|
expect(inputEventArgs.every((t) => t.type === TERM_TOKEN_TYPE)).toBe(true);
|
|
@@ -104,7 +104,7 @@ describe('Filtered search', () => {
|
|
|
104
104
|
`('passes through $eventName', async ({ eventName, payload }) => {
|
|
105
105
|
createComponent();
|
|
106
106
|
findSearchBox().vm.$emit(eventName, payload[0]);
|
|
107
|
-
await
|
|
107
|
+
await nextTick();
|
|
108
108
|
|
|
109
109
|
expect(wrapper.emitted()[eventName][0]).toStrictEqual(payload);
|
|
110
110
|
});
|
|
@@ -113,11 +113,11 @@ describe('Filtered search', () => {
|
|
|
113
113
|
createComponent({
|
|
114
114
|
value: [{ type: 'faketoken', value: '' }],
|
|
115
115
|
});
|
|
116
|
-
await
|
|
116
|
+
await nextTick();
|
|
117
117
|
|
|
118
118
|
wrapper.findComponent(FakeToken).vm.$emit('activate');
|
|
119
119
|
|
|
120
|
-
await
|
|
120
|
+
await nextTick();
|
|
121
121
|
|
|
122
122
|
expect(wrapper.findComponent(FakeToken).props('active')).toBe(true);
|
|
123
123
|
});
|
|
@@ -126,12 +126,12 @@ describe('Filtered search', () => {
|
|
|
126
126
|
createComponent({
|
|
127
127
|
value: [{ type: 'faketoken', value: '' }],
|
|
128
128
|
});
|
|
129
|
-
await
|
|
129
|
+
await nextTick();
|
|
130
130
|
|
|
131
131
|
wrapper.findComponent(FakeToken).vm.$emit('activate');
|
|
132
132
|
wrapper.findComponent(FakeToken).vm.$emit('deactivate');
|
|
133
133
|
|
|
134
|
-
await
|
|
134
|
+
await nextTick();
|
|
135
135
|
|
|
136
136
|
expect(
|
|
137
137
|
wrapper.findAllComponents({ ref: 'tokens' }).filter((w) => w.props('active') === true)
|
|
@@ -145,12 +145,12 @@ describe('Filtered search', () => {
|
|
|
145
145
|
{ type: 'faketoken', value: { data: '2' } },
|
|
146
146
|
],
|
|
147
147
|
});
|
|
148
|
-
await
|
|
148
|
+
await nextTick();
|
|
149
149
|
|
|
150
150
|
wrapper.findComponent(FakeToken).vm.$emit('activate');
|
|
151
151
|
wrapper.findAllComponents(FakeToken).at(1).vm.$emit('deactivate');
|
|
152
152
|
|
|
153
|
-
await
|
|
153
|
+
await nextTick();
|
|
154
154
|
|
|
155
155
|
expect(wrapper.findComponent(FakeToken).props('active')).toBe(true);
|
|
156
156
|
});
|
|
@@ -161,16 +161,16 @@ describe('Filtered search', () => {
|
|
|
161
161
|
value: [{ type: 'faketoken', value: { data: '' } }, 'one', 'two', 'three'],
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
await
|
|
164
|
+
await nextTick();
|
|
165
165
|
|
|
166
166
|
findSecondTerm().vm.$emit('activate');
|
|
167
167
|
findSecondTerm().vm.$emit('input', { data: '' });
|
|
168
168
|
|
|
169
|
-
await
|
|
169
|
+
await nextTick();
|
|
170
170
|
|
|
171
171
|
findSecondTerm().vm.$emit('deactivate');
|
|
172
172
|
|
|
173
|
-
await
|
|
173
|
+
await nextTick();
|
|
174
174
|
|
|
175
175
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
176
176
|
{ type: 'faketoken', value: { data: '' } },
|
|
@@ -184,11 +184,11 @@ describe('Filtered search', () => {
|
|
|
184
184
|
createComponent({
|
|
185
185
|
value: [{ type: 'faketoken', value: '' }, 'one'],
|
|
186
186
|
});
|
|
187
|
-
await
|
|
187
|
+
await nextTick();
|
|
188
188
|
|
|
189
189
|
wrapper.findComponent(FakeToken).vm.$emit('destroy');
|
|
190
190
|
|
|
191
|
-
await
|
|
191
|
+
await nextTick();
|
|
192
192
|
|
|
193
193
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
194
194
|
{ type: TERM_TOKEN_TYPE, value: { data: 'one' } },
|
|
@@ -200,11 +200,11 @@ describe('Filtered search', () => {
|
|
|
200
200
|
createComponent({
|
|
201
201
|
value: ['one', { type: 'faketoken', value: '' }, 'two'],
|
|
202
202
|
});
|
|
203
|
-
await
|
|
203
|
+
await nextTick();
|
|
204
204
|
|
|
205
205
|
wrapper.findComponent(FakeToken).vm.$emit('destroy');
|
|
206
206
|
|
|
207
|
-
await
|
|
207
|
+
await nextTick();
|
|
208
208
|
|
|
209
209
|
expect(wrapper.findComponent(GlFilteredSearchTerm).props('active')).toBe(true);
|
|
210
210
|
});
|
|
@@ -213,7 +213,7 @@ describe('Filtered search', () => {
|
|
|
213
213
|
createComponent();
|
|
214
214
|
wrapper.findComponent(GlFilteredSearchTerm).vm.$emit('destroy');
|
|
215
215
|
|
|
216
|
-
await
|
|
216
|
+
await nextTick();
|
|
217
217
|
|
|
218
218
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
219
219
|
{ type: TERM_TOKEN_TYPE, value: { data: '' } },
|
|
@@ -226,7 +226,7 @@ describe('Filtered search', () => {
|
|
|
226
226
|
.findComponent(GlFilteredSearchTerm)
|
|
227
227
|
.vm.$emit('replace', { type: 'faketoken', value: { data: 'test' } });
|
|
228
228
|
|
|
229
|
-
await
|
|
229
|
+
await nextTick();
|
|
230
230
|
|
|
231
231
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
232
232
|
{ type: 'faketoken', value: { data: 'test' } },
|
|
@@ -241,13 +241,13 @@ describe('Filtered search', () => {
|
|
|
241
241
|
|
|
242
242
|
findSearchBox().vm.$emit('input', '');
|
|
243
243
|
|
|
244
|
-
await
|
|
244
|
+
await nextTick();
|
|
245
245
|
|
|
246
246
|
wrapper
|
|
247
247
|
.findComponent(GlFilteredSearchTerm)
|
|
248
248
|
.vm.$emit('replace', { type: 'faketoken', value: { data: 'test' } });
|
|
249
249
|
|
|
250
|
-
await
|
|
250
|
+
await nextTick();
|
|
251
251
|
|
|
252
252
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
253
253
|
{ type: 'faketoken', value: { data: 'test' } },
|
|
@@ -260,7 +260,7 @@ describe('Filtered search', () => {
|
|
|
260
260
|
wrapper.findComponent(GlFilteredSearchTerm).vm.$emit('activate');
|
|
261
261
|
wrapper.findComponent(GlFilteredSearchTerm).vm.$emit('split');
|
|
262
262
|
|
|
263
|
-
await
|
|
263
|
+
await nextTick();
|
|
264
264
|
|
|
265
265
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
266
266
|
{ type: TERM_TOKEN_TYPE, value: { data: 'one' } },
|
|
@@ -270,12 +270,12 @@ describe('Filtered search', () => {
|
|
|
270
270
|
|
|
271
271
|
it('jumps to last token when insert of empty term requested', async () => {
|
|
272
272
|
createComponent({ value: ['one', 'two'] });
|
|
273
|
-
await
|
|
273
|
+
await nextTick();
|
|
274
274
|
|
|
275
275
|
wrapper.findComponent(GlFilteredSearchTerm).vm.$emit('activate');
|
|
276
276
|
wrapper.findComponent(GlFilteredSearchTerm).vm.$emit('split');
|
|
277
277
|
|
|
278
|
-
await
|
|
278
|
+
await nextTick();
|
|
279
279
|
|
|
280
280
|
expect(wrapper.findAllComponents(GlFilteredSearchTerm).at(2).props('active')).toBe(true);
|
|
281
281
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
@@ -289,11 +289,11 @@ describe('Filtered search', () => {
|
|
|
289
289
|
createComponent({ value: ['one'] });
|
|
290
290
|
wrapper.findComponent(GlFilteredSearchTerm).vm.$emit('activate');
|
|
291
291
|
|
|
292
|
-
await
|
|
292
|
+
await nextTick();
|
|
293
293
|
|
|
294
294
|
wrapper.findComponent(GlFilteredSearchTerm).vm.$emit('split', ['foo', 'bar']);
|
|
295
295
|
|
|
296
|
-
await
|
|
296
|
+
await nextTick();
|
|
297
297
|
|
|
298
298
|
expect(wrapper.emitted().input.pop()[0]).toStrictEqual([
|
|
299
299
|
{ type: TERM_TOKEN_TYPE, value: { data: 'one' } },
|
|
@@ -336,7 +336,7 @@ describe('Filtered search', () => {
|
|
|
336
336
|
createComponent({
|
|
337
337
|
value: [{ type: 'faketoken', value: '' }],
|
|
338
338
|
});
|
|
339
|
-
await
|
|
339
|
+
await nextTick();
|
|
340
340
|
|
|
341
341
|
const fakeTokenInstance = wrapper.findComponent(FakeToken);
|
|
342
342
|
expect(fakeTokenInstance.exists()).toBe(true);
|
|
@@ -344,6 +344,40 @@ describe('Filtered search', () => {
|
|
|
344
344
|
expect.arrayContaining(['current-value', 'index', 'config', 'value'])
|
|
345
345
|
);
|
|
346
346
|
});
|
|
347
|
+
|
|
348
|
+
it('passes `searchButtonAttributes` prop to `GlSearchBoxByClick`', () => {
|
|
349
|
+
const searchButtonAttributes = { 'data-qa-selector': 'foo-bar' };
|
|
350
|
+
|
|
351
|
+
createComponent({ searchButtonAttributes });
|
|
352
|
+
|
|
353
|
+
expect(findSearchBox().props('searchButtonAttributes')).toEqual(searchButtonAttributes);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('passes `searchInputAttributes` prop to search term', async () => {
|
|
357
|
+
const searchInputAttributes = { 'data-qa-selector': 'foo-bar' };
|
|
358
|
+
|
|
359
|
+
createComponent({
|
|
360
|
+
value: ['one'],
|
|
361
|
+
searchInputAttributes,
|
|
362
|
+
});
|
|
363
|
+
await nextTick();
|
|
364
|
+
|
|
365
|
+
expect(wrapper.findComponent(GlFilteredSearchTerm).props('searchInputAttributes')).toEqual(
|
|
366
|
+
searchInputAttributes
|
|
367
|
+
);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('passes `isLastToken` prop to search terms', async () => {
|
|
371
|
+
createComponent({
|
|
372
|
+
value: ['one'],
|
|
373
|
+
});
|
|
374
|
+
await nextTick();
|
|
375
|
+
|
|
376
|
+
const filteredSearchTerms = wrapper.findAllComponents(GlFilteredSearchTerm);
|
|
377
|
+
|
|
378
|
+
expect(filteredSearchTerms.at(0).props('isLastToken')).toBe(false);
|
|
379
|
+
expect(filteredSearchTerms.at(1).props('isLastToken')).toBe(true);
|
|
380
|
+
});
|
|
347
381
|
});
|
|
348
382
|
|
|
349
383
|
describe('Filtered search integration tests', () => {
|
|
@@ -420,7 +454,7 @@ describe('Filtered search integration tests', () => {
|
|
|
420
454
|
beforeEach(async () => {
|
|
421
455
|
mountComponent();
|
|
422
456
|
activate(0);
|
|
423
|
-
await
|
|
457
|
+
await nextTick();
|
|
424
458
|
});
|
|
425
459
|
|
|
426
460
|
it('brings focus to term element input', () => {
|
|
@@ -441,7 +475,7 @@ describe('Filtered search integration tests', () => {
|
|
|
441
475
|
const input = findInput();
|
|
442
476
|
input.setValue('sta'); // partial of "static"
|
|
443
477
|
|
|
444
|
-
await
|
|
478
|
+
await nextTick();
|
|
445
479
|
|
|
446
480
|
const suggestions = wrapper.findComponent(GlFilteredSearchSuggestionList);
|
|
447
481
|
expect(suggestions.exists()).toBe(true);
|
|
@@ -452,7 +486,7 @@ describe('Filtered search integration tests', () => {
|
|
|
452
486
|
const input = findInput();
|
|
453
487
|
input.setValue('--wrong-- ');
|
|
454
488
|
|
|
455
|
-
await
|
|
489
|
+
await nextTick();
|
|
456
490
|
|
|
457
491
|
const suggestions = wrapper.findComponent(GlFilteredSearchSuggestionList);
|
|
458
492
|
expect(suggestions.exists()).toBe(true);
|
|
@@ -463,7 +497,7 @@ describe('Filtered search integration tests', () => {
|
|
|
463
497
|
const input = findInput();
|
|
464
498
|
input.setValue('--wrong--');
|
|
465
499
|
|
|
466
|
-
await
|
|
500
|
+
await nextTick();
|
|
467
501
|
|
|
468
502
|
const suggestions = wrapper.findComponent(GlFilteredSearchSuggestionList);
|
|
469
503
|
expect(suggestions.exists()).toBe(false);
|
|
@@ -473,11 +507,11 @@ describe('Filtered search integration tests', () => {
|
|
|
473
507
|
const input = findInput();
|
|
474
508
|
input.trigger('keydown', { key: 'ArrowDown' });
|
|
475
509
|
|
|
476
|
-
await
|
|
510
|
+
await nextTick();
|
|
477
511
|
|
|
478
512
|
input.trigger('keydown', { key: 'Enter' });
|
|
479
513
|
|
|
480
|
-
await
|
|
514
|
+
await nextTick();
|
|
481
515
|
|
|
482
516
|
const token = wrapper.findComponent(GlFilteredSearchToken);
|
|
483
517
|
expect(token.exists()).toBe(true);
|
|
@@ -488,9 +522,9 @@ describe('Filtered search integration tests', () => {
|
|
|
488
522
|
|
|
489
523
|
const input = findInput();
|
|
490
524
|
input.trigger('keydown', { key: 'ArrowDown' });
|
|
491
|
-
await
|
|
525
|
+
await nextTick();
|
|
492
526
|
input.trigger('keydown', { key: 'Enter' });
|
|
493
|
-
await
|
|
527
|
+
await nextTick();
|
|
494
528
|
|
|
495
529
|
expect(wrapper.props('value')).toEqual(initialValue);
|
|
496
530
|
});
|
|
@@ -500,11 +534,11 @@ describe('Filtered search integration tests', () => {
|
|
|
500
534
|
input.trigger('keydown', { key: 'ArrowDown' });
|
|
501
535
|
const alignSuggestionsSpy = jest.spyOn(wrapper.vm, 'alignSuggestions');
|
|
502
536
|
|
|
503
|
-
await
|
|
537
|
+
await nextTick();
|
|
504
538
|
|
|
505
539
|
input.trigger('keydown', { key: 'Enter' });
|
|
506
540
|
|
|
507
|
-
await
|
|
541
|
+
await nextTick();
|
|
508
542
|
|
|
509
543
|
expect(alignSuggestionsSpy).toHaveBeenCalled();
|
|
510
544
|
});
|
|
@@ -514,7 +548,7 @@ describe('Filtered search integration tests', () => {
|
|
|
514
548
|
mountComponent({ value: ['token', { type: 'unique', value: { data: 'something' } }] });
|
|
515
549
|
activate(0);
|
|
516
550
|
|
|
517
|
-
await
|
|
551
|
+
await nextTick();
|
|
518
552
|
|
|
519
553
|
const suggestions = wrapper.findComponent(GlFilteredSearchSuggestionList);
|
|
520
554
|
expect(suggestions.exists()).toBe(true);
|
|
@@ -525,27 +559,27 @@ describe('Filtered search integration tests', () => {
|
|
|
525
559
|
mountComponent({ value: ['one two'] });
|
|
526
560
|
activate(0);
|
|
527
561
|
|
|
528
|
-
await
|
|
562
|
+
await nextTick();
|
|
529
563
|
|
|
530
564
|
activate(1);
|
|
531
565
|
|
|
532
|
-
await
|
|
566
|
+
await nextTick();
|
|
533
567
|
|
|
534
568
|
expect(wrapper.findAllComponents(GlFilteredSearchTerm).at(1).find('input').exists()).toBe(true);
|
|
535
569
|
});
|
|
536
570
|
|
|
537
571
|
it('correctly switches focus on token destroy', async () => {
|
|
538
572
|
mountComponent({ value: ['one t three'] });
|
|
539
|
-
await
|
|
573
|
+
await nextTick();
|
|
540
574
|
|
|
541
575
|
activate(1);
|
|
542
576
|
|
|
543
|
-
await
|
|
577
|
+
await nextTick();
|
|
544
578
|
|
|
545
579
|
// Unfortunately backspace is not working in JSDOM
|
|
546
580
|
wrapper.findAllComponents(GlFilteredSearchTerm).at(1).vm.$emit('destroy');
|
|
547
581
|
|
|
548
|
-
await
|
|
582
|
+
await nextTick();
|
|
549
583
|
|
|
550
584
|
expect(document.activeElement).toBe(
|
|
551
585
|
wrapper.findComponent(GlFilteredSearchTerm).find('input').element
|
|
@@ -554,14 +588,14 @@ describe('Filtered search integration tests', () => {
|
|
|
554
588
|
|
|
555
589
|
it('clicking clear button clears component input', async () => {
|
|
556
590
|
mountComponent({ value: ['one two three'] });
|
|
557
|
-
await
|
|
591
|
+
await nextTick();
|
|
558
592
|
|
|
559
593
|
wrapper
|
|
560
594
|
.findAll('button')
|
|
561
595
|
.filter((b) => b.attributes('name') === 'clear')
|
|
562
596
|
.trigger('click');
|
|
563
597
|
|
|
564
|
-
await
|
|
598
|
+
await nextTick();
|
|
565
599
|
|
|
566
600
|
expect(wrapper.findAllComponents(GlFilteredSearchTerm)).toHaveLength(1);
|
|
567
601
|
});
|
|
@@ -85,6 +85,16 @@ export default {
|
|
|
85
85
|
required: false,
|
|
86
86
|
default: false,
|
|
87
87
|
},
|
|
88
|
+
searchButtonAttributes: {
|
|
89
|
+
type: Object,
|
|
90
|
+
required: false,
|
|
91
|
+
default: () => ({}),
|
|
92
|
+
},
|
|
93
|
+
searchInputAttributes: {
|
|
94
|
+
type: Object,
|
|
95
|
+
required: false,
|
|
96
|
+
default: () => ({}),
|
|
97
|
+
},
|
|
88
98
|
},
|
|
89
99
|
data() {
|
|
90
100
|
return {
|
|
@@ -253,6 +263,7 @@ export default {
|
|
|
253
263
|
:value="tokens"
|
|
254
264
|
:history-items="historyItems"
|
|
255
265
|
:clearable="hasValue"
|
|
266
|
+
:search-button-attributes="searchButtonAttributes"
|
|
256
267
|
data-testid="filtered-search-input"
|
|
257
268
|
@submit="submit"
|
|
258
269
|
@input="applyNewValue"
|
|
@@ -278,6 +289,8 @@ export default {
|
|
|
278
289
|
:index="idx"
|
|
279
290
|
:placeholder="termPlaceholder"
|
|
280
291
|
:show-friendly-text="showFriendlyText"
|
|
292
|
+
:search-input-attributes="searchInputAttributes"
|
|
293
|
+
:is-last-token="isLastToken(idx)"
|
|
281
294
|
class="gl-filtered-search-item"
|
|
282
295
|
:class="{
|
|
283
296
|
'gl-filtered-search-last-item': isLastToken(idx),
|
|
@@ -13,6 +13,12 @@ export default {
|
|
|
13
13
|
value: {
|
|
14
14
|
additionalInfo: 'Current term value',
|
|
15
15
|
},
|
|
16
|
+
searchInputAttributes: {
|
|
17
|
+
additionalInfo: 'HTML attributes to add to the search input',
|
|
18
|
+
},
|
|
19
|
+
isLastToken: {
|
|
20
|
+
additionalInfo: 'If this is the last token',
|
|
21
|
+
},
|
|
16
22
|
},
|
|
17
23
|
events: [
|
|
18
24
|
{ event: 'activate', description: 'Emitted when this term token is clicked' },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { nextTick } from 'vue';
|
|
1
2
|
import { shallowMount } from '@vue/test-utils';
|
|
2
3
|
import GlFilteredSearchSuggestion from './filtered_search_suggestion.vue';
|
|
3
4
|
import FilteredSearchTerm from './filtered_search_term.vue';
|
|
@@ -11,6 +12,8 @@ const availableTokens = [
|
|
|
11
12
|
describe('Filtered search term', () => {
|
|
12
13
|
let wrapper;
|
|
13
14
|
|
|
15
|
+
const searchInputAttributes = { 'data-qa-selector': 'foo-bar' };
|
|
16
|
+
|
|
14
17
|
const defaultProps = {
|
|
15
18
|
availableTokens: [],
|
|
16
19
|
};
|
|
@@ -18,6 +21,7 @@ describe('Filtered search term', () => {
|
|
|
18
21
|
const segmentStub = {
|
|
19
22
|
name: 'gl-filtered-search-token-segment-stub',
|
|
20
23
|
template: '<div><slot name="view"></slot><slot name="suggestions"></slot></div>',
|
|
24
|
+
props: ['searchInputAttributes', 'isLastToken'],
|
|
21
25
|
};
|
|
22
26
|
|
|
23
27
|
const createComponent = (props) => {
|
|
@@ -29,6 +33,8 @@ describe('Filtered search term', () => {
|
|
|
29
33
|
});
|
|
30
34
|
};
|
|
31
35
|
|
|
36
|
+
const findTokenSegmentComponent = () => wrapper.findComponent(segmentStub);
|
|
37
|
+
|
|
32
38
|
it('renders value in inactive mode', () => {
|
|
33
39
|
createComponent({ value: { data: 'test-value' } });
|
|
34
40
|
expect(wrapper.html()).toMatchSnapshot();
|
|
@@ -44,11 +50,12 @@ describe('Filtered search term', () => {
|
|
|
44
50
|
expect(wrapper.find('input').attributes('placeholder')).toBe('placeholder-stub');
|
|
45
51
|
});
|
|
46
52
|
|
|
47
|
-
it('filters suggestions by input', () => {
|
|
53
|
+
it('filters suggestions by input', async () => {
|
|
48
54
|
createComponent({ availableTokens, active: true, value: { data: 'test1' } });
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
|
|
56
|
+
await nextTick();
|
|
57
|
+
|
|
58
|
+
expect(wrapper.findAllComponents(GlFilteredSearchSuggestion)).toHaveLength(2);
|
|
52
59
|
});
|
|
53
60
|
|
|
54
61
|
it.each`
|
|
@@ -61,14 +68,40 @@ describe('Filtered search term', () => {
|
|
|
61
68
|
${'backspace'} | ${'destroy'}
|
|
62
69
|
`(
|
|
63
70
|
'emits $emittedEvent when token segment emits $originalEvent',
|
|
64
|
-
({ originalEvent, emittedEvent }) => {
|
|
71
|
+
async ({ originalEvent, emittedEvent }) => {
|
|
65
72
|
createComponent({ active: true, value: { data: 'something' } });
|
|
66
73
|
|
|
67
|
-
|
|
74
|
+
findTokenSegmentComponent().vm.$emit(originalEvent);
|
|
75
|
+
|
|
76
|
+
await nextTick();
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
expect(wrapper.emitted()[emittedEvent]).toHaveLength(1);
|
|
71
|
-
});
|
|
78
|
+
expect(wrapper.emitted()[emittedEvent]).toHaveLength(1);
|
|
72
79
|
}
|
|
73
80
|
);
|
|
81
|
+
|
|
82
|
+
it('passes `searchInputAttributes` and `isLastToken` prop to `GlFilteredSearchTokenSegment`', () => {
|
|
83
|
+
const isLastToken = true;
|
|
84
|
+
|
|
85
|
+
createComponent({
|
|
86
|
+
value: { data: 'something' },
|
|
87
|
+
searchInputAttributes,
|
|
88
|
+
isLastToken,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(findTokenSegmentComponent().props()).toEqual({
|
|
92
|
+
searchInputAttributes,
|
|
93
|
+
isLastToken,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('adds `searchInputAttributes` prop to search term input', () => {
|
|
98
|
+
createComponent({
|
|
99
|
+
placeholder: 'placeholder-stub',
|
|
100
|
+
searchInputAttributes,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
expect(wrapper.find('input').attributes('data-qa-selector')).toBe(
|
|
104
|
+
searchInputAttributes['data-qa-selector']
|
|
105
|
+
);
|
|
106
|
+
});
|
|
74
107
|
});
|
|
@@ -28,6 +28,16 @@ export default {
|
|
|
28
28
|
required: false,
|
|
29
29
|
default: '',
|
|
30
30
|
},
|
|
31
|
+
searchInputAttributes: {
|
|
32
|
+
type: Object,
|
|
33
|
+
required: false,
|
|
34
|
+
default: () => ({}),
|
|
35
|
+
},
|
|
36
|
+
isLastToken: {
|
|
37
|
+
type: Boolean,
|
|
38
|
+
required: false,
|
|
39
|
+
default: false,
|
|
40
|
+
},
|
|
31
41
|
},
|
|
32
42
|
computed: {
|
|
33
43
|
suggestedTokens() {
|
|
@@ -54,6 +64,8 @@ export default {
|
|
|
54
64
|
class="gl-filtered-search-term-token"
|
|
55
65
|
:active="active"
|
|
56
66
|
:class="{ 'gl-w-full': placeholder }"
|
|
67
|
+
:search-input-attributes="searchInputAttributes"
|
|
68
|
+
:is-last-token="isLastToken"
|
|
57
69
|
@activate="$emit('activate')"
|
|
58
70
|
@deactivate="$emit('deactivate')"
|
|
59
71
|
@complete="$emit('replace', { type: $event })"
|
|
@@ -74,6 +86,7 @@ export default {
|
|
|
74
86
|
<template #view>
|
|
75
87
|
<input
|
|
76
88
|
v-if="placeholder"
|
|
89
|
+
v-bind="searchInputAttributes"
|
|
77
90
|
class="gl-filtered-search-term-input"
|
|
78
91
|
:placeholder="placeholder"
|
|
79
92
|
:aria-label="placeholder"
|
|
@@ -19,6 +19,12 @@ export default {
|
|
|
19
19
|
value: {
|
|
20
20
|
additionalInfo: 'Current term value',
|
|
21
21
|
},
|
|
22
|
+
searchInputAttributes: {
|
|
23
|
+
additionalInfo: 'HTML attributes to add to the search input',
|
|
24
|
+
},
|
|
25
|
+
isLastToken: {
|
|
26
|
+
additionalInfo: 'If this is the last token',
|
|
27
|
+
},
|
|
22
28
|
},
|
|
23
29
|
events: [
|
|
24
30
|
{ event: 'activate', description: 'Emitted on mousedown event on the main component' },
|
|
@@ -6,6 +6,8 @@ const OPTIONS = [{ value: '=' }, { value: '!=' }];
|
|
|
6
6
|
describe('Filtered search token segment', () => {
|
|
7
7
|
let wrapper;
|
|
8
8
|
|
|
9
|
+
const searchInputAttributes = { 'data-qa-selector': 'foo-bar' };
|
|
10
|
+
|
|
9
11
|
beforeAll(() => {
|
|
10
12
|
if (!HTMLElement.prototype.scrollIntoView) {
|
|
11
13
|
HTMLElement.prototype.scrollIntoView = jest.fn();
|
|
@@ -251,4 +253,55 @@ describe('Filtered search token segment', () => {
|
|
|
251
253
|
});
|
|
252
254
|
});
|
|
253
255
|
});
|
|
256
|
+
|
|
257
|
+
describe('when input is active', () => {
|
|
258
|
+
it('adds `searchInputAttributes` prop to search token segment input', () => {
|
|
259
|
+
createComponent({ active: true, value: 'something', searchInputAttributes });
|
|
260
|
+
|
|
261
|
+
expect(wrapper.find('input').attributes('data-qa-selector')).toBe(
|
|
262
|
+
searchInputAttributes['data-qa-selector']
|
|
263
|
+
);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('does not add `searchInputAttributes` prop to search token segment', () => {
|
|
267
|
+
createComponent({
|
|
268
|
+
active: true,
|
|
269
|
+
value: 'something',
|
|
270
|
+
searchInputAttributes,
|
|
271
|
+
isLastToken: true,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
expect(wrapper.attributes('data-qa-selector')).toBe(undefined);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe('when input is not active', () => {
|
|
279
|
+
describe('when `isLastToken` prop is `true`', () => {
|
|
280
|
+
it('adds `searchInputAttributes` prop to search token segment', () => {
|
|
281
|
+
createComponent({
|
|
282
|
+
active: false,
|
|
283
|
+
value: 'something',
|
|
284
|
+
searchInputAttributes,
|
|
285
|
+
isLastToken: true,
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
expect(wrapper.attributes('data-qa-selector')).toBe(
|
|
289
|
+
searchInputAttributes['data-qa-selector']
|
|
290
|
+
);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe('when `isLastToken` prop is `false`', () => {
|
|
295
|
+
it('does not add `searchInputAttributes` prop to search token segment', () => {
|
|
296
|
+
createComponent({
|
|
297
|
+
active: false,
|
|
298
|
+
value: 'something',
|
|
299
|
+
searchInputAttributes,
|
|
300
|
+
isLastToken: false,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
expect(wrapper.attributes('data-qa-selector')).toBe(undefined);
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
254
307
|
});
|
|
@@ -49,6 +49,16 @@ export default {
|
|
|
49
49
|
required: true,
|
|
50
50
|
validator: () => true,
|
|
51
51
|
},
|
|
52
|
+
searchInputAttributes: {
|
|
53
|
+
type: Object,
|
|
54
|
+
required: false,
|
|
55
|
+
default: () => ({}),
|
|
56
|
+
},
|
|
57
|
+
isLastToken: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
required: false,
|
|
60
|
+
default: false,
|
|
61
|
+
},
|
|
52
62
|
},
|
|
53
63
|
|
|
54
64
|
data() {
|
|
@@ -244,6 +254,7 @@ export default {
|
|
|
244
254
|
|
|
245
255
|
<template>
|
|
246
256
|
<div
|
|
257
|
+
v-bind="isLastToken && !active && searchInputAttributes"
|
|
247
258
|
class="gl-filtered-search-token-segment"
|
|
248
259
|
:class="{ 'gl-filtered-search-token-segment-active': active }"
|
|
249
260
|
data-testid="filtered-search-token-segment"
|
|
@@ -252,6 +263,7 @@ export default {
|
|
|
252
263
|
<template v-if="active">
|
|
253
264
|
<input
|
|
254
265
|
ref="input"
|
|
266
|
+
v-bind="searchInputAttributes"
|
|
255
267
|
v-model="inputValue"
|
|
256
268
|
class="gl-filtered-search-token-segment-input"
|
|
257
269
|
:aria-label="label"
|
|
@@ -52,6 +52,9 @@ export default {
|
|
|
52
52
|
additionalInfo:
|
|
53
53
|
'Container for tooltip. Valid values: DOM node, selector string or `false` for default',
|
|
54
54
|
},
|
|
55
|
+
searchButtonAttributes: {
|
|
56
|
+
additionalInfo: 'HTML attributes to add to the search button',
|
|
57
|
+
},
|
|
55
58
|
},
|
|
56
59
|
events: [
|
|
57
60
|
{
|
|
@@ -25,6 +25,7 @@ describe('search box by click component', () => {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const findClearIcon = () => wrapper.findComponent(ClearIcon);
|
|
28
|
+
const findSearchButton = () => wrapper.find('[data-testid="search-button"]');
|
|
28
29
|
|
|
29
30
|
it('emits input event when input changes', async () => {
|
|
30
31
|
createComponent({ value: 'somevalue' });
|
|
@@ -125,8 +126,8 @@ describe('search box by click component', () => {
|
|
|
125
126
|
});
|
|
126
127
|
|
|
127
128
|
it('displays disabled search button', () => {
|
|
128
|
-
expect(
|
|
129
|
-
expect(
|
|
129
|
+
expect(findSearchButton().exists()).toBe(true);
|
|
130
|
+
expect(findSearchButton().attributes('disabled')).toBe('true');
|
|
130
131
|
});
|
|
131
132
|
|
|
132
133
|
it('does not render clear icon even with value', () => {
|
|
@@ -145,9 +146,19 @@ describe('search box by click component', () => {
|
|
|
145
146
|
|
|
146
147
|
it('emits submit event when search button is pressed', async () => {
|
|
147
148
|
createComponent({ value: 'some-input' });
|
|
148
|
-
|
|
149
|
+
findSearchButton().vm.$emit('click');
|
|
149
150
|
|
|
150
151
|
await wrapper.vm.$nextTick();
|
|
151
152
|
expect(wrapper.emitted().submit[0]).toEqual(['some-input']);
|
|
152
153
|
});
|
|
154
|
+
|
|
155
|
+
it('adds `searchButtonAttributes` prop to search button', () => {
|
|
156
|
+
const searchButtonAttributes = { 'data-qa-selector': 'foo-bar' };
|
|
157
|
+
|
|
158
|
+
createComponent({ searchButtonAttributes });
|
|
159
|
+
|
|
160
|
+
expect(findSearchButton().attributes('data-qa-selector')).toBe(
|
|
161
|
+
searchButtonAttributes['data-qa-selector']
|
|
162
|
+
);
|
|
163
|
+
});
|
|
153
164
|
});
|
|
@@ -84,6 +84,11 @@ export default {
|
|
|
84
84
|
validator: (value) =>
|
|
85
85
|
value === false || typeof value === 'string' || value instanceof HTMLElement,
|
|
86
86
|
},
|
|
87
|
+
searchButtonAttributes: {
|
|
88
|
+
type: Object,
|
|
89
|
+
required: false,
|
|
90
|
+
default: () => ({}),
|
|
91
|
+
},
|
|
87
92
|
},
|
|
88
93
|
data() {
|
|
89
94
|
return {
|
|
@@ -216,11 +221,13 @@ export default {
|
|
|
216
221
|
/>
|
|
217
222
|
<template #append class="gl-search-box-by-click-input-group-control">
|
|
218
223
|
<gl-button
|
|
224
|
+
v-bind="searchButtonAttributes"
|
|
219
225
|
ref="searchButton"
|
|
220
226
|
class="gl-search-box-by-click-search-button"
|
|
221
227
|
icon="search"
|
|
222
228
|
:disabled="disabled"
|
|
223
229
|
aria-label="Search"
|
|
230
|
+
data-testid="search-button"
|
|
224
231
|
@click="search(currentValue)"
|
|
225
232
|
/>
|
|
226
233
|
</template>
|