iT邦幫忙

2021 iThome 鐵人賽

DAY 22
1
Modern Web

Angular 深入淺出三十天:表單與測試系列 第 22

Angular 深入淺出三十天:表單與測試 Day22 - 把 Cypress 變成 TypeScript 版

  • 分享至 

  • xImage
  •  

Day22

平常都用慣 TypeScript 版的 Cypress,但這兩天都用 JavaScript 在寫測試,令我有點不太習慣。

雖然 JS 版或 TS 版的差別並沒有多大,但少了一些開發時期的型別檢查與 Intellisense 還是令人感到彆扭。

因此,我們今天就來分享如何把 JS 版的 Cypress 變成 TS 版吧!

Angular 專案

首先,如果你的專案是 Angular ,預設不會配有任何 E2E 自動化測試工具,如果我們想要在 Angular 的專案使用 Cypress ,可以直接在終端機輸入以下指令:

$ ng add @cypress/schematic

等待它執行完成後,你會發現 Angular Schematics 除了幫你裝好 Cypress 之後,也在 package.json 裡的 scripts 區段增加了以下三個指令:

{
  "scripts": {
    "e2e": "ng e2e",
    "cypress:open": "cypress open",
    "cypress:run": "cypress run"
  }
}

並且在 angular.json 裡的 architect 區段添加了以下設定:

{
  "cypress-run": {
    "builder": "@cypress/schematic:cypress",
    "options": {
      "devServerTarget": "ng-with-cypress:serve"
    },
    "configurations": {
      "production": {
        "devServerTarget": "ng-with-cypress:serve:production"
      }
    }
  },
  "cypress-open": {
    "builder": "@cypress/schematic:cypress",
    "options": {
      "watch": true,
      "headless": false
    }
  },
  "e2e": {
    "builder": "@cypress/schematic:cypress",
    "options": {
      "devServerTarget": "ng-with-cypress:serve",
      "watch": true,
      "headless": false
    },
    "configurations": {
      "production": {
        "devServerTarget": "ng-with-cypress:serve:production"
      }
    }
  }
}

e2e 的部份如果原本是使用 Protractor ,也會被調整過來。

這段設定的用意是讓 Angular CLI 知道,當我們要執行 cypress runcypress open 或是 ng e2e 的指令時,會連帶啟動 Angular 的服務,方便開發者使用時,不需額外自己啟動。

葛來芬多 Cypress 加 10 分!

此外,不可少的 cypress.json/cypress 資料夾當然也已經新增好了,而且 cypress.json 裡還已經幫我們配置了以下設定:

{
  "integrationFolder": "cypress/integration",
  "supportFile": "cypress/support/index.ts",
  "videosFolder": "cypress/videos",
  "screenshotsFolder": "cypress/screenshots",
  "pluginsFile": "cypress/plugins/index.ts",
  "fixturesFolder": "cypress/fixtures",
  "baseUrl": "http://localhost:4200"
}

原本 /cypress 資料夾裡的 .js 檔也都變成了 .ts 檔,至此,我們就成功地把 Cypress 加入的 Angular 專案之中了,是不是超方便、超簡單的?!

Angular + Cypress 真的會把開發者寵壞

想知道什麼是 Angular Schematics 嗎?可以閱讀我的系列文:高效 Coding 術:Angular Schematics 實戰三十天

其他更多資訊,可以參考 Cypress 官方文件:https://docs.cypress.io/guides/migrating-to-cypress/protractor#Recommended-Installation

額外告訴大家一個小故事:其實這個 Schematics 原本不是官方維護的,這個 Schematics 的原身一開始是這個 @briebug/cypress-schematic ,不過後來被官方採用,才改由 Cypress 團隊維護。

衷心感謝所有曾經或正在為 Open Source 貢獻心力的每一個人。

其他類型專案

Angular 專案有 Angular Schematics ,但其他類型的專案或者是單單只有 Cypress 的專案怎辦?

別擔心,其實要做的事情也不會太繁瑣或困難。

首先,我們可以先在專案裡輸入以下指令以安裝 TypeScript :

$ npm install typescript --save-dev

or

$ yarn add typescript --dev

如果你的專案裡已經有安裝 TypeScript 的話請略過此步驟

然後在 /cypress 資料夾內新增一個 tsconfig.json 檔,並添加以下內容:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["es5", "dom"],
    "types": ["cypress"]
  },
  "include": ["**/*.ts"]
}

然後就可以把我們的 .js 檔都改成 .ts 檔,並把所有的 /// <reference types="cypress" /> 都拿掉囉!

不過如果你本來的專案就是 TypeScript 的,這時候你可能會發現你原本非 E2E 測試的 .spec.ts 檔案多了一堆紅色毛毛蟲:

VSCode Capture

然後你將滑鼠游標移到紅色毛毛蟲上, VSCode 會跟你說:

VSCode Capture

但是如果我們實際跑測試的話,又都會通過,那到底為什麼會有紅色毛毛蟲呢?

其實這是因為, VSCode 以為原本非 E2E 測試的 .spec.ts 是 Cypress 的檔案,所以它把原本是 Jasmineexpect()

VSCode Capture

誤認為是 Chaiexpect()

VSCode Capture

那該怎麼辦才好呢?

其實會造成這個狀況是因為 VSCode 它預設會吃 tsconfig.json 的設定,而如果原本根目錄就有 tsconfig.json ,然後又在 /cypress 裡加了 tsconfig.json 的話,就會出現這種狀況。

這時我們只需要在根目錄的 tsconfig.json 加上這個設定就可以恢復正常了:

{
  "include": [
    "src",
    "node_modules/cypress"
  ],
  "exclude": [
    "node_modules/cypress"
  ]
}

如果這部份有遇到問題的話,可以參考我的 Source Code 的設定。

不過別高興地太早,還有一件事情需要我們留意與調整。

自訂 Command

之前在 JS 版本使用自訂 Command 時,自訂的 Command 沒有 Intellisense 很不方便,而且參數也都沒有辦法定義型別,也增加了後續維護的困難度。

而現在我們升級成 TS 版本後,想要享受 TS 所帶來的好處之前,我們需要在我們的 command.ts 檔的開頭增加以下程式碼:

declare namespace Cypress {
  interface Chainable {
    // 這裡面擺放的是自訂 Command 的宣告
    // 例如:
    fillWith(account: string, password: string): Chainable<string>
  }
}

原本的自訂 Command 的區塊也可以一併調整成這樣:

Cypress.Commands.add('fillWith', (account: string, password: string) => {
  cy.get('#account').type(account);
  cy.get('#password').type(password);
})

如此一來,我們在寫測試案例的時候即可享有 Intellisense 與型別檢查的好處囉!

想知道更多可以參考官方的 TypeScript Support 文件

本日小結

今天的重點主要是升級完成後,千萬記得要在 command.ts 加上 namespace 的宣告,這點可能會是很多人會不小心忘記的地方。

此外,也記得將 /// <reference types="cypress" /> 從程式碼中移除,這個語法主要是針對 JS 的,升級 TS 之後有它反而會錯。

我今天的實作程式碼會放在 Github - Branch: day22 上供大家參考,不過雖然該專案是 Angular 專案,但我是使用「其他專案」的方式,所以在測試時會需要自己啟動 Angular 的服務。

同時也建議大家在看我的實作之前,先按照需求規格自己做一遍,之後再跟我的對照,看看自己的實作跟我的實作不同的地方在哪裡、有什麼好處與壞處,如此反覆咀嚼消化後,我相信你一定可以進步地非常快!

如果你有任何的問題或是回饋,還請麻煩留言給我讓我知道!


上一篇
Angular 深入淺出三十天:表單與測試 Day21 - E2E 測試實作 - 被保人表單
下一篇
Angular 深入淺出三十天:表單與測試 Day23 - Reactive Forms 進階技巧 - 欄位連動檢核邏輯
系列文
Angular 深入淺出三十天:表單與測試30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
ryan851109
iT邦新手 5 級 ‧ 2022-03-04 16:45:18

Hi Leo,
分享一下我在這篇遇到的事情
環境 : angular 13 、 把前面的範例從js修改成ts,故從其他類型專案開始做
1.安裝 TypeScript => 版本可能過高導致npm start時發生錯誤
解法 : 根據指示將TypeScript做降版的動作
參考資料 : https://stackoverflow.com/questions/57216110/the-angular-compiler-requires-typescript-3-4-0-and-3-5-0-but-3-5-3-was-found
2.cypress中JSON檔案無法讀取
解法 : 在cypress中的tsconfig.json裡面的compilerOptions加上"resolveJsonModule": true
參考資料 : https://www.codegrepper.com/code-examples/javascript/consider+using+%27--resolvejsonmodule%27+to+import+module+with+%27.json%27+extension
3.cypress中insured-form.spec.ts範例引入JSON方式錯誤
解法 : 將原本的import insuredForm from '../fixtures/insured-form.json';修改成import * as insuredForm from '../fixtures/insured-form.json';
Ps. 將"resolveJsonModule": true放到tsconfig.json裡面的compilerOptions也行,但網路上的人說會有其他的問題,自己還沒嘗試過XD
4.變成TS檔後,cypress中的plugins/index.ts裡面的module發生Cannot find name 'module'.
解法 : 根據提示安裝npm i --save-dev @types/node並在cypress中的tsconfig.json裡面的compilerOptions/types加上node=> "types": ["node","cypress"]

不過沒有遇到文中需要在根目錄的tsconfig.json加上include/exclude的問題

Leo iT邦新手 3 級 ‧ 2022-03-04 17:16:35 檢舉

哇!超詳盡的!!!!

非常感謝你的整理與分享!可惜不能按讚不然我一定按爆!!

不會~剛好我遇到的問題都有辦法解決^_^

Leo iT邦新手 3 級 ‧ 2022-03-07 09:20:30 檢舉

/images/emoticon/emoticon12.gif

我要留言

立即登入留言