美文网首页
组件测试及发布

组件测试及发布

作者: 翔子丶 | 来源:发表于2021-04-12 09:59 被阅读0次
单元测试

在组件开发完成并发布之前,需要对组件进行单元测试,单元测试是使用断言的方式判断实际的输出与预测的输出是否相同,目的是发现可能存在的问题;组件的单元测试是指使用单元测试工具对组件的各种状态及行为进行测试,确保组件发布后在使用过程中不会出现错误。

Vue组件的单元测试

  • 组件的单元测试有很多好处:

    • 提供描述组件行为的文档
    • 节省手动测试的时间
    • 减少研发新特性时产生的 bug
    • 改进设计
    • 促进重构
  • 用 Jest 测试单文件组件

    官方文档

    首先需要安装 Jest 和 Vue Test Utils

    yarn add jest @vue/test-utils -D -W
    

    然后需要在 package.json 中定义一个单元测试的脚本

    // package.json
    {
      "scripts": {
        "test": "jest" // 修改test为jest
      }
    }
    

    为了告诉 Jest 如何处理 *.vue 文件,需要安装和配置 vue-jest 预处理器:

    yarn add vue-jest -D -W
    

    创建jext.config.js配置文件

    module.exports = {
      "testMatch": ["**/__tests__/**/*.[jt]s?(x)"],
      "moduleFileExtensions": [
        "js",
        "json",
        // 告诉 Jest 处理 `*.vue` 文件
        "vue"
      ],
      "transform": {
        // 用 `vue-jest` 处理 `*.vue` 文件
        ".*\\.(vue)$": "vue-jest",
        // 用 `babel-jest` 处理 js
        ".*\\.(js)$": "babel-jest" 
      }
    }
    

    需要安装 babel-jest处理es6语法

    yarn add babel-jest -D -W
    

    babel配置文件

    // babel.config.js
    module.exports = {
      presets: [
        [
          '@babel/preset-env'
        ]
      ]
    }
    

    Babel 的桥接

    yarn add babel-core@bridge -D -W
    
  • Jest常用API

    中文文档

    • 全局函数

      describe(name, fn) 把相关测试组合在一起

      test(name, fn) 测试方法

      expect(value) 断言

    • 匹配器

      toBe(value) 判断值是否相等

      toEqual(obj) 判断对象是否相等

      toContain(value) 判断数组或字符串是否包含

    • 快照

      toMatchSnapshot()

  • vue-jest常用API

    中文文档

    • mount() 创建一个包含被挂载和渲染的Vue组件的Wrapper
    • Wrapper
      • vm wrapper包裹的组件实例
      • props() 返回Vue实例选项中的props对象
      • html() 组件生成的HTML标签
      • find() 通过选择器返回匹配的组件中的DOM元素
      • trigger() 触发DOM原生事件,自定义事件wrapper.vm.$emit()
      • ...
  • 创建packages/input/__tests__/input.test.js文件

    @vue/test-utils提供API用于挂载组件,Jest不需要导入因为测试文件是被jest加载执行的

    import input from '../src/input.vue'
    import { mount } from '@vue/test-utils'
    
    // 创建代码块 将input相关测试都添加到这里
    describe('wang-input', () => {
      test('input-text', () => {
        // 挂载组件 只是内存中的挂载 返回一个包裹器
        const wrapper = mount(input)
        // 测试生成的html中是否包含type=text
        expect(wrapper.html()).toContain('input type="text"')
      })
    })
    
    
  • 使用yarn test测试

    image-20210412082210659.png
  • 添加更多测试

    ...
    test('input-password', () => {
        const wrapper = mount(input, {
          propsData: {
            type: 'password',
          },
        })
        expect(wrapper.html()).toContain('input type="password"')
      })
    
      test('input-password', () => {
        const wrapper = mount(input, {
          propsData: {
            type: 'password',
            value: 'admin',
          },
        })
        expect(wrapper.props('value')).toBe('admin')
      })
    
      // 快照
      test('input-snapshot', () => {
        const wrapper = mount(input, {
          propsData: {
            type: 'password',
            value: 'admin',
          },
        })
        // 快照 第一次运行会将wrapper.vm.$el的内容存储在./__snapshots__/input.test.js.snap中
        expect(wrapper.vm.$el).toMatchSnapshot()
      })
    ...
    

    如果以后生成的快照和第一次生成的不同,会测试失败,如下所示:

    image-20210412082559674.png

可以通过yarn test -u删除旧的快照文件,并重新生成

Rollup打包
  • 特点

    • Rollup是一个模块打包器
    • Rollup支持Tree-shaking
    • 打包结果比webpack小
    • 开发框架/组件库使用Rollup更合适,如Vue、React等
  • 安装

    • Rollup
    • rollup-plugin-terser 对代码进行压缩
    • Rollup-plugin-vue@5.1.9 将单文件组件编译成js代码,最新版本适用于vue3.x,内部需要使用到vue-template-compiler
    • vue-template-compiler
  • 设置Rollup配置文件

    import { terser } from 'rollup-plugin-terser'
    import vue from 'rollup-plugin-vue'
    
    module.exports = [
      {
        input: 'index.js',
        output: [
          {
            file: 'dist/index.js',
            format: 'es'
          }
        ],
        plugins: [
          vue({
            // Dynamically inject css as a <style> tag
            css: true, 
            // Explicitly convert template to render function
            compileTemplate: true
          }),
          terser()
        ]
      }
    ]
    
  • 单独打包button组件

    在button组件中添加rollup.config.js

    配置package.json添加脚本

    "build": "rollup -c"
    

    使用yarn workspace执行所有包中的命令

    yarn workspace wang-button run build
    

    打包完成,可以看到dist中生成的js文件

    image-20210412083944432.png
  • 打包所有组件

    需要额外安装的插件

    @rollup/plugin-json 让rollup可以把json文件作为模块加载

    rollup-plugin-postcss

    @rollup/plugin-node-resolve 打包过程会将依赖的第三方包进行打包

    执行命令

    yarn add @rollup/plugin-json rollup-plugin-postcss @rollup/plugin-node-resolve -D -W
    
  • 项目根目录创建rollup.config.js

    import fs from 'fs'
    import path from 'path'
    import json from '@rollup/plugin-json'
    import vue from 'rollup-plugin-vue'
    import postcss from 'rollup-plugin-postcss'
    import { terser } from 'rollup-plugin-terser'
    import { nodeResolve } from '@rollup/plugin-node-resolve'
    
    const isDev = process.env.NODE_ENV !== 'production'
    
    // 公共插件配置
    const plugins = [
      vue({
        // Dynamically inject css as a <style> tag
        css: true,
        // Explicitly convert template to render function
        compileTemplate: true
      }),
      json(),
      nodeResolve(),
      postcss({
        // 把 css 插入到 style 中
        // inject: true,
        // 把 css 放到和js同一目录
        extract: true
      })
    ]
    
    // 如果不是开发环境,开启压缩
    isDev || plugins.push(terser())
    
    // packages 文件夹路径
    const root = path.resolve(__dirname, 'packages')
    
    module.exports = fs.readdirSync(root)
      // 过滤,只保留文件夹
      .filter(item => fs.statSync(path.resolve(root, item)).isDirectory())
      // 为每一个文件夹创建对应的配置
      .map(item => {
        const pkg = require(path.resolve(root, item, 'package.json'))
        return {
          input: path.resolve(root, item, 'index.js'),
          output: [
            {
              exports: 'auto',
              file: path.resolve(root, item, pkg.main),
              format: 'cjs'
            },
            {
              exports: 'auto',
              file: path.join(root, item, pkg.module),
              format: 'es'
            },
          ],
          plugins: plugins
        }
      })
    
  • 配置package.json添加build命令

  • 对每个packages中的package.json设置mainmodule,打包的出口,使用包的入口

    ...
    "main": "dist/cjs/index.js",
    "module": "dist/es/index.js",
    ...
    
  • 使用yarn build进行打包

    打包完成,可以看到在packages中每个组件都生成了cjs和es模块

    image-20210412084909815.png
  • 设置环境变量

    yarn add cross-env -D -W 
    

    配置package.json

    "build:prod": "cross-env NODE_ENV=production rollup -c",
    "build:dev": "cross-env NODE_ENV=development rollup -c"
    

    分别执行不同的打包模式,dev模式下是不会进行代码压缩的

  • 清理所有包中的node_modules和dist

    删除node_module直接使用lerna clean即可

    image-20210412085521460.png

删除dist需要使用第三方包rimraf

安装

yarn add rimraf -D -W

在每个组件的package.json中添加del命令

"del": "rimraf dist"

执行yarn workspaces run del

发布

使用yarn plop新增link组件

  • 发布之前需要先添加测试文件,测试组件所有状态和对外公布方法

    import { mount } from '@vue/test-utils'
    import link from '../src/link.vue'
    
    describe('Wang-Link', () => {
      test('link-disabled-underlined', () => {
        // 挂载组件 只是内存中的挂载 返回一个包裹器
        const wrapper = mount(link, {
          propsData: {
            disabled: true,
          },
        })
        expect(wrapper.html()).toContain('class="disabled underlined"')
      })
      test('link-disabled', () => {
        const wrapper = mount(link, {
          propsData: {
            disabled: true,
            underlined: true,
          },
        })
        expect(wrapper.html()).toContain('class="disabled"')
      })
      test('link-a', () => {
        const wrapper = mount(link, {
          propsData: {
            href: 'www.baidu.com',
          },
        })
        expect(wrapper.props('href')).toBe('www.baidu.com')
      })
      test('link-snapshot', () => {
        const wrapper = mount(link, {
          propsData: {
            href: 'www.baidu.com',
            disabled: true,
          },
        })
        // 快照 第一次运行会将wrapper.vm.$el的内容存储在./__snapshots__/link.test.js.snap中
        expect(wrapper.vm.$el).toMatchSnapshot()
      })
    })
    
  • 运行生成环境打包

  • 发布之前检查npm登陆状态

    npm whoami
    
  • 使用yarn lerna进行发布

    发布完成,打开npm

    image-20210412094537562.png

项目地址

相关文章

网友评论

      本文标题:组件测试及发布

      本文链接:https://www.haomeiwen.com/subject/spbtlltx.html