The article is divided into three parts, the project adopts VUe-CLI + Vue/CLI-plugin-e2E -cypress to explain

Vue-cli project generation + Basic configuration (albeit dumb-type 😅)

  • Generation project (official website dad)
npm install -g @vue/cli // You can get used to NPM with YARN
vue create hello-world Eslint + Prettier standard Does not support Prettier 😭
Copy the code
  • Modify the package.json file
"Start ": "vue-cli-service serve", // develop + test environment "serve": "vue-cli-service serve --mode test", // combine + backend small sister "dev": "Vue-cli-service build --mode dev", // Test environment deployment "build": "vue-cli-service build", // Online environment deploymentCopy the code
  • Adding a Configuration File
// Different environment configurations
touch .env.test
echo NODE_ENV = 'development' > .env.test
// webpack alias + webstorm /.. / this)
touch vue.config.js
const path = require('path')
module.exports = {
  configureWebpack: {
    plugins: []},chainWebpack: config= > {
    config.resolve.alias
      .set(The '@', path.join(__dirname, 'src'))
      .set('component', path.join(__dirname, 'src'.'components'))
      .set('config', path.join(__dirname, 'src'.'config'))
/ / webstorm configurationCommond +, output webpack custom profile node_modules / @ vue - cli/server/webpack config. Js + apply to command + B 🎇 🎇 🎇 🎇 🎇 🎇// Don't like lodash get because it doesn't look good in typescript
npm i '@babel/plugin-proposal-optional-chaining' -D
touch .babelrc
module.exports = {
  'presets': [
    '@vue/app'].'plugins': [
    '@babel/plugin-proposal-optional-chaining']}const a = { c: 1 }
console.log(a? .b)// Does not interrupt program execution is not comfortable to write
Copy the code
  • Let’s write a vue Loading plugin to play with 😢
import Vue from 'vue'
import Loading from './Loading' // How does Loading achieve free play
let instance
let ZIndex = 101

const LoadingBuilder = function (type) {
  return (options) = > {
    if (Vue.prototype.$isServer) return false
    options = options || {}

    let data = Object.assign({}, options, { type: type, ZIndex: ZIndex })

    instance = new Loading({
      data: data
    })
    instance.vm = instance.$mount()
    document.body.appendChild(instance.vm.$el)
    instance.dom = instance.vm.$el
    instance.vm.open()
    ZIndex = ZIndex + 1
    return instance.vm
  }
}
const LoadingComponent = {}
LoadingComponent.install = function (Vue, opts = {}) {
  const Loading = LoadingBuilder()
  Vue.$loading = Loading
  window.$loading = Loading
  Object.defineProperties(Vue.prototype, {
    loading: {
      get () {
        return Loading
      }
    },
    $loading: {
      get () {
        return Loading
      }
    }
  })
}
export default LoadingComponent
Copy the code

Cypress. IO Basic configuration

  • Install Cypress in an existing project
vue add @vue/e2e-cypress
Copy the code
  • catalogue

    The following is automatically generated

├ ─ ─ tests │ └ ─ ─ e2e │ ├ ─ ─ the plugins / / configure the test file where │ │ └ ─ ─ index. The js │ ├ ─ ─ the specs / / write test place │ │ └ ─ ─ test. The js │ └ ─ ─ the support / / │ ├─ commands.js │ ├─ index.jsCopy the code
  • Modify the package.json file
"Test ": "vue-cli-service test:e2e --mode dev", // "test:e2e": "Vue-cli-service test:e2e --headless --mode dev", // Run JenkinsCopy the code
  • Basic syntax (the official website must be more clear than ME, I this quick start)

    • Assertion syntax is the same as other testing frameworks (various assertion syntax is supported, including customization)
      expect([]).to.be.a('Array') // Determine the type
      expect(a.b).to.exist // Check whether the attribute exists
      expect(1).to.be.oneOf([1.2.3]) // Check if the value is one of them
      expect('testing').to.match(/^test/) // Regex matches.Copy the code
    • UI testing (feels similar to Python Selenium)
    describe('Test Login', () => {
        before(() ={}) // Start hook
        beforEach((a)= > {}) // The hook before each test starts
        it('login', () => {
            cy.visit('/') // Access the root directory cy.visit('http://localhost:3000')
            cy.url().should('include'.'/login') // assert that the URL contains login
            cy.get('.user-input')
                .type('Jack z')
                .should('have.value'.'Jack z') // find input.user-input and type Jack z assert that the input value is Jack z
            cy.get('.submit-button').click() // Get the.submit-button DOM and trigger the click event
            cy.get('#navbar').contains('about').should('have.class'.'is-active') // Get the navbar text content about and class is IS-active
            cy.wait(1000) / / wait for 1 s
            cy.pause() / / pause
            cy.server({method: ' '.header: {token: ' '}, ...}) + cy.router('method'.'url'.'config') // This network request cannot be debugger
            cy.request(method, url, config).then((a)= > {}) // This can be debugger
            cy.contains().find().eq().each() // Use the DOM as JQuery to make UI judgments.// Support animation tests
        })
        after((a)= > {})
        afterEach((a)= >{})}...Copy the code
    • Custom commands
    // Customize setLocalStorage
    Cypress.Commands.add('setLocalStorage', (key, value) => { window.localStorage.setItem(key, value)
    cy.setLocalStorage('a'.JSON.strigify('Jack z'))
    Copy the code

Gitlab Webhook + Jenkins + jenkinsFile basic configuration

  • Jenkinsfile configuration
// touch Jenkinsfile pipeline {agent {docker {image 'cypress/base:10' // Args '-u root:root' // Permission configuration otherwise NPM install fail~~~~}} environment {CHROME_BIN = '/bin/ Google -chrome' // Global configuration of environment variables} // Pipe Steps {sh 'rm -rf node_modules' sh 'NPM install' sh' NPM rebuild Node-sass '}} stage(' Run test ') {pipe steps {sh 'NPM run test:e2e'}}} POST {always {junit {def MSG = "[${author}]" results/cypress-report.xml // error message configuration file for CI not to pass // def imageUrl = "https://www.iconsdb.com/icons/preview/red/x-mark-3-xxl.png" if (currentBuild.currentResult=="SUCCESS"){ ImageUrl = "http://icons.iconarchive.com/icons/paomedia/small-n-flat/1024/sign-check-icon.png" MSG = "${an} 】 【 launch successful, Good job!" } dingTalk accessToken:"xxxx",message:"${msg}",imageUrl:"${imageUrl}",messageUrl:"${BUILD_URL}" } } } }Copy the code
  • Create a docker Jenkins

    • Jenkins initialization
docker run --name devops-jenkins --user=root -p 8080:8080 -p 50000:50000 -v /opt/data/jenkins_home:/var/jenkins_home -d jenkins/jenkins:lts docker run --name devops-registry -p 5000:5000 -v /opt/devdata/registry:/var/lib/registry -d After Jenkins is started by registry, enter http://host IP of Jenkins deployment through the browser: how to view the login password on the home page after the portCopy the code

After entering the administrator account, click “Continue as Admin” to enter the admin interface and click “System Administration – Plug-in Management” to install Node

Node Version Management

Upload files after packing

. Click on whatever is missing

  • Create two missions

    1. A running test (this can include a second personal preference)

    Building task

    Code position

    Jenkins Webhook configuration (need to install Gitlab Webhook plugin and GitHub webhook is not different, but Jenkins is still quite large need I add) red line useful copy

    Pipeline configuration

    2, a run deployment

    Building task

    Code position

    Execute when a task is finished (need to install plug-ins)

    Configure packaging and transferring files

  • Gitlab configuration

    Gitlab Webhook configuration arrow fill in the circle above 👆

Finally, write wrong place, welcome big guy to correct