你不知道的Cypress系列(15) -- 支持跨域訪問了!
iTesting,愛測試,愛分享
一個人到底要走多少彎路,才能成為一名合格的測試開發(fā)工程師?
轉(zhuǎn)眼之間,你不知道的Cypress系列已經(jīng)到第15篇了。在Cypress中國群內(nèi)、在公眾號iTesting里,我每天都能看到大量關(guān)于Cypress的使用討論和私下問詢。這讓我感到無比榮幸(買了書的同學(xué)們,公眾號回復(fù)你的微信號,拉你到Cypress中國群)。
說起Cypress,讀者朋友們應(yīng)該對“下一代Web端自動化測試技術(shù)”,“彎道超車首選”等等早已爛熟于心了。Cypress獨(dú)特的運(yùn)行機(jī)制(運(yùn)行在瀏覽器內(nèi))也使得它吊打Webdriver之類的UI自動化測試工具。但是Cypress并不是完美無瑕,我們在使用Cypress做自動化測試時,經(jīng)常會提的一個問題就是,Cypress不支持跨域訪問,而我的測試需要跨域怎么辦?
今天在Cypress中國群內(nèi),有同學(xué)拋出了以下這個待發(fā)行的解決方案,我看了后頓時覺得好香,特記錄之。(永遠(yuǎn)不要懷疑Cypress開發(fā)團(tuán)隊(duì)的愿景:The web has evolved.? ? ? ? ? ?Finally, testing has too.)
跨域訪問的問題
看過我Cypress書的同學(xué)都應(yīng)該明白,Cypress里進(jìn)行跨域訪問會報錯:
//?關(guān)注iTesting,跟萬人測試團(tuán)一起成長。
describe('iTesting測試',?function?()?{
????it(`[This?is?a?demo?test`,?function?()?{
????????cy.visit('https://www.cypress.io/')
????????cy.contains('Login').invoke('removeAttr',?'target').click({force:?true})
????????//這里點(diǎn)擊google登錄,會跨域,所以報錯
????????cy.contains('Log?in?with?Google').click()
????});
});報錯的信息通常如下所示:

為了避免這個錯誤,如果我們使用的是Chrome瀏覽器進(jìn)行測試,我們通常在cypress.json文件夾里添加如下配置:
chromeWebSecurity:false
有時候,我們不想在cypress.json里配置,也可以直接在運(yùn)行命令行參數(shù)時,指定參數(shù):
yarn?cypress?open?--config?chromeWebSecurity=false
但這個方案不總是有效。像當(dāng)前這個情況就是無效的。
這個時候怎么辦?
當(dāng)前的解決方案是盡量的拆Case,從而保證在一條測試運(yùn)行里不進(jìn)行跨域訪問。比如,我的這條case實(shí)際上是通過google登錄,那么我可以在這條case里直接訪問登錄的那個url,而不必訪問cypress.io, ?但是這個是很簡單的情況,實(shí)際測試中,很復(fù)雜,我們必須要拆分測試用例,而這個操作很不方便。好在Cypress團(tuán)隊(duì)也注意到了這個問題。在即將發(fā)布的9.6.0版本中,Cypress將支持跨域訪問。
Cypress支持跨域 -- cy.origin()
在即將發(fā)布的9.6.0版本中,我們可以通過cy.origin()命令來支持跨域訪問。要啟用cy.origin(),我們需要在cypress.json中配置如下:
{?"experimentalSessionAndOrigin":?true}
此時,你就可以使用了,cy.origin()的語法如下:
cy.origin(url,?callbackFn)
cy.origin(url,?options,?callbackFn)
注意:
url:?這個url是cy.origin執(zhí)行回調(diào)的那個次要來源(假設(shè)在A domain下進(jìn)行某個操作會跳轉(zhuǎn)到domain B,那么A就是主要來源,B就是次要來源)。
options:?這個參數(shù)是一個普通的 JavaScript 對象,它將被序列化并從主要來源發(fā)送到次要來源。從那里它將被反序列化并作為第一個也是唯一的參數(shù)傳遞給回調(diào)函數(shù)。該參數(shù)的args對象(注意這個對象,看后續(xù)的代碼)是唯一可以將數(shù)據(jù)注入回調(diào)的機(jī)制,因?yàn)榛卣{(diào)不是閉包,并且不保留對聲明它的 JavaScript 上下文的訪問。
callbackFn:?此參數(shù)包含要在次要來源中執(zhí)行的Cypress命令的函數(shù)。Cypress將觸發(fā)此函數(shù)并從當(dāng)前Cypress實(shí)例傳遞到次要源并進(jìn)行評估。
實(shí)踐
舉個例子吧:
//?關(guān)注iTesting,跟萬人測試團(tuán)一起成長。
describe('iTesting測試',?function?()?{
????it(`This?is?a?demo`,?function?()?{
????????cy.visit('https://www.cypress.io/')
????????cy.contains('Login').invoke('removeAttr',?'target').click({force:?true})
????????//這里點(diǎn)擊google登錄,會跨域,所以報錯
????????cy.contains('Log?in?with?Google').click()
????????//?這個url填你的地址,可以手工copy過來
????????cy.origin("https://accounts.google.com/o/oauth2/auth/identifier?response_type=code&redirect_uri=https%3A%2F%2Fauth.cypress.io%2Flogin%2Fcallback&scope=email%20profile&state=vJHVGMmWHCZr7cEG-u8Si9JuLhh2uD9V&client_id=976680234070-jlotbgdqfah46f34o4oheoqkrng39jn9.apps.googleusercontent.com&hl=zh-CN&flowName=GeneralOAuthFlow",?()?=>?{
????????????cy.get("input[type="email"]").type('[email protected]');// 這里用戶名寫死了。
????????????cy.contains('Next').click()
????????????cy.get("input[type='password']").type('你的密碼')//密碼也是一樣寫死了。
????????????cy.contains('Next').click()
????????????//登錄成功,斷言
????????????cy.url().should('include',?'https://dashboard.cypress.io/welcome')?
????});
});
更進(jìn)一步 -- 重用
可以看到,上面的是個通過SSO登錄的例子,那么實(shí)際上,登錄應(yīng)該是個通用的操作,我們把它寫到support/commands.js?文件下:
Cypress.Commands.add("googleLogin",?(email,?password)?=>?{
??cy.visit('https://www.cypress.io/')
??cy.contains('Login').invoke('removeAttr',?'target').click({force:?true})
??//這里點(diǎn)擊google登錄
??cy.contains('Log?in?with?Google').click()
??
??//?關(guān)注iTesting,跟萬人測試團(tuán)一起成長。
??cy.origin(
????"登錄地址",
????{?args:?[email,?password]?}, // args 對象,劃重點(diǎn)
????([email,?password])?=>?{
??????cy.get("input[type="email"]").type(email); // args對象用法
??????cy.contains('Next').click()
??????cy.get("input[type='password']").type(password);
??????cy.contains('Next').click()
????}
??);
??//登錄成功,斷言
??cy.url().should('include',?'https://dashboard.cypress.io/welcome')?
});
通過這樣的方式,我們就可以直接在測試用例里調(diào)用:
beforeEach(()?=>?{
??cy.googleLogin('用戶名iTesting',?'密碼');
});
使用cy.session()加速鑒權(quán)
記得?你不知道的Cypress系列(11) -- 使用cy.session()加速鑒權(quán)?這篇文章不?我們來再次update下我們的最終代碼。
Cypress.Commands.add("login",?(email,?password)?=>?{
??cy.session([email,?password],?()?=>?{
??????cy.visit('https://www.cypress.io/')
??????cy.contains('Login').invoke('removeAttr',?'target').click({force:?true})
??????//這里點(diǎn)擊google登錄
??????cy.contains('Log?in?with?Google').click()
??????//?關(guān)注iTesting,跟萬人測試團(tuán)一起成長。
??????cy.origin(
????????"登錄地址",
????????{?args:?[email,?password]?},
????????([email,?password])?=>?{
??????????cy.get("input[type="email"]").type(email);
??????????cy.contains('Next').click()
??????????cy.get("input[type='password']").type(password);
??????????cy.contains('Next').click()
????????}
??????);
??????//登錄成功,斷言
??????cy.url().should('include',?'https://dashboard.cypress.io/welcome')?
??});
});
使用的方式一樣,直接在測試代碼里調(diào)用即可:
beforeEach(()?=>?{
??cy.googleLogin('用戶名iTesting',?'密碼');
});注意:
cy.origin()需要升級Cypress到最新的9.6.0,截止本文發(fā)布時(2022/04/27),官方還沒有release 9.6.0版本。
Cypress有很多奇淫巧技, 我已經(jīng)總結(jié)超過百篇
別走開,下一篇更精彩!
往期回看:
?????????????????? ?你不知道的Cypress系列(1) --雞肋的BDD
? ? ? ? ? ? ? ? ? ? 你不知道的Cypress系列(2) -- ”該死"的PO模型!
????????????????????你不知道的Cypress系列(3) -- 是時候重構(gòu)自己的思維了!
????????????????????你不知道的Cypress系列(4) -- “PO”已死,App Action當(dāng)立?
????????????????????你不知道的Cypress系列(5) -- "眼瞎"的TestRunner
????????????????????你不知道的Cypress系列(6) -- 多Tab的小秘密
? ? ? ? ? ? ? ?? ??你不知道的Cypress系列(7) -- 當(dāng)iFrame遇見彈出框??? ?? ? ?
? ? ? ? ? ? ? ? ? ??你不知道的Cypress系列(8) -- “可視化”測試你知多少
????????????????????你不知道的Cypress系列(9) -- 代碼“自動生成”術(shù)
? ? ? ? ? ? ? ? ? ??你不知道的Cypress系列(10) -- CypressHelper
? ? ? ? ? ? ? ? ???你不知道的Cypress系列(11) -- 使用cy.session()加速鑒權(quán)。??
? ? ? ? ? ? ? ? ? ?你不知道的Cypress系列(12) -- 測試報告Allure??
????????????????? ??你不知道的Cypress系列(13) -- 你真的需要多瀏覽器測試嗎??
?????????????????????你不知道的Cypress系列(14) -- 一文說透元素定位?????? ? ?
為了更好的支持我創(chuàng)作,麻煩同學(xué)們動動小手,點(diǎn)贊 +?在看 + 轉(zhuǎn)發(fā)一鍵三聯(lián)。再過一個月,給你們的小驚喜可能就來了 :)
?-???-??時人莫小池中水, 淺處不妨有臥龍??-??-
作者:
Kevin Cai, 江湖人稱蔡老師。
過期兩性情感專家,非著名測試開發(fā)。
技術(shù)路線的堅(jiān)定支持者,始終相信Nobody can be somebody。?
