平常都用慣 TypeScript 版的 Cypress,但這兩天都用 JavaScript 在寫測試,令我有點不太習慣。
雖然 JS 版或 TS 版的差別並沒有多大,但少了一些開發時期的型別檢查與 Intellisense 還是令人感到彆扭。
因此,我們今天就來分享如何把 JS 版的 Cypress 變成 TS 版吧!
首先,如果你的專案是 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 run
、 cypress 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 會跟你說:
但是如果我們實際跑測試的話,又都會通過,那到底為什麼會有紅色毛毛蟲呢?
其實這是因為, VSCode 以為原本非 E2E 測試的 .spec.ts
是 Cypress 的檔案,所以它把原本是 Jasmine 的 expect()
:
誤認為是 Chai 的 expect()
:
那該怎麼辦才好呢?
其實會造成這個狀況是因為 VSCode 它預設會吃 tsconfig.json
的設定,而如果原本根目錄就有 tsconfig.json
,然後又在 /cypress
裡加了 tsconfig.json
的話,就會出現這種狀況。
這時我們只需要在根目錄的 tsconfig.json
加上這個設定就可以恢復正常了:
{
"include": [
"src",
"node_modules/cypress"
],
"exclude": [
"node_modules/cypress"
]
}
如果這部份有遇到問題的話,可以參考我的 Source Code 的設定。
不過別高興地太早,還有一件事情需要我們留意與調整。
之前在 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 的服務。
同時也建議大家在看我的實作之前,先按照需求規格自己做一遍,之後再跟我的對照,看看自己的實作跟我的實作不同的地方在哪裡、有什麼好處與壞處,如此反覆咀嚼消化後,我相信你一定可以進步地非常快!
如果你有任何的問題或是回饋,還請麻煩留言給我讓我知道!
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的問題
哇!超詳盡的!!!!
非常感謝你的整理與分享!可惜不能按讚不然我一定按爆!!
不會~剛好我遇到的問題都有辦法解決^_^