Cypress系列(69)- route() 命令詳解

小菠蘿測試筆記發表於2020-10-21

如果想從頭學起Cypress,可以看下面的系列文章哦

https://www.cnblogs.com/poloyy/category/1768839.html

 

作用

管理控制整個網路請求

 

重要注意事項

Cypress 目前僅支援攔截 XMLHttpRequest(XHR)

可在開發者工具(network 一欄)看到請求的 type 是 xhr,或者直接點選 xhr 進行篩選

同樣是 login 請求,有些是 xhr,有些卻是 document,對於 type=document 的請求, .route() 預設是不會攔截到的

 

非 XHR 請求

使用 Fetch API 的請求以及其他型別的網路請求(例如頁面載入和 <script> 標記)將不會在命令日誌中被攔截或看到

 

實驗性功能

實驗性 route2() 命令,該命令支援使用 Fetch API 的請求以及其他型別的網路請求,例如頁面載入;該命令將在後面wenz展開講解

 

語法格式

cy.route(url)
cy.route(url, response)
cy.route(method, url)
cy.route(method, url, response)
cy.route(callbackFn)
cy.route(options)

 

引數說明

url

需要監聽的 URL,遵循 minimatch 模式

 

response

為匹配上的 URL 提供自定義響應體

 

method

待匹配監聽 URL 的請求方法

 

callbackFn

回撥函式

 

options

 

通俗理解的總結

  • 當發出請求的 url + method 匹配上路由的 url + method,就會被該路由監聽到
  • 簡單理解:response 是自定義響應體,status 是自定義響應狀態碼,headers 是自定義響應頭
  • 如果設定了 response、status、headers 引數,則被監聽到的請求會獲取到這三個引數

 

 

命令執行結果

  • 執行結果是 null
  • 且後續不能再連結其他命令

 

URL minimatch 的栗子

前言

可以通過 *、** 來匹配動態的路由,我們們直接看栗子就好了

 

栗子一

cy.server()
cy.route('**/users/*/comments')

// https://localhost:7777/users/123/comments     <-- 匹配
// https://localhost:7777/users/123/comments/465 <-- 不匹配

 

栗子二

cy.server()
cy.route('**/posts/**')

// https://localhost:7777/posts/1            <-- 匹配
// https://localhost:7777/posts/foo/bar/baz  <-- 匹配
// https://localhost:7777/posts/quuz?a=b&1=2 <-- 匹配
// https://localhost:7777/posts <-- 不匹配
 

 

栗子三

cy.route('**/users/*')

// 下面的都匹配
/users/1
http://localhost:2020/users/2
https://google.com/users/3

// 下面的都不匹配
/users/4/foo
http://localhost:2020/users/5/foo

 

實際栗子

進入演示專案目錄下

注:演示專案是 cypress 提供的,如何下載可看 Cypress 系列文章的一開始幾篇都有寫

cd C:\Users\user\Desktop\py\cypress-example-recipes\examples\logging-in__xhr-web-forms

 

啟動演示專案

npm start

 

瀏覽器訪問專案

http://localhost:7079/

 

測試程式碼

    const username = 'jane.lane'
    const password = 'password123'

    before(function () {
        cy.visit('http://localhost:7079/')
    })

    it('正常登入,修改登入請求的status、response', function () {
        cy.server()
        cy.route({
            url: '**/login',
            method: 'POST',
            status: 503,
            delay: 1000,
            response: {
                success: false,
                data: 'Not success'
            },
        }).as("login")
        cy.get("input[name=username]").type(username)
        cy.get("input[name=password]").type(`${password}{enter}`)
        cy.wait('@login').then((res) => {
            cy.log(res)
            expect(res.status).to.eq(503)
            expect(res.responseBody.data).to.eq('Not success')
        })
    });

 

測試結果

 

檢視 route 路由的日誌

  • 每當啟動伺服器( cy.server() )並新增路由( cy.route() )時,Cypress 都會顯示一個名為 ROUTES(n) 的新模組日誌
  • 它將在日誌中列出路由表,包括方法,URL,是否Stubbed,別名和成功匹配請求的數量

可以看到成功匹配一個請求

 

檢視 XHR 命令日誌

  • 當發出 XHR 請求後,Cypress 會記錄此請求是否匹配到某個路由的別名
  • 這裡的 /login 請求就匹配到了 @login 

 

console 檢視響應結果

如果要對響應體做斷言,可以從這物件裡面拿到對應的值

 

重點

Cypress 通過 cy.route().as() 和 cy.wait() ,可以自動等到介面返回以後再執行後續操作,增強了測試用例的健壯性

// 簡單的程式碼結構(僅演示)

// 啟動 Mock 伺服器
cy.server({
    // 新增 options...        
})

// 新增多個 route 路由
cy.route({
    // 新增 options...       
}).as("route1")

cy.route({
    // 新增 options...       
}).as("route2")

....

// UI 介面的操作...
// 某些操作發出請求

// 等待請求的完成
cy.wait('route1').then((res)=>{
    
    // 對介面的響應做後續操作或斷言
    expect(res.status).to.eq(200)
})

 

強制返回 404 的栗子

不匹配路由的請求,強制返回 404 狀態和空 response

測試程式碼

 cy.server({ force404: true })
        cy.route({
            url: '**/logins',
            method: 'POST',
            status: 503,
            delay: 1000,
            response: {
                success: false,
                data: 'Not success'
            },
        }).as("login")

// 虛擬碼
// 發出 /login 請求的操作

 

測試結果

當 /login 沒有匹配到任意路由的時候,會返回 404

 

檢視 route 路由的日誌

可以看到沒有請求匹配成功此路由

 

官方的栗子

    it('cy.route() - route responses to matching requests', () => {
        // https://on.cypress.io/route
        // 訪問
        cy.visit('https://example.cypress.io/commands/network-requests')

        // 預置變數
        let message = 'whoa, this comment does not exist'

        // 啟動 Mock 伺服器
        cy.server()

        // 路由1:監聽 url 是 comments/* 且 請求方法是 GET 的請求
        cy.route('GET', 'comments/*').as('getComment')

        // 點選按鈕觸發請求
        cy.get('.network-btn').click()

        // 等待請求響應成功後獲取 status 進行斷言
        cy.wait('@getComment').its('status').should('eq', 200)

        // 路由2:監聽 url 是 /commets 且 請求方法是 POST 的請求
        cy.route('POST', '/comments').as('postComment')

        // 點選按鈕觸發請求
        cy.get('.network-post').click()

        // 等待請求響應成功後進行斷言
        cy.wait('@postComment').should((xhr) => {
            expect(xhr.requestBody).to.include('email')
            expect(xhr.requestHeaders).to.have.property('Content-Type')
            expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()')
        })

        /*
        路由3:監聽 url 是 comments/* 且 請求方法是 POST 的請求
        自定義 status、response、delay 並返回給監聽到的請求
         */
        cy.route({
            method: 'PUT',
            url: 'comments/*',
            status: 503,
            response: {error: message},
            delay: 500,
        }).as('putComment')

        // // 等待請求響應成功後進行斷言
        cy.get('.network-put').click()

        cy.wait('@putComment')

        // 出現 404 之後斷言文案
        cy.get('.network-put-comment').should('contain', message)
    })

 

注意事項

瞭解存根與常規XHR

Cypress 會在命令日誌中顯示 XHR 是傳送給伺服器還是 stub

在命令日誌中顯示(XHR STUB)的XHR就是傳送到 stub的,並且它們的 response,status,headers,delay 已由匹配的 cy.route() 控制

 

  • 單擊命令日誌中的命令時,在開發者工具 Console 中 Cypress 還會顯示 XHR是 否存根到控制檯、匹配到的 URL
  • Initiator 是啟動器,裡面是傳送 XHR 的堆疊跟蹤

 

無法使用  cy.request() 除錯 cy.route() 

  •  cy.request() 會將請求直接傳送到伺服器,直接繞開 .route() 路由
  •  cy.request() 目的是用於檢查實際雲心的伺服器,而無須啟動前端應用程式

 

相關文章