Skip to content

Commit

Permalink
Merge pull request #6905 from bootstrap-vue/vue3-compat-build
Browse files Browse the repository at this point in the history
feat(compat): add Vue 3 support via @vue/compat
  • Loading branch information
xanf committed Oct 25, 2022
2 parents debe660 + 6ef2ba4 commit 58516a4
Show file tree
Hide file tree
Showing 222 changed files with 1,761 additions and 1,097 deletions.
3 changes: 0 additions & 3 deletions .eslintrc.js
Expand Up @@ -15,9 +15,6 @@ module.exports = {
es6: true,
'jest/globals': true
},
globals: {
Vue: true
},
rules: {
'no-unused-vars': [
'error',
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/test.yml
Expand Up @@ -125,8 +125,19 @@ jobs:
- name: Test unit
run: yarn run test:unit --coverage --maxWorkers=2

- name: Test unit (Vue 3)
run: yarn run test:unit --coverage --maxWorkers=2
env:
USE_VUE3: '1'

- name: Merge coverage
run:
npx istanbul-merge --out ./coverage-final.json coverage/coverage-final.json
coverage-vue3/coverage-final.json

- name: CodeCov
uses: codecov/codecov-action@v3.1.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unittests
files: ./coverage-final.json
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,6 +4,7 @@
.vercel/
.vscode/
coverage/
coverage-vue3/
dist/
docs-dist/
esm/
Expand Down
16 changes: 13 additions & 3 deletions jest.config.js
@@ -1,11 +1,21 @@
const useVue3 = 'USE_VUE3' in process.env

const moduleNameMapper = useVue3
? {
'^vue$': '@vue/compat',
'^@vue/test-utils$': '@vue/test-utils-vue3'
}
: {}

module.exports = {
testRegex: 'spec.js$',
moduleFileExtensions: ['js', 'vue'],
moduleNameMapper,
transform: {
'^.+\\.js$': 'babel-jest',
'.*\\.(vue)$': 'vue-jest'
'^.+\\.js$': 'babel-jest'
},
coverageDirectory: './coverage/',
transformIgnorePatterns: ['/node_modules(?![\\\\/]vue-test-utils-compat[\\\\/])'],
coverageDirectory: useVue3 ? './coverage-vue3' : './coverage/',
testEnvironmentOptions: {
pretendToBeVisual: true
},
Expand Down
11 changes: 7 additions & 4 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "bootstrap-vue",
"version": "2.22.0",
"version": "2.23.0",
"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.",
"main": "./dist/bootstrap-vue.common.js",
"web": "./dist/bootstrap-vue.js",
Expand Down Expand Up @@ -66,7 +66,7 @@
"docs-gen": "cross-env NODE_ENV=docs nuxt generate -c docs/nuxt.config.js",
"lint": "eslint --ext .js,.md,.vue ./",
"postinstall": "opencollective || exit 0",
"prepare": "husky install",
"prepare": "husky install && yarn run build",
"prettify": "prettier --write '**/*.{js,json,md,scss,ts,vue}'",
"release": "yarn run prettify && yarn run test && yarn run build && yarn run release-notes && standard-version",
"release-notes": "jiti ./scripts/release-notes",
Expand Down Expand Up @@ -99,7 +99,10 @@
"@nuxtjs/robots": "^2.5.0",
"@nuxtjs/sitemap": "^2.4.0",
"@testing-library/jest-dom": "^5.12.0",
"@vue/compat": "^3.2.40",
"@vue/compiler-dom": "^3.2.40",
"@vue/test-utils": "^1.3.0",
"@vue/test-utils-vue3": "npm:@vue/test-utils@2.2.0",
"autoprefixer": "^10.4.0",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^10.1.0",
Expand Down Expand Up @@ -148,10 +151,10 @@
"standard-version": "^9.3.0",
"terser": "^5.15.0",
"vue": "^2.6.12",
"vue-jest": "^3.0.7",
"vue-router": "^3.5.1",
"vue-server-renderer": "^2.6.12",
"vue-template-compiler": "^2.6.12"
"vue-template-compiler": "^2.6.12",
"vue-test-utils-compat": "0.0.6"
},
"keywords": [
"Bootstrap",
Expand Down
6 changes: 3 additions & 3 deletions src/components/alert/alert.js
@@ -1,4 +1,3 @@
import { COMPONENT_UID_KEY, Vue } from '../../vue'
import { NAME_ALERT } from '../../constants/components'
import { EVENT_NAME_DISMISSED, EVENT_NAME_DISMISS_COUNT_DOWN } from '../../constants/events'
import {
Expand All @@ -7,13 +6,14 @@ import {
PROP_TYPE_STRING
} from '../../constants/props'
import { SLOT_NAME_DISMISS } from '../../constants/slots'
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
import { requestAF } from '../../utils/dom'
import { isBoolean, isNumeric } from '../../utils/inspect'
import { makeModelMixin } from '../../utils/model'
import { toInteger } from '../../utils/number'
import { sortKeys } from '../../utils/object'
import { makeProp, makePropsConfigurable } from '../../utils/props'
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
import { COMPONENT_UID_KEY, extend } from '../../vue'
import { BButtonClose } from '../button/button-close'
import { BVTransition } from '../transition/bv-transition'

Expand Down Expand Up @@ -68,7 +68,7 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BAlert = /*#__PURE__*/ Vue.extend({
export const BAlert = /*#__PURE__*/ extend({
name: NAME_ALERT,
mixins: [modelMixin, normalizeSlotMixin],
props,
Expand Down
4 changes: 2 additions & 2 deletions src/components/aspect/aspect.js
@@ -1,4 +1,4 @@
import { Vue } from '../../vue'
import { extend } from '../../vue'
import { NAME_ASPECT } from '../../constants/components'
import { PROP_TYPE_NUMBER_STRING, PROP_TYPE_STRING } from '../../constants/props'
import { RX_ASPECT, RX_ASPECT_SEPARATOR } from '../../constants/regex'
Expand Down Expand Up @@ -26,7 +26,7 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BAspect = /*#__PURE__*/ Vue.extend({
export const BAspect = /*#__PURE__*/ extend({
name: NAME_ASPECT,
mixins: [normalizeSlotMixin],
props,
Expand Down
8 changes: 4 additions & 4 deletions src/components/avatar/avatar-group.js
@@ -1,15 +1,15 @@
import { Vue } from '../../vue'
import { NAME_AVATAR_GROUP } from '../../constants/components'
import {
PROP_TYPE_BOOLEAN,
PROP_TYPE_BOOLEAN_STRING,
PROP_TYPE_NUMBER_STRING,
PROP_TYPE_STRING
} from '../../constants/props'
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
import { mathMax, mathMin } from '../../utils/math'
import { toFloat } from '../../utils/number'
import { makeProp, makePropsConfigurable } from '../../utils/props'
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
import { extend } from '../../vue'
import { computeSize } from './avatar'

// --- Props ---
Expand All @@ -33,11 +33,11 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BAvatarGroup = /*#__PURE__*/ Vue.extend({
export const BAvatarGroup = /*#__PURE__*/ extend({
name: NAME_AVATAR_GROUP,
mixins: [normalizeSlotMixin],
provide() {
return { bvAvatarGroup: this }
return { getBvAvatarGroup: () => this }
},
props,
computed: {
Expand Down
9 changes: 6 additions & 3 deletions src/components/avatar/avatar.js
@@ -1,4 +1,4 @@
import { Vue } from '../../vue'
import { extend } from '../../vue'
import { NAME_AVATAR } from '../../constants/components'
import { EVENT_NAME_CLICK, EVENT_NAME_IMG_ERROR } from '../../constants/events'
import {
Expand Down Expand Up @@ -67,11 +67,11 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BAvatar = /*#__PURE__*/ Vue.extend({
export const BAvatar = /*#__PURE__*/ extend({
name: NAME_AVATAR,
mixins: [normalizeSlotMixin],
inject: {
bvAvatarGroup: { default: null }
getBvAvatarGroup: { default: () => () => null }
},
props,
data() {
Expand All @@ -80,6 +80,9 @@ export const BAvatar = /*#__PURE__*/ Vue.extend({
}
},
computed: {
bvAvatarGroup() {
return this.getBvAvatarGroup()
},
computedSize() {
// Always use the avatar group size
const { bvAvatarGroup } = this
Expand Down
12 changes: 6 additions & 6 deletions src/components/avatar/avatar.spec.js
Expand Up @@ -250,7 +250,7 @@ describe('avatar', () => {
const wrapper1 = mount(BAvatar, {
provide: {
// Emulate `undefined`/`null` props
bvAvatarGroup: {}
getBvAvatarGroup: () => ({})
}
})

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

const wrapper2 = mount(BAvatar, {
provide: {
bvAvatarGroup: {
getBvAvatarGroup: () => ({
variant: 'danger'
}
})
}
})

Expand All @@ -289,7 +289,7 @@ describe('avatar', () => {
},
provide: {
// Emulate `undefined`/`null` props
bvAvatarGroup: {}
getBvAvatarGroup: () => ({})
}
})

Expand All @@ -307,9 +307,9 @@ describe('avatar', () => {
size: '2em'
},
provide: {
bvAvatarGroup: {
getBvAvatarGroup: () => ({
size: '5em'
}
})
}
})

Expand Down
4 changes: 2 additions & 2 deletions src/components/badge/badge.js
@@ -1,4 +1,4 @@
import { Vue, mergeData } from '../../vue'
import { extend, mergeData } from '../../vue'
import { NAME_BADGE } from '../../constants/components'
import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props'
import { omit, sortKeys } from '../../utils/object'
Expand All @@ -25,7 +25,7 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BBadge = /*#__PURE__*/ Vue.extend({
export const BBadge = /*#__PURE__*/ extend({
name: NAME_BADGE,
functional: true,
props,
Expand Down
4 changes: 2 additions & 2 deletions src/components/breadcrumb/breadcrumb-item.js
@@ -1,4 +1,4 @@
import { Vue, mergeData } from '../../vue'
import { extend, mergeData } from '../../vue'
import { NAME_BREADCRUMB_ITEM } from '../../constants/components'
import { makePropsConfigurable } from '../../utils/props'
import { BBreadcrumbLink, props as BBreadcrumbLinkProps } from './breadcrumb-link'
Expand All @@ -10,7 +10,7 @@ export const props = makePropsConfigurable(BBreadcrumbLinkProps, NAME_BREADCRUMB
// --- Main component ---

// @vue/component
export const BBreadcrumbItem = /*#__PURE__*/ Vue.extend({
export const BBreadcrumbItem = /*#__PURE__*/ extend({
name: NAME_BREADCRUMB_ITEM,
functional: true,
props,
Expand Down
4 changes: 2 additions & 2 deletions src/components/breadcrumb/breadcrumb-link.js
@@ -1,4 +1,4 @@
import { Vue, mergeData } from '../../vue'
import { extend, mergeData } from '../../vue'
import { NAME_BREADCRUMB_LINK } from '../../constants/components'
import { PROP_TYPE_STRING } from '../../constants/props'
import { htmlOrText } from '../../utils/html'
Expand All @@ -21,7 +21,7 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BBreadcrumbLink = /*#__PURE__*/ Vue.extend({
export const BBreadcrumbLink = /*#__PURE__*/ extend({
name: NAME_BREADCRUMB_LINK,
functional: true,
props,
Expand Down
4 changes: 2 additions & 2 deletions src/components/breadcrumb/breadcrumb.js
@@ -1,4 +1,4 @@
import { Vue, mergeData } from '../../vue'
import { extend, mergeData } from '../../vue'
import { NAME_BREADCRUMB } from '../../constants/components'
import { PROP_TYPE_ARRAY } from '../../constants/props'
import { isArray, isObject } from '../../utils/inspect'
Expand All @@ -18,7 +18,7 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BBreadcrumb = /*#__PURE__*/ Vue.extend({
export const BBreadcrumb = /*#__PURE__*/ extend({
name: NAME_BREADCRUMB,
functional: true,
props,
Expand Down
4 changes: 2 additions & 2 deletions src/components/button-group/button-group.js
@@ -1,4 +1,4 @@
import { Vue, mergeData } from '../../vue'
import { extend, mergeData } from '../../vue'
import { NAME_BUTTON_GROUP } from '../../constants/components'
import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props'
import { pick, sortKeys } from '../../utils/object'
Expand All @@ -21,7 +21,7 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BButtonGroup = /*#__PURE__*/ Vue.extend({
export const BButtonGroup = /*#__PURE__*/ extend({
name: NAME_BUTTON_GROUP,
functional: true,
props,
Expand Down
4 changes: 2 additions & 2 deletions src/components/button-toolbar/button-toolbar.js
@@ -1,4 +1,4 @@
import { Vue } from '../../vue'
import { extend } from '../../vue'
import { NAME_BUTTON_TOOLBAR } from '../../constants/components'
import { PROP_TYPE_BOOLEAN } from '../../constants/props'
import { CODE_DOWN, CODE_LEFT, CODE_RIGHT, CODE_UP } from '../../constants/key-codes'
Expand Down Expand Up @@ -30,7 +30,7 @@ export const props = makePropsConfigurable(
// --- Main component ---

// @vue/component
export const BButtonToolbar = /*#__PURE__*/ Vue.extend({
export const BButtonToolbar = /*#__PURE__*/ extend({
name: NAME_BUTTON_TOOLBAR,
mixins: [normalizeSlotMixin],
props,
Expand Down
42 changes: 6 additions & 36 deletions src/components/button-toolbar/button-toolbar.spec.js
Expand Up @@ -108,42 +108,12 @@ describe('button-toolbar', () => {
const $btns = wrapper.findAll('button')
expect($btns).toBeDefined()
expect($btns.length).toBe(6)
expect(
$btns
.at(0)
.find('button[tabindex="-1"')
.exists()
).toBe(true)
expect(
$btns
.at(1)
.find('button[tabindex="-1"')
.exists()
).toBe(true)
expect(
$btns
.at(2)
.find('button[tabindex="-1"')
.exists()
).toBe(false) // Disabled button
expect(
$btns
.at(3)
.find('button[tabindex="-1"')
.exists()
).toBe(true)
expect(
$btns
.at(4)
.find('button[tabindex="-1"')
.exists()
).toBe(true)
expect(
$btns
.at(5)
.find('button[tabindex="-1"')
.exists()
).toBe(true)
expect($btns.at(0).element.matches('button[tabindex="-1"')).toBe(true)
expect($btns.at(1).element.matches('button[tabindex="-1"')).toBe(true)
expect($btns.at(2).element.matches('button[tabindex="-1"')).toBe(false) // Disabled button
expect($btns.at(3).element.matches('button[tabindex="-1"')).toBe(true)
expect($btns.at(4).element.matches('button[tabindex="-1"')).toBe(true)
expect($btns.at(5).element.matches('button[tabindex="-1"')).toBe(true)

wrapper.destroy()
})
Expand Down

0 comments on commit 58516a4

Please sign in to comment.