javascript - 使用 bootstrap-vue 运行 jest 时出现问题

标签 javascript vue.js jestjs bootstrap-vue vue-test-utils

我正在尝试使用 jest 和 bootstrap-vue 进行单元测试,但 Bootstrap-vue 标签上出现错误,例如:

  • [Vue warn]:未知的自定义元素:b-navbar - 您是否注册了 组件正确吗?...
  • [Vue warn]:未知的自定义元素: b-navbar-nav - 您是否正确注册了组件? …
  • [Vue warn]:未知的自定义元素:b-button - 您是否注册了 组件正确吗? ...

请在下面找到可以帮助您解决我的问题的源代码...;-) 谢谢

<小时/>

//Package.json

{
  "name": "theappname",
  "version": "1.0.0",
  "repository": {
    "type": "git",
    "url": ""
  },
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server --open",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --progress",
    "staging": "cross-env NODE_ENV=staging webpack",
    "build": "cross-env NODE_ENV=production webpack",
    "test": "jest",
    "test:debug": "node --inspect node_modules/.bin/jest --runInBand",
    "test:debugw": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand"
  },
  "dependencies": {
    "@fortawesome/fontawesome-free": "^5.11.2",
    "babel-jest": "^24.9.0",
    "bootstrap": "^4.3.1",
    "bootstrap-vue": "^2.0.2",
    "file-loader": "^4.2.0",
    "jquery": "^1.9.1",
    "postcss-loader": "^3.0.0",
    "style-loader": "^1.0.0",
    "url-loader": "^2.1.0",
    "vee-validate": "^2.2.8",
    "vue": "^2.6.10",
    "vue-router": "^3.1.3",
    "vuex": "^3.1.1"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/preset-env": "^7.6.2",
    "@vue/test-utils": "^1.0.0-beta.29",
    "babel-core": "^7.0.0-bridge.0",
    "babel-loader": "^8.0.6",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-stage-2": "^6.24.1",
    "babel-preset-vue": "^2.0.2",
    "css-loader": "^3.2.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "jest": "^24.9.0",
    "jest-serializer-vue": "^2.0.2",
    "jest-transform-stub": "^2.0.0",
    "node-sass": "^4.12.0",
    "path": "^0.12.7",
    "sass": "^1.22.12",
    "sass-loader": "^8.0.0",
    "vue-jest": "^3.0.5",
    "vue-loader": "^15.7.1",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.41.0",
    "webpack-cli": "^3.3.9",
    "webpack-dev-server": "^3.8.1"
  },
  "jest": {
    "moduleFileExtensions": [
      "jsx",
      "js",
      "json",
      "vue"
    ],
    "moduleNameMapper": {
      "^@/(.*)$": "<rootDir>/src/$1"
    },
    "transform": {
      "^.+\\.vue$": "vue-jest",
      ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
      "^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest"
    },
    "snapshotSerializers": [
      "<rootDir>/node_modules/jest-serializer-vue"
    ],
    "testPathIgnorePatterns": [
      "<rootDir>/node_modules"
    ],
    "testMatch": [
      "**/test/unit/**/*.spec.(js|jsx|ts|tsx)|**/test/*.(js|jsx|ts|tsx)"
    ]
  }
}
<小时/>

`//Webpack.config.js

var path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    mode: 'development',
    resolve: {
        extensions: ['.js', '.vue']
    },
    module: {
        rules: [
            {
              test: /\.html$/,
              use: [
                {
                  loader: "html-loader"
                }
              ]
            },
            {
                test: /\.vue?$/,
                exclude: /(node_modules)/,
                use: 'vue-loader'
            },
            {
                test: /\.js?$/,
                exclude: /(node_modules)/,
                use: 'babel-loader'
            },
            {
                test: /\.(png|jpg|gif|svg)$/,
                loader: 'file-loader',
                options: {
                  name: '[name].[ext]?[hash]',
                  outputPath: './public',
                }
            },
            {
                test: /\.css$/,
                loader:  ['style-loader', 'css-loader']
            },
            {
                test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    mimetype: 'application/font-woff',
                    fallback: 'file-loader'
                }
            }, {
                test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    mimetype: 'application/octet-stream',
                    fallback: 'file-loader'
                }
            }, {
                test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'file-loader'
            }, {
                test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader',
                options: {
                    limit: 10000,
                    mimetype: 'application/image/svg+xml',
                    fallback: 'file-loader'
                }
            },{
                // Apply rule for .sass or .scss files
                test: /\.(sa|sc)ss$/i,
                use: [
                  // Creates `style` nodes from JS strings
                  'style-loader',
                  // Translates CSS into CommonJS
                  'css-loader',
                  // Compiles Sass to CSS
                  'sass-loader',
                ]
            }
        ]
    },
    entry: {
      index: './src/index.js'//,
      //adminApp: './src/index.js'
    },
    output: {
      path: path.resolve(__dirname, './dist'),
      publicPath: '/',
      filename: 'build.js'
    },
    plugins: [new HtmlWebpackPlugin({
        favicon: './src/public/favicon.png',
        template: './src/index.html',
        filename: "./index.html"/*,
        publicPath: '/public/'*/
    })],
    devServer: {
        historyApiFallback: true,
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 9000
    },
    externals: {
        // global app config object
        config: JSON.stringify({
            apiUrl: 'http://localhost:3001/api/v1'
        })
    }
}
<小时/>
//components.Navbar.spec.js
import BootstrapVue, { BNavbar, BNavbarBrand } from 'bootstrap-vue';
import Vuex from 'vuex'
import Router from 'vue-router';
import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
import Navbar from '@/components/Navbar';

const localVue = createLocalVue();
localVue.use(Vuex);
localVue.use(Router);
debugger;
localVue.use(BootstrapVue/*,{
  components: {
        BNavbar: true,
        BNavbarBrand: true
      }
}*/);

const router = new Router();

const mockActions = {
  // fetchSomething: sinon.stub()
};
const store = new Vuex.Store({
  state: {
    account: {
      status: {
        loggedIn: false
      }
    }
  }
});

describe('Navbar.vue', () => {
  let wrapper;

  beforeEach(()=>{
    wrapper = shallowMount(Navbar, {
      localVue,
      store,
      router/*,
      stubs: {
              "b-navbar": BNavbar,
              "b-navbar-brand": BNavbarBrand
            }*/
    });
  });

  it("renders a vue instance", () => {
    const wrapper = shallowMount(Navbar, {
      computed: {
        isConnected: (state) => {
          if (state.account && state.account.status && state.account.status.loggedIn){
            return true;
          }
          return false;
        }
      },
      mocks: {
        $store: {
          state: { account: { status: { loggedIn: false } } }
        }
      }
    })
    expect(wrapper.isVueInstance()).toBe(true);
  });
})
<小时/>
//Navbar.vue
<template>
  <div>
    <b-navbar toggleable="lg">
      <b-navbar-brand href="/"><img src="../assets/logo_250.png">theappname</b-navbar-brand>
      <b-navbar-toggle target="nav-collapse"></b-navbar-toggle>

      <b-collapse id="nav-collapse" is-nav>
        <b-navbar-nav>
          <b-nav-item href="#">bla bla</b-nav-item>
          <b-nav-item href="#">bla bla</b-nav-item>
        </b-navbar-nav>

        <!-- Right aligned nav items -->
        <b-navbar-nav  v-if="isConnected" class="ml-auto">
         …        
        <b-navbar-nav class="ml-auto" v-else>
          ….        
        </b-navbar-nav>
      </b-collapse>
    </b-navbar>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex'

export default {
    data() {
        return {
            item: ''
        }
    },
    computed: {
        ...mapState({
            account: state => state.account
        }),

        isConnected: function () {
          if (this.account && this.account.status && this.account.status.loggedIn){
            return true;
          }
          return false;
        }
    },

    methods: {
      ...mapActions('account', ['logout']),
  }
}

最佳答案

我找到了解决方案,事实上问题不在这些文件中而是在.babelrc中

关于javascript - 使用 bootstrap-vue 运行 jest 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58183121/

相关文章:

javascript - @vue-composition/如何在 setup() 中使用异步方法

reactjs - 测试 React 组件方法正在调用函数 pass 作为 prop

unit-testing - 如何在每个测试中以不同的方式模拟克隆的导入依赖项

vue.js - Vue 客户端 : Cannot find module '../package.json' error after npm install

node.js - 用 Electron 而不是 Node 运行 Jest

java - 检查变量是否为真

php - 对实时应用程序使用持续的 ajax 请求会给服务器/数据库带来压力吗?

c# - __doPostBack 未在 JavaScript 中定义

javascript - 函数无法访问其他函数创建的变量(闭包)

methods - 在 vueJs 的计算属性中使用方法