Skip to content

Commit 58516a4

Browse files
authored
Merge pull request bootstrap-vue#6905 from bootstrap-vue/vue3-compat-build
feat(compat): add Vue 3 support via @vue/compat
2 parents debe660 + 6ef2ba4 commit 58516a4

File tree

222 files changed

+1761
-1097
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

222 files changed

+1761
-1097
lines changed

.eslintrc.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ module.exports = {
1515
es6: true,
1616
'jest/globals': true
1717
},
18-
globals: {
19-
Vue: true
20-
},
2118
rules: {
2219
'no-unused-vars': [
2320
'error',

.github/workflows/test.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,19 @@ jobs:
125125
- name: Test unit
126126
run: yarn run test:unit --coverage --maxWorkers=2
127127

128+
- name: Test unit (Vue 3)
129+
run: yarn run test:unit --coverage --maxWorkers=2
130+
env:
131+
USE_VUE3: '1'
132+
133+
- name: Merge coverage
134+
run:
135+
npx istanbul-merge --out ./coverage-final.json coverage/coverage-final.json
136+
coverage-vue3/coverage-final.json
137+
128138
- name: CodeCov
129139
uses: codecov/codecov-action@v3.1.1
130140
with:
131141
token: ${{ secrets.CODECOV_TOKEN }}
132142
flags: unittests
143+
files: ./coverage-final.json

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
.vercel/
55
.vscode/
66
coverage/
7+
coverage-vue3/
78
dist/
89
docs-dist/
910
esm/

jest.config.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1+
const useVue3 = 'USE_VUE3' in process.env
2+
3+
const moduleNameMapper = useVue3
4+
? {
5+
'^vue$': '@vue/compat',
6+
'^@vue/test-utils$': '@vue/test-utils-vue3'
7+
}
8+
: {}
9+
110
module.exports = {
211
testRegex: 'spec.js$',
312
moduleFileExtensions: ['js', 'vue'],
13+
moduleNameMapper,
414
transform: {
5-
'^.+\\.js$': 'babel-jest',
6-
'.*\\.(vue)$': 'vue-jest'
15+
'^.+\\.js$': 'babel-jest'
716
},
8-
coverageDirectory: './coverage/',
17+
transformIgnorePatterns: ['/node_modules(?![\\\\/]vue-test-utils-compat[\\\\/])'],
18+
coverageDirectory: useVue3 ? './coverage-vue3' : './coverage/',
919
testEnvironmentOptions: {
1020
pretendToBeVisual: true
1121
},

package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bootstrap-vue",
3-
"version": "2.22.0",
3+
"version": "2.23.0",
44
"description": "With more than 85 components, over 45 available plugins, several directives, and 1000+ icons, BootstrapVue provides one of the most comprehensive implementations of the Bootstrap v4 component and grid system available for Vue.js v2.6, complete with extensive and automated WAI-ARIA accessibility markup.",
55
"main": "./dist/bootstrap-vue.common.js",
66
"web": "./dist/bootstrap-vue.js",
@@ -66,7 +66,7 @@
6666
"docs-gen": "cross-env NODE_ENV=docs nuxt generate -c docs/nuxt.config.js",
6767
"lint": "eslint --ext .js,.md,.vue ./",
6868
"postinstall": "opencollective || exit 0",
69-
"prepare": "husky install",
69+
"prepare": "husky install && yarn run build",
7070
"prettify": "prettier --write '**/*.{js,json,md,scss,ts,vue}'",
7171
"release": "yarn run prettify && yarn run test && yarn run build && yarn run release-notes && standard-version",
7272
"release-notes": "jiti ./scripts/release-notes",
@@ -99,7 +99,10 @@
9999
"@nuxtjs/robots": "^2.5.0",
100100
"@nuxtjs/sitemap": "^2.4.0",
101101
"@testing-library/jest-dom": "^5.12.0",
102+
"@vue/compat": "^3.2.40",
103+
"@vue/compiler-dom": "^3.2.40",
102104
"@vue/test-utils": "^1.3.0",
105+
"@vue/test-utils-vue3": "npm:@vue/test-utils@2.2.0",
103106
"autoprefixer": "^10.4.0",
104107
"babel-core": "^7.0.0-bridge.0",
105108
"babel-eslint": "^10.1.0",
@@ -148,10 +151,10 @@
148151
"standard-version": "^9.3.0",
149152
"terser": "^5.15.0",
150153
"vue": "^2.6.12",
151-
"vue-jest": "^3.0.7",
152154
"vue-router": "^3.5.1",
153155
"vue-server-renderer": "^2.6.12",
154-
"vue-template-compiler": "^2.6.12"
156+
"vue-template-compiler": "^2.6.12",
157+
"vue-test-utils-compat": "0.0.6"
155158
},
156159
"keywords": [
157160
"Bootstrap",

src/components/alert/alert.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { COMPONENT_UID_KEY, Vue } from '../../vue'
21
import { NAME_ALERT } from '../../constants/components'
32
import { EVENT_NAME_DISMISSED, EVENT_NAME_DISMISS_COUNT_DOWN } from '../../constants/events'
43
import {
@@ -7,13 +6,14 @@ import {
76
PROP_TYPE_STRING
87
} from '../../constants/props'
98
import { SLOT_NAME_DISMISS } from '../../constants/slots'
9+
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
1010
import { requestAF } from '../../utils/dom'
1111
import { isBoolean, isNumeric } from '../../utils/inspect'
1212
import { makeModelMixin } from '../../utils/model'
1313
import { toInteger } from '../../utils/number'
1414
import { sortKeys } from '../../utils/object'
1515
import { makeProp, makePropsConfigurable } from '../../utils/props'
16-
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
16+
import { COMPONENT_UID_KEY, extend } from '../../vue'
1717
import { BButtonClose } from '../button/button-close'
1818
import { BVTransition } from '../transition/bv-transition'
1919

@@ -68,7 +68,7 @@ export const props = makePropsConfigurable(
6868
// --- Main component ---
6969

7070
// @vue/component
71-
export const BAlert = /*#__PURE__*/ Vue.extend({
71+
export const BAlert = /*#__PURE__*/ extend({
7272
name: NAME_ALERT,
7373
mixins: [modelMixin, normalizeSlotMixin],
7474
props,

src/components/aspect/aspect.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue } from '../../vue'
1+
import { extend } from '../../vue'
22
import { NAME_ASPECT } from '../../constants/components'
33
import { PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props'
44
import { RX_ASPECT, RX_ASPECT_SEPARATOR } from '../../constants/regex'
@@ -26,7 +26,7 @@ export const props = makePropsConfigurable(
2626
// --- Main component ---
2727

2828
// @vue/component
29-
export const BAspect = /*#__PURE__*/ Vue.extend({
29+
export const BAspect = /*#__PURE__*/ extend({
3030
name: NAME_ASPECT,
3131
mixins: [normalizeSlotMixin],
3232
props,

src/components/avatar/avatar-group.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { Vue } from '../../vue'
21
import { NAME_AVATAR_GROUP } from '../../constants/components'
32
import {
43
PROP_TYPE_BOOLEAN,
54
PROP_TYPE_BOOLEAN_STRING,
65
PROP_TYPE_NUMBER_STRING,
76
PROP_TYPE_STRING
87
} from '../../constants/props'
8+
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
99
import { mathMax, mathMin } from '../../utils/math'
1010
import { toFloat } from '../../utils/number'
1111
import { makeProp, makePropsConfigurable } from '../../utils/props'
12-
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
12+
import { extend } from '../../vue'
1313
import { computeSize } from './avatar'
1414

1515
// --- Props ---
@@ -33,11 +33,11 @@ export const props = makePropsConfigurable(
3333
// --- Main component ---
3434

3535
// @vue/component
36-
export const BAvatarGroup = /*#__PURE__*/ Vue.extend({
36+
export const BAvatarGroup = /*#__PURE__*/ extend({
3737
name: NAME_AVATAR_GROUP,
3838
mixins: [normalizeSlotMixin],
3939
provide() {
40-
return { bvAvatarGroup: this }
40+
return { getBvAvatarGroup: () => this }
4141
},
4242
props,
4343
computed: {

src/components/avatar/avatar.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue } from '../../vue'
1+
import { extend } from '../../vue'
22
import { NAME_AVATAR } from '../../constants/components'
33
import { EVENT_NAME_CLICK, EVENT_NAME_IMG_ERROR } from '../../constants/events'
44
import {
@@ -67,11 +67,11 @@ export const props = makePropsConfigurable(
6767
// --- Main component ---
6868

6969
// @vue/component
70-
export const BAvatar = /*#__PURE__*/ Vue.extend({
70+
export const BAvatar = /*#__PURE__*/ extend({
7171
name: NAME_AVATAR,
7272
mixins: [normalizeSlotMixin],
7373
inject: {
74-
bvAvatarGroup: { default: null }
74+
getBvAvatarGroup: { default: () => () => null }
7575
},
7676
props,
7777
data() {
@@ -80,6 +80,9 @@ export const BAvatar = /*#__PURE__*/ Vue.extend({
8080
}
8181
},
8282
computed: {
83+
bvAvatarGroup() {
84+
return this.getBvAvatarGroup()
85+
},
8386
computedSize() {
8487
// Always use the avatar group size
8588
const { bvAvatarGroup } = this

src/components/avatar/avatar.spec.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ describe('avatar', () => {
250250
const wrapper1 = mount(BAvatar, {
251251
provide: {
252252
// Emulate `undefined`/`null` props
253-
bvAvatarGroup: {}
253+
getBvAvatarGroup: () => ({})
254254
}
255255
})
256256

@@ -265,9 +265,9 @@ describe('avatar', () => {
265265

266266
const wrapper2 = mount(BAvatar, {
267267
provide: {
268-
bvAvatarGroup: {
268+
getBvAvatarGroup: () => ({
269269
variant: 'danger'
270-
}
270+
})
271271
}
272272
})
273273

@@ -289,7 +289,7 @@ describe('avatar', () => {
289289
},
290290
provide: {
291291
// Emulate `undefined`/`null` props
292-
bvAvatarGroup: {}
292+
getBvAvatarGroup: () => ({})
293293
}
294294
})
295295

@@ -307,9 +307,9 @@ describe('avatar', () => {
307307
size: '2em'
308308
},
309309
provide: {
310-
bvAvatarGroup: {
310+
getBvAvatarGroup: () => ({
311311
size: '5em'
312-
}
312+
})
313313
}
314314
})
315315

src/components/badge/badge.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue, mergeData } from '../../vue'
1+
import { extend, mergeData } from '../../vue'
22
import { NAME_BADGE } from '../../constants/components'
33
import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props'
44
import { omit, sortKeys } from '../../utils/object'
@@ -25,7 +25,7 @@ export const props = makePropsConfigurable(
2525
// --- Main component ---
2626

2727
// @vue/component
28-
export const BBadge = /*#__PURE__*/ Vue.extend({
28+
export const BBadge = /*#__PURE__*/ extend({
2929
name: NAME_BADGE,
3030
functional: true,
3131
props,

src/components/breadcrumb/breadcrumb-item.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue, mergeData } from '../../vue'
1+
import { extend, mergeData } from '../../vue'
22
import { NAME_BREADCRUMB_ITEM } from '../../constants/components'
33
import { makePropsConfigurable } from '../../utils/props'
44
import { BBreadcrumbLink, props as BBreadcrumbLinkProps } from './breadcrumb-link'
@@ -10,7 +10,7 @@ export const props = makePropsConfigurable(BBreadcrumbLinkProps, NAME_BREADCRUMB
1010
// --- Main component ---
1111

1212
// @vue/component
13-
export const BBreadcrumbItem = /*#__PURE__*/ Vue.extend({
13+
export const BBreadcrumbItem = /*#__PURE__*/ extend({
1414
name: NAME_BREADCRUMB_ITEM,
1515
functional: true,
1616
props,

src/components/breadcrumb/breadcrumb-link.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue, mergeData } from '../../vue'
1+
import { extend, mergeData } from '../../vue'
22
import { NAME_BREADCRUMB_LINK } from '../../constants/components'
33
import { PROP_TYPE_STRING } from '../../constants/props'
44
import { htmlOrText } from '../../utils/html'
@@ -21,7 +21,7 @@ export const props = makePropsConfigurable(
2121
// --- Main component ---
2222

2323
// @vue/component
24-
export const BBreadcrumbLink = /*#__PURE__*/ Vue.extend({
24+
export const BBreadcrumbLink = /*#__PURE__*/ extend({
2525
name: NAME_BREADCRUMB_LINK,
2626
functional: true,
2727
props,

src/components/breadcrumb/breadcrumb.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue, mergeData } from '../../vue'
1+
import { extend, mergeData } from '../../vue'
22
import { NAME_BREADCRUMB } from '../../constants/components'
33
import { PROP_TYPE_ARRAY } from '../../constants/props'
44
import { isArray, isObject } from '../../utils/inspect'
@@ -18,7 +18,7 @@ export const props = makePropsConfigurable(
1818
// --- Main component ---
1919

2020
// @vue/component
21-
export const BBreadcrumb = /*#__PURE__*/ Vue.extend({
21+
export const BBreadcrumb = /*#__PURE__*/ extend({
2222
name: NAME_BREADCRUMB,
2323
functional: true,
2424
props,

src/components/button-group/button-group.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue, mergeData } from '../../vue'
1+
import { extend, mergeData } from '../../vue'
22
import { NAME_BUTTON_GROUP } from '../../constants/components'
33
import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props'
44
import { pick, sortKeys } from '../../utils/object'
@@ -21,7 +21,7 @@ export const props = makePropsConfigurable(
2121
// --- Main component ---
2222

2323
// @vue/component
24-
export const BButtonGroup = /*#__PURE__*/ Vue.extend({
24+
export const BButtonGroup = /*#__PURE__*/ extend({
2525
name: NAME_BUTTON_GROUP,
2626
functional: true,
2727
props,

src/components/button-toolbar/button-toolbar.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Vue } from '../../vue'
1+
import { extend } from '../../vue'
22
import { NAME_BUTTON_TOOLBAR } from '../../constants/components'
33
import { PROP_TYPE_BOOLEAN } from '../../constants/props'
44
import { CODE_DOWN, CODE_LEFT, CODE_RIGHT, CODE_UP } from '../../constants/key-codes'
@@ -30,7 +30,7 @@ export const props = makePropsConfigurable(
3030
// --- Main component ---
3131

3232
// @vue/component
33-
export const BButtonToolbar = /*#__PURE__*/ Vue.extend({
33+
export const BButtonToolbar = /*#__PURE__*/ extend({
3434
name: NAME_BUTTON_TOOLBAR,
3535
mixins: [normalizeSlotMixin],
3636
props,

src/components/button-toolbar/button-toolbar.spec.js

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -108,42 +108,12 @@ describe('button-toolbar', () => {
108108
const $btns = wrapper.findAll('button')
109109
expect($btns).toBeDefined()
110110
expect($btns.length).toBe(6)
111-
expect(
112-
$btns
113-
.at(0)
114-
.find('button[tabindex="-1"')
115-
.exists()
116-
).toBe(true)
117-
expect(
118-
$btns
119-
.at(1)
120-
.find('button[tabindex="-1"')
121-
.exists()
122-
).toBe(true)
123-
expect(
124-
$btns
125-
.at(2)
126-
.find('button[tabindex="-1"')
127-
.exists()
128-
).toBe(false) // Disabled button
129-
expect(
130-
$btns
131-
.at(3)
132-
.find('button[tabindex="-1"')
133-
.exists()
134-
).toBe(true)
135-
expect(
136-
$btns
137-
.at(4)
138-
.find('button[tabindex="-1"')
139-
.exists()
140-
).toBe(true)
141-
expect(
142-
$btns
143-
.at(5)
144-
.find('button[tabindex="-1"')
145-
.exists()
146-
).toBe(true)
111+
expect($btns.at(0).element.matches('button[tabindex="-1"')).toBe(true)
112+
expect($btns.at(1).element.matches('button[tabindex="-1"')).toBe(true)
113+
expect($btns.at(2).element.matches('button[tabindex="-1"')).toBe(false) // Disabled button
114+
expect($btns.at(3).element.matches('button[tabindex="-1"')).toBe(true)
115+
expect($btns.at(4).element.matches('button[tabindex="-1"')).toBe(true)
116+
expect($btns.at(5).element.matches('button[tabindex="-1"')).toBe(true)
147117

148118
wrapper.destroy()
149119
})

0 commit comments

Comments
 (0)