@gitlab/ui 64.24.1 → 65.0.1
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 +19 -0
- package/dist/components/base/button/button.js +2 -2
- package/dist/components/base/dropdown/dropdown.js +12 -1
- package/dist/tokens/css/tokens.css +1 -1
- package/dist/tokens/css/tokens.dark.css +1 -1
- package/dist/tokens/js/tokens.dark.js +1 -1
- package/dist/tokens/js/tokens.js +1 -1
- package/dist/tokens/scss/_tokens.dark.scss +1 -1
- package/dist/tokens/scss/_tokens.scss +1 -1
- package/dist/utils/is_slot_empty.js +34 -0
- package/package.json +8 -7
- package/src/components/base/button/button.spec.js +11 -0
- package/src/components/base/button/button.vue +2 -2
- package/src/components/base/dropdown/dropdown.vue +13 -0
- package/src/utils/is_slot_empty.js +37 -0
- package/src/utils/is_slot_empty.spec.js +73 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## [65.0.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v65.0.0...v65.0.1) (2023-08-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **button:** correctly detect empty slot for icon only ([bbbc03e](https://gitlab.com/gitlab-org/gitlab-ui/commit/bbbc03ef43139bf023573706894cd9ba60cfce0a))
|
|
7
|
+
|
|
8
|
+
# [65.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.24.1...v65.0.0) (2023-08-01)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### chore
|
|
12
|
+
|
|
13
|
+
* move dompurify to peer & dev dependency ([f87d3e6](https://gitlab.com/gitlab-org/gitlab-ui/commit/f87d3e6924e9f7e81affc38b913c87a1ec45a59f))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### BREAKING CHANGES
|
|
17
|
+
|
|
18
|
+
* please upgrade to latest dompurify release
|
|
19
|
+
|
|
1
20
|
## [64.24.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.24.0...v64.24.1) (2023-07-31)
|
|
2
21
|
|
|
3
22
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BButton } from 'bootstrap-vue/esm/index.js';
|
|
2
2
|
import { buttonCategoryOptions, buttonVariantOptions, buttonSizeOptions } from '../../../utils/constants';
|
|
3
3
|
import { logWarning } from '../../../utils/utils';
|
|
4
|
+
import { isSlotEmpty } from '../../../utils/is_slot_empty';
|
|
4
5
|
import { SafeLinkMixin } from '../../mixins/safe_link_mixin';
|
|
5
6
|
import GlIcon from '../icon/icon';
|
|
6
7
|
import GlLoadingIcon from '../loading_icon/loading_icon';
|
|
@@ -75,8 +76,7 @@ var script = {
|
|
|
75
76
|
return this.icon !== '';
|
|
76
77
|
},
|
|
77
78
|
hasIconOnly() {
|
|
78
|
-
|
|
79
|
-
return Object.keys(this.$slots).length === 0 && this.hasIcon;
|
|
79
|
+
return isSlotEmpty(this, 'default') && this.hasIcon;
|
|
80
80
|
},
|
|
81
81
|
isButtonDisabled() {
|
|
82
82
|
return this.disabled || this.loading;
|
|
@@ -47,6 +47,7 @@ var script = {
|
|
|
47
47
|
GlLoadingIcon
|
|
48
48
|
},
|
|
49
49
|
mixins: [ButtonMixin],
|
|
50
|
+
inheritAttrs: false,
|
|
50
51
|
props: {
|
|
51
52
|
headerText: {
|
|
52
53
|
type: String,
|
|
@@ -155,6 +156,16 @@ var script = {
|
|
|
155
156
|
type: Object,
|
|
156
157
|
required: false,
|
|
157
158
|
default: null
|
|
159
|
+
},
|
|
160
|
+
noFlip: {
|
|
161
|
+
type: Boolean,
|
|
162
|
+
required: false,
|
|
163
|
+
default: false
|
|
164
|
+
},
|
|
165
|
+
splitHref: {
|
|
166
|
+
type: String,
|
|
167
|
+
required: false,
|
|
168
|
+
default: ''
|
|
158
169
|
}
|
|
159
170
|
},
|
|
160
171
|
computed: {
|
|
@@ -218,7 +229,7 @@ var script = {
|
|
|
218
229
|
const __vue_script__ = script;
|
|
219
230
|
|
|
220
231
|
/* template */
|
|
221
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-dropdown',_vm._g(_vm._b({ref:"dropdown",staticClass:"gl-dropdown",attrs:{"split":_vm.split,"variant":_vm.variant,"size":_vm.buttonSize,"toggle-class":[_vm.toggleButtonClasses],"split-class":_vm.splitButtonClasses,"block":_vm.block,"disabled":_vm.disabled || _vm.loading,"right":_vm.right,"popper-opts":_vm.popperOptions},scopedSlots:_vm._u([{key:"button-content",fn:function(){return [_vm._t("button-content",function(){return [(_vm.loading)?_c('gl-loading-icon',{class:{ 'gl-mr-2': !_vm.isIconOnly }}):_vm._e(),_vm._v(" "),(_vm.icon && !(_vm.isIconOnly && _vm.loading))?_c('gl-icon',{staticClass:"dropdown-icon",attrs:{"name":_vm.icon}}):_vm._e(),_vm._v(" "),_c('span',{staticClass:"gl-dropdown-button-text",class:{ 'gl-sr-only': _vm.textSrOnly }},[_vm._t("button-text",function(){return [_vm._v(_vm._s(_vm.buttonText))]})],2),_vm._v(" "),(_vm.renderCaret)?_c('gl-icon',{staticClass:"gl-button-icon dropdown-chevron",attrs:{"name":"chevron-down"}}):_vm._e()]})]},proxy:true}],null,true)},'b-dropdown',_vm.$attrs,false),_vm.$listeners),[_c('div',{staticClass:"gl-dropdown-inner"},[(_vm.hasSlotContents('header') || _vm.headerText)?_c('div',{staticClass:"gl-dropdown-header",class:{ 'gl-border-b-0!': _vm.hideHeaderBorder }},[(_vm.headerText)?_c('p',{staticClass:"gl-dropdown-header-top"},[_vm._v("\n "+_vm._s(_vm.headerText)+"\n ")]):_vm._e(),_vm._v(" "),_vm._t("header")],2):_vm._e(),_vm._v(" "),(_vm.hasHighlightedItemsOrClearAll)?_c('div',{staticClass:"gl-display-flex gl-flex-direction-row gl-justify-content-space-between gl-align-items-center"},[(_vm.hasHighlightedItemsContent && _vm.showHighlightedItemsTitle)?_c('div',{staticClass:"gl-display-flex gl-flex-grow-1 gl-justify-content-flex-start",class:_vm.highlightedItemsTitleClass},[_c('span',{staticClass:"gl-font-weight-bold",attrs:{"data-testid":"highlighted-items-title"}},[_vm._v(_vm._s(_vm.highlightedItemsTitle))])]):_vm._e(),_vm._v(" "),(_vm.showClearAll)?_c('div',{staticClass:"gl-display-flex gl-flex-grow-1 gl-justify-content-end",class:_vm.clearAllTextClass},[_c('gl-button',{attrs:{"size":"small","category":"tertiary","variant":"link","data-testid":"clear-all-button"},on:{"click":function($event){return _vm.$emit('clear-all', $event)}}},[_vm._v(_vm._s(_vm.clearAllText))])],1):_vm._e()]):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-dropdown-contents"},[(_vm.hasHighlightedItemsContent)?_c('div',{staticClass:"gl-overflow-visible",attrs:{"data-testid":"highlighted-items"}},[_vm._t("highlighted-items"),_vm._v(" "),_c('gl-dropdown-divider')],2):_vm._e(),_vm._v(" "),_vm._t("default")],2),_vm._v(" "),(_vm.hasSlotContents('footer'))?_c('div',{staticClass:"gl-dropdown-footer"},[_vm._t("footer")],2):_vm._e()])])};
|
|
232
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('b-dropdown',_vm._g(_vm._b({ref:"dropdown",staticClass:"gl-dropdown",attrs:{"split":_vm.split,"variant":_vm.variant,"size":_vm.buttonSize,"toggle-class":[_vm.toggleButtonClasses],"split-class":_vm.splitButtonClasses,"block":_vm.block,"disabled":_vm.disabled || _vm.loading,"right":_vm.right,"popper-opts":_vm.popperOptions,"no-flip":_vm.noFlip,"split-href":_vm.splitHref},scopedSlots:_vm._u([{key:"button-content",fn:function(){return [_vm._t("button-content",function(){return [(_vm.loading)?_c('gl-loading-icon',{class:{ 'gl-mr-2': !_vm.isIconOnly }}):_vm._e(),_vm._v(" "),(_vm.icon && !(_vm.isIconOnly && _vm.loading))?_c('gl-icon',{staticClass:"dropdown-icon",attrs:{"name":_vm.icon}}):_vm._e(),_vm._v(" "),_c('span',{staticClass:"gl-dropdown-button-text",class:{ 'gl-sr-only': _vm.textSrOnly }},[_vm._t("button-text",function(){return [_vm._v(_vm._s(_vm.buttonText))]})],2),_vm._v(" "),(_vm.renderCaret)?_c('gl-icon',{staticClass:"gl-button-icon dropdown-chevron",attrs:{"name":"chevron-down"}}):_vm._e()]})]},proxy:true}],null,true)},'b-dropdown',_vm.$attrs,false),_vm.$listeners),[_c('div',{staticClass:"gl-dropdown-inner"},[(_vm.hasSlotContents('header') || _vm.headerText)?_c('div',{staticClass:"gl-dropdown-header",class:{ 'gl-border-b-0!': _vm.hideHeaderBorder }},[(_vm.headerText)?_c('p',{staticClass:"gl-dropdown-header-top"},[_vm._v("\n "+_vm._s(_vm.headerText)+"\n ")]):_vm._e(),_vm._v(" "),_vm._t("header")],2):_vm._e(),_vm._v(" "),(_vm.hasHighlightedItemsOrClearAll)?_c('div',{staticClass:"gl-display-flex gl-flex-direction-row gl-justify-content-space-between gl-align-items-center"},[(_vm.hasHighlightedItemsContent && _vm.showHighlightedItemsTitle)?_c('div',{staticClass:"gl-display-flex gl-flex-grow-1 gl-justify-content-flex-start",class:_vm.highlightedItemsTitleClass},[_c('span',{staticClass:"gl-font-weight-bold",attrs:{"data-testid":"highlighted-items-title"}},[_vm._v(_vm._s(_vm.highlightedItemsTitle))])]):_vm._e(),_vm._v(" "),(_vm.showClearAll)?_c('div',{staticClass:"gl-display-flex gl-flex-grow-1 gl-justify-content-end",class:_vm.clearAllTextClass},[_c('gl-button',{attrs:{"size":"small","category":"tertiary","variant":"link","data-testid":"clear-all-button"},on:{"click":function($event){return _vm.$emit('clear-all', $event)}}},[_vm._v(_vm._s(_vm.clearAllText))])],1):_vm._e()]):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-dropdown-contents"},[(_vm.hasHighlightedItemsContent)?_c('div',{staticClass:"gl-overflow-visible",attrs:{"data-testid":"highlighted-items"}},[_vm._t("highlighted-items"),_vm._v(" "),_c('gl-dropdown-divider')],2):_vm._e(),_vm._v(" "),_vm._t("default")],2),_vm._v(" "),(_vm.hasSlotContents('footer'))?_c('div',{staticClass:"gl-dropdown-footer"},[_vm._t("footer")],2):_vm._e()])])};
|
|
222
233
|
var __vue_staticRenderFns__ = [];
|
|
223
234
|
|
|
224
235
|
/* style */
|
package/dist/tokens/js/tokens.js
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Vue from 'vue';
|
|
2
|
+
|
|
3
|
+
// Fragment will be available only in Vue.js 3
|
|
4
|
+
const {
|
|
5
|
+
Fragment,
|
|
6
|
+
Comment
|
|
7
|
+
} = Vue;
|
|
8
|
+
function callIfNeeded(fnOrResult, args) {
|
|
9
|
+
return fnOrResult instanceof Function ? fnOrResult(args) : fnOrResult;
|
|
10
|
+
}
|
|
11
|
+
function isEmpty(vnode) {
|
|
12
|
+
if (!vnode || Comment && vnode.type === Comment) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(vnode)) {
|
|
16
|
+
return vnode.every(isEmpty);
|
|
17
|
+
}
|
|
18
|
+
if (Fragment && vnode.type === Fragment) {
|
|
19
|
+
// Vue.js 3 fragment, check children
|
|
20
|
+
return vnode.children.every(isEmpty);
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
function isSlotEmpty(vueInstance, slot, slotArgs) {
|
|
25
|
+
var _vueInstance$$scopedS, _vueInstance$$scopedS2;
|
|
26
|
+
const isVue3 = Boolean(Fragment);
|
|
27
|
+
const slotContent = isVue3 ?
|
|
28
|
+
// we need to check both $slots and $scopedSlots due to https://github.com/vuejs/core/issues/8869
|
|
29
|
+
// additionally, in @vue/compat $slot might be a function instead of array of vnodes (sigh)
|
|
30
|
+
callIfNeeded(vueInstance.$slots[slot] || vueInstance.$scopedSlots[slot], slotArgs) : (_vueInstance$$scopedS = (_vueInstance$$scopedS2 = vueInstance.$scopedSlots)[slot]) === null || _vueInstance$$scopedS === void 0 ? void 0 : _vueInstance$$scopedS.call(_vueInstance$$scopedS2, slotArgs);
|
|
31
|
+
return isEmpty(slotContent);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { isSlotEmpty };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "65.0.1",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -65,7 +65,6 @@
|
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"@floating-ui/dom": "1.2.9",
|
|
67
67
|
"bootstrap-vue": "2.23.1",
|
|
68
|
-
"dompurify": "^2.4.5",
|
|
69
68
|
"echarts": "^5.3.2",
|
|
70
69
|
"iframe-resizer": "^4.3.2",
|
|
71
70
|
"lodash": "^4.17.20",
|
|
@@ -75,6 +74,7 @@
|
|
|
75
74
|
"peerDependencies": {
|
|
76
75
|
"@gitlab/svgs": "^1.116.0 || ^2.0.0 || ^3.0.0",
|
|
77
76
|
"bootstrap": ">=4.5.3 <=4.6.2",
|
|
77
|
+
"dompurify": "^2.4.7 || ^3.0.5",
|
|
78
78
|
"emoji-regex": ">=10.0.0",
|
|
79
79
|
"pikaday": "^1.8.0",
|
|
80
80
|
"vue": "^2.6.10"
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"@gitlab/eslint-plugin": "19.0.0",
|
|
92
92
|
"@gitlab/fonts": "^1.2.0",
|
|
93
93
|
"@gitlab/stylelint-config": "4.1.0",
|
|
94
|
-
"@gitlab/svgs": "3.
|
|
94
|
+
"@gitlab/svgs": "3.58.0",
|
|
95
95
|
"@rollup/plugin-commonjs": "^11.1.0",
|
|
96
96
|
"@rollup/plugin-node-resolve": "^7.1.3",
|
|
97
97
|
"@rollup/plugin-replace": "^2.3.2",
|
|
@@ -119,17 +119,18 @@
|
|
|
119
119
|
"babel-plugin-require-context-hook": "^1.0.0",
|
|
120
120
|
"bootstrap": "4.6.2",
|
|
121
121
|
"cypress": "12.17.2",
|
|
122
|
+
"dompurify": "^2.4.7",
|
|
122
123
|
"emoji-regex": "^10.0.0",
|
|
123
|
-
"eslint": "8.
|
|
124
|
+
"eslint": "8.46.0",
|
|
124
125
|
"eslint-import-resolver-jest": "3.0.2",
|
|
125
126
|
"eslint-plugin-cypress": "2.13.3",
|
|
126
127
|
"eslint-plugin-storybook": "0.6.12",
|
|
127
128
|
"glob": "^7.2.0",
|
|
128
129
|
"identity-obj-proxy": "^3.0.0",
|
|
129
130
|
"inquirer-select-directory": "^1.2.0",
|
|
130
|
-
"jest": "^29.6.
|
|
131
|
-
"jest-circus": "29.6.
|
|
132
|
-
"jest-environment-jsdom": "29.6.
|
|
131
|
+
"jest": "^29.6.2",
|
|
132
|
+
"jest-circus": "29.6.2",
|
|
133
|
+
"jest-environment-jsdom": "29.6.2",
|
|
133
134
|
"markdownlint-cli": "^0.29.0",
|
|
134
135
|
"mockdate": "^2.0.5",
|
|
135
136
|
"module-alias": "^2.2.2",
|
|
@@ -211,4 +211,15 @@ describe('button component', () => {
|
|
|
211
211
|
});
|
|
212
212
|
});
|
|
213
213
|
});
|
|
214
|
+
|
|
215
|
+
it('should correctly detect empty content for icon only mode', () => {
|
|
216
|
+
const DemoComponent = {
|
|
217
|
+
components: { GlButton },
|
|
218
|
+
template: `<gl-button icon="ellipsis_h"><slot><span v-if="false">not-rendered</span></slot></gl-button>`,
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
wrapper = mount(DemoComponent);
|
|
222
|
+
|
|
223
|
+
expect(wrapper.classes()).toContain('btn-icon');
|
|
224
|
+
});
|
|
214
225
|
});
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
buttonSizeOptions,
|
|
8
8
|
} from '../../../utils/constants';
|
|
9
9
|
import { logWarning } from '../../../utils/utils';
|
|
10
|
+
import { isSlotEmpty } from '../../../utils/is_slot_empty';
|
|
10
11
|
import { SafeLinkMixin } from '../../mixins/safe_link_mixin';
|
|
11
12
|
import GlIcon from '../icon/icon.vue';
|
|
12
13
|
import GlLoadingIcon from '../loading_icon/loading_icon.vue';
|
|
@@ -79,8 +80,7 @@ export default {
|
|
|
79
80
|
return this.icon !== '';
|
|
80
81
|
},
|
|
81
82
|
hasIconOnly() {
|
|
82
|
-
|
|
83
|
-
return Object.keys(this.$slots).length === 0 && this.hasIcon;
|
|
83
|
+
return isSlotEmpty(this, 'default') && this.hasIcon;
|
|
84
84
|
},
|
|
85
85
|
isButtonDisabled() {
|
|
86
86
|
return this.disabled || this.loading;
|
|
@@ -54,6 +54,7 @@ export default {
|
|
|
54
54
|
GlLoadingIcon,
|
|
55
55
|
},
|
|
56
56
|
mixins: [ButtonMixin],
|
|
57
|
+
inheritAttrs: false,
|
|
57
58
|
props: {
|
|
58
59
|
headerText: {
|
|
59
60
|
type: String,
|
|
@@ -163,6 +164,16 @@ export default {
|
|
|
163
164
|
required: false,
|
|
164
165
|
default: null,
|
|
165
166
|
},
|
|
167
|
+
noFlip: {
|
|
168
|
+
type: Boolean,
|
|
169
|
+
required: false,
|
|
170
|
+
default: false,
|
|
171
|
+
},
|
|
172
|
+
splitHref: {
|
|
173
|
+
type: String,
|
|
174
|
+
required: false,
|
|
175
|
+
default: '',
|
|
176
|
+
},
|
|
166
177
|
},
|
|
167
178
|
computed: {
|
|
168
179
|
renderCaret() {
|
|
@@ -247,6 +258,8 @@ export default {
|
|
|
247
258
|
:disabled="disabled || loading"
|
|
248
259
|
:right="right"
|
|
249
260
|
:popper-opts="popperOptions"
|
|
261
|
+
:no-flip="noFlip"
|
|
262
|
+
:split-href="splitHref"
|
|
250
263
|
v-on="$listeners"
|
|
251
264
|
>
|
|
252
265
|
<div class="gl-dropdown-inner">
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Vue from 'vue';
|
|
2
|
+
|
|
3
|
+
// Fragment will be available only in Vue.js 3
|
|
4
|
+
const { Fragment, Comment } = Vue;
|
|
5
|
+
|
|
6
|
+
function callIfNeeded(fnOrResult, args) {
|
|
7
|
+
return fnOrResult instanceof Function ? fnOrResult(args) : fnOrResult;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function isEmpty(vnode) {
|
|
11
|
+
if (!vnode || (Comment && vnode.type === Comment)) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (Array.isArray(vnode)) {
|
|
16
|
+
return vnode.every(isEmpty);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (Fragment && vnode.type === Fragment) {
|
|
20
|
+
// Vue.js 3 fragment, check children
|
|
21
|
+
return vnode.children.every(isEmpty);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isSlotEmpty(vueInstance, slot, slotArgs) {
|
|
28
|
+
const isVue3 = Boolean(Fragment);
|
|
29
|
+
|
|
30
|
+
const slotContent = isVue3
|
|
31
|
+
? // we need to check both $slots and $scopedSlots due to https://github.com/vuejs/core/issues/8869
|
|
32
|
+
// additionally, in @vue/compat $slot might be a function instead of array of vnodes (sigh)
|
|
33
|
+
callIfNeeded(vueInstance.$slots[slot] || vueInstance.$scopedSlots[slot], slotArgs)
|
|
34
|
+
: vueInstance.$scopedSlots[slot]?.(slotArgs);
|
|
35
|
+
|
|
36
|
+
return isEmpty(slotContent);
|
|
37
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { isSlotEmpty } from './is_slot_empty';
|
|
3
|
+
|
|
4
|
+
describe('is slot empty', () => {
|
|
5
|
+
const TestComponent = {
|
|
6
|
+
template: `
|
|
7
|
+
<div>
|
|
8
|
+
<slot></slot>
|
|
9
|
+
</div>
|
|
10
|
+
`,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
it('should return true for empty slot', () => {
|
|
14
|
+
const PassesNothing = {
|
|
15
|
+
components: { TestComponent },
|
|
16
|
+
template: '<test-component></test-component>',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const wrapper = mount(PassesNothing);
|
|
20
|
+
|
|
21
|
+
expect(isSlotEmpty(wrapper.findComponent(TestComponent).vm, 'default')).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should return true for slot with comment', () => {
|
|
25
|
+
const PassesComment = {
|
|
26
|
+
components: { TestComponent },
|
|
27
|
+
template: '<test-component><!-- comment --></test-component>',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const wrapper = mount(PassesComment);
|
|
31
|
+
|
|
32
|
+
expect(isSlotEmpty(wrapper.findComponent(TestComponent).vm, 'default')).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should return true for slot with multiple comments', () => {
|
|
36
|
+
const PassesComment = {
|
|
37
|
+
components: { TestComponent },
|
|
38
|
+
template: '<test-component><!-- comment --><!-- comment2 --></test-component>',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const wrapper = mount(PassesComment);
|
|
42
|
+
|
|
43
|
+
expect(isSlotEmpty(wrapper.findComponent(TestComponent).vm, 'default')).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should return false for non-empty slot', () => {
|
|
47
|
+
const PassesComment = {
|
|
48
|
+
components: { TestComponent },
|
|
49
|
+
template: '<test-component>non-empty</test-component>',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const wrapper = mount(PassesComment);
|
|
53
|
+
|
|
54
|
+
expect(isSlotEmpty(wrapper.findComponent(TestComponent).vm, 'default')).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it.each([true, false])(
|
|
58
|
+
'should return %s for conditional slot contents based on slot-scope',
|
|
59
|
+
(shouldRender) => {
|
|
60
|
+
const PassesComment = {
|
|
61
|
+
components: { TestComponent },
|
|
62
|
+
template:
|
|
63
|
+
'<test-component><template #default="{ shouldRender }"><span v-if="shouldRender">empty</span></template></test-component>',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const wrapper = mount(PassesComment);
|
|
67
|
+
|
|
68
|
+
expect(
|
|
69
|
+
isSlotEmpty(wrapper.findComponent(TestComponent).vm, 'default', { shouldRender })
|
|
70
|
+
).toBe(!shouldRender);
|
|
71
|
+
}
|
|
72
|
+
);
|
|
73
|
+
});
|