顯示具有 Cypress 標籤的文章。 顯示所有文章
顯示具有 Cypress 標籤的文章。 顯示所有文章

2023年3月11日 星期六

原始碼解析 create-vue 快速建立 Vue 專案


Vue 可以透過下面的指令,接著詢問一系列的問題,按照設定快速初始一個專案。(目前版本為 3.6.1)

npm init vue@latest

實際是執行這個 create-vue,想透過原始碼的解析,來了解怎麼樣做一個類似的功能,這個專案架構是如何、如何達成建立專案的功能。


1. playground

運用 git submodules的功能,主要是將各種條件下的樣板做snapshot,形成另一個 create-vue-templates 專案。


2. scripts

顧名思義分別對應到 package.json 的 scripts 所執行的檔案名。

  • build
  • prepublish
  • snapshot
  • test

3. template

將程式碼依照性質分成不同的目錄,根據使用者的設定將對應的檔案複製或合成等,形成 Vue 的專案。

  • base: 基本必備的程式碼,主要套件為 vue, vite
  • code: HelloWorld.vue 元件以及 vue-router 範例程式碼,會分成有無使用 ts 版本。
  • config: 裡面每個目錄依照套件名稱命名,目錄包含:cypress-ct, cypress, jsx, pinia, playwright, router, typescript, vitest,目錄裡是安裝套件的設定檔。主要會有 package.json 設定安裝那些套件,後續會將內容與現有設定合併,再來以 cypress 為例,會有 cypress.config.jscypress.config.ts,屆時會根據是否有用 ts 來複製對應的檔案。
  • entry: 指的是 vite 打包的 entry main.js,執行 createApp 的功能,總共有預設, pinia, router, pinia+router 這四種版本。
  • eslint
  • tsconfig

4. utils

目錄及檔案合併等方法都在這個目錄裡,檔名命名已經相當清楚。


5. index

主要邏輯在這個檔案

  • 讀 argv 指令
  • 使用 prompts 詢問一連串問題
  • 依照專案名稱等,產生 package.json
  • 複製 base
  • 複製 config
  • 複製 tsconfig
  • 產生 eslint
  • 複製 entry
  • 清除 js or ts 多餘的檔案或重新命名
  • 產生 README.md
  • 專案已完成,顯示指令提示

拆解過後,我覺得最重要的是如何整理出 template/,讓不同的安裝需求可以拆解出來,有秩序地組成這個初始的專案。


2022年9月28日 星期三

[E2E Testing] 如何從 cypress 9 升級 10

使用 cypress 進行 E2e Testing,針對比較常用的部分整理從 Cypress 9 升級到 10 一些異動,最大的差別是不再支援 cypress.json,並移除了 plugins 目錄。


安裝 cypress 10

npm install --save-dev cypress@10

如何升級至 cypress 10

主要針對 e2e 調整的部分進行說明,啟動 cypress 時,原本會讀取根目錄建立 cypress.json的設定,cypress 10不再支援。檔案格式可以支援 js/ts,底下範例以cypress.config.js為主,另外參數的設定也做出調整:

baseUrl

從設定在最上層,改成專屬 e2e 測試的設定,若只做 component testing 就不需要設定這個參數,讓 e2e / component testing 的設定更一目瞭然。

Before cypress.json
{
  'baseUrl': 'http://localhost:1234'
}
After cypress.config.js
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:1234'
  }
});

pluginsFile

這個設定不需要,直接移除即可。

Before cypress.json
{
  'pluginsFile': 'cypress/plugins/index.js'
}

setupNodeEvents

移除 pluginsFile 的設定後,原本的內容也直接移到 cypress.config.js 進行設定,過去版本9若同時使用 component / e2e testing,可以將設定直接分開來寫。

Before cypress/plugins/index.js
module.exports = (on, config) => {
  if (config.testingType === 'component') {
    // component testing dev server setup code
    // component testing node events setup code
  } else {
    // e2e testing node events setup code
  }
};
After cypress.config.js
const { defineConfig } = require('cypress');

module.exports = defineConfig({
  component: {
    devServer(cypressConfig) {
      // component testing dev server setup code
    },
    setupNodeEvents(on, config) {
      // component testing node events setup code
    },
  },
  e2e: {
    setupNodeEvents(on, config) {
      // e2e testing node events setup code
    },
  },
});

完整內容請參考官網升級指引


相關文章:


2022年2月22日 星期二

Cypress+Vue 元件測試 (component testing)

接續「e2e 測試工具 Cypress 安裝及介紹」,除了用在實際開啟瀏覽器的測試,cypress也支援元件測試,需要安裝相關的套件將元件render出來。


安裝
npm install --save-dev cypress @cypress/vue @cypress/webpack-dev-server webpack-dev-server

如果是 Vue3 ,請記得把 @cypress/vue 換成:

npm install --save-dev @cypress/vue@next


設定

先到 cypress/plugins/index.js 的註冊 dev-server:start 事件,再來要注意 require('@vue/cli-service/webpack.config.js')這段,你的專案不見得有安裝這個套件,你可以建立自己的webpack設定,並替換上正確的路徑。

// cypress/plugins/index.js

const { startDevServer } = require('@cypress/webpack-dev-server');
// Vue's Webpack configuration
const webpackConfig = require('@vue/cli-service/webpack.config.js');

module.exports = (on, config) => {
  on('dev-server:start', options =>
    startDevServer({ options, webpackConfig });
  );
};

若我們要測試的元件內容為:

<!-- Button.vue -->
<template>
  <button>
    <slot />
  </button>
</template>

在測試時,vue2和vue3引入 mount 的寫法相同,並且將設定元件所需的輸入

import {mount} from '@cypress/vue'
import Button from './Button.vue';

it('Button', () => {
  mount(Button, {
    slots: {
      default: 'Test button',
    },
  });

  cy.get('button').contains('Test button').click();
});


執行

提供 GUI 介面操作

npx cypress open-ct

無GUI,在 Terminal 上執行

npx cypress run-ct


參考文件: https://docs.cypress.io/guides/component-testing/introduction


2022年1月31日 星期一

e2e 測試工具 Cypress 安裝及介紹


e2e測試(End-to-End testing)是模擬使用者的行為,實際打開瀏覽器操作頁面的測試方式,因此不限於vue, react的專案,e2e的測試可以反映出頁面在不同瀏覽器的執行情形。

Cypress便是其中一個常見工具,Cypress在安裝上簡單,語法採用 mocha 的句法、chai 的斷詞(expect, should, assert),撰寫的方式跟 unit test 相似。


安裝

進到想要測試的專案目錄內,使用 npm 安裝。(官網說明)

npm install cypress --save-dev

接著在目錄裡,建立先建立一個 cypress.json,內容放一個空物件,此時你可以直接執行下面的命令(官網說明):

npx cypress open

會發現多了一個 cypress/ 的資料夾,裡面有四個目錄:

  • integration: 主要的測試檔案
  • fixtures: 固定的資料
  • plugins: 主要有 on 定義全局的不同時間點的執行工作,以及 config 提供全局使用的參數,如常用的 env
  • support: 可提供自定義的指令、或引入擴充的指令,供撰寫測試檔案使用


Cypress.json 與環境變數(.env)

使用 cypress 都必須在專案的根目錄裡新增 cypress.json,如果直接放 {} 空物件,代表直接使用預設值。

下面是我的設定,從字面上不難理解設定的內容,第一個testFiles是測試的檔案名稱,接著各個目錄的路徑,video是 Boolean 決定是否錄製測試過程的影片,screenshotOnRunFailure也是 Boolean 是否在執行失敗時擷取畫面。

{
    "testFiles": "**/*.spec.js",
    "integrationFolder": "resources/cypress/integration",
    "componentFolder": "resources/cypress/components",
    "fixturesFolder": "resources/cypress/fixtures",
    "pluginsFile": "resources/cypress/plugins",
    "supportFile": "resources/cypress/support",
    "video": false,
    "screenshotOnRunFailure": false
}

除了cypress基本的設定,常常也需要讀取環境設定檔(.env),假設內容如下(官方說明):

APP_URL=https://chenuin.github.io/
USER_NAME=chenuin

plugins/index.js可以設定:

// plugins/index.js

require('dotenv').config();

module.exports = (on, config) => {
    config.baseUrl = process.env.APP_URL;

    config.env.USER_NAME = process.env.USER_NAME;

    return config;
}
測試檔案需要使用時,可以直接呼叫:
Cypress.config('baseUrl')
Cypress.env('USER_NAME')

打開GUI,點選上方的 Settings 可以看到設定的結果,上面的顏色可以區分目前的設定是讀取哪裡,像是 baseUrl 是紫色的 plugin,

因此,可以知道下面兩種寫法都可以達到相同的效果:

// plugins/index.js
config.baseUrl = process.env.APP_URL;


// cypress.json
{
    "baseUrl": "https://chenuin.github.io/"
}


執行

提供 GUI 介面操作

npx cypress open

無GUI,在 Terminal 上執行

npx cypress run


訪問頁面 visit

測試的第一步常常是先進入某一個頁面,通常專案內都在相同的Domain下,如果有設定 baseUrl,Cypress會直接將設定作為前綴,導到相應的頁面,在寫法上簡潔許多。

// https://chenuin.github.io/webpack/2021/08/08/webpack5-getting-started.html

cy.visit('/webpack/2021/08/08/webpack5-getting-started.html')

若未設定,需要傳入完整的路徑,或者cypress會嘗試在你的web server上找到對應位置的頁面。(官方說明)


intercept與fixtures的使用

使用 intercept 來監聽由頁面上請求(request)及回應(response),下面三者是相同的意思:

cy.intercept('/users/**')
cy.intercept('GET', '/users/**')
cy.intercept({
  method: 'GET',
  url: '/users/**',
})

你也可以為這個路由(route)新增別名(alias),除了方便辨識外,如果需要在request後執行的工作,可以使用下面的寫法:

cy.intercept('POST', '/users').as('createUser');

// once a request to create user responds, 'cy.wait' will resolve
cy.wait('@createUser')

GUI上可以看到這個 route 表格

執行此請求時會留下Log記錄,所有被監聽的路由會列在route表格,表格上可以看到所有route被呼叫的次數(表格最右側的數字),對應的別名(alias)是什麼。

上面 Stubbed 是代表回應(response)是否被取代了,這個是很好用的功能,例如:當我們將 users 這個請求的回應,取代為一個列表:

// requests to '/users' will be fulfilled
// with a body of list: ['John', 'Ben', 'Mary]

cy.intercept(
  '/users',
  ['John', 'Ben', 'Mary],
)

或者可以使用 fixture ,後面填寫 fixture/ 目錄裡的檔案名稱。

// requests to '/users' will be fulfilled
// with the contents of the "users.json" fixture

cy.intercept(
  '/users',
  { fixture: 'users.json' },
)
(官方說明)


ESLint設定

請在 .eslintrc.js 加上設定,不需要安裝任何套件:

module.exports = {
  extends: [
    'plugin:cypress/recommended',
  ],
};