我使用 Nuxt.js 作为前端框架,使用 Laravel 作为 api 服务器,并使用 Cypress 编写一些 e2e 测试。我正在尝试使用 cy.intercept 减少 asyncData api 调用,但未能成功拦截 api 调用,我的测试规范如下所示:
const siteUrl = Cypress.env('site_url')
const apiUrl = Cypress.env('api_url')
describe('Post Test', () => {
beforeEach(() => {
cy.intercept('GET', `${apiUrl}/post`, {
fixture: 'post.json',
})
})
it('should render posts same as mock data', () => {
cy.visit(`/post`)
cy.contains('some posts from mock data')
})
})
我的帖子/index.vue 看起来像这样:
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.description }}</p>
</div>
</template>
<script>
export default {
async asyncData({ params, $http }) {
const post = await $http.$get(`${apiUrl}/post`)
return { post }
}
}
</script>
当我运行测试时,在 asyncData 钩子中,Nuxt.js 仍然会向 Laravel 发送实际请求,要求发布数据。我已经阅读了this issue,但还是想问有没有其他方法可以用 Cypress 拦截来自服务器端的 api 调用?
答案 0 :(得分:1)
当您运行带有服务器端渲染的 Nuxt 应用时,asyncData()
调用是在服务器上进行的。
接收到的数据被添加到页面底部的“水合”功能中,然后提供给赛普拉斯浏览器。所以 cy.intercept()
永远不会接听电话。
处理它的一种方法是在测试期间模拟服务器,这可以在任务中完成
/cypress/plugins/index.js
let server; // static reference to the mock server
// so we can close and re-assign on 2nd call
module.exports = (on, config) => {
on('task', {
mockServer({ interceptUrl, fixture }) {
const fs = require('fs')
const http = require('http')
const { URL } = require('url')
if (server) server.close(); // close any previous instance
const url = new URL(interceptUrl)
server = http.createServer((req, res) => {
if (req.url === url.pathname) {
const data = fs.readFileSync(`./cypress/fixtures/${fixture}`)
res.end(data)
} else {
res.end()
}
})
server.listen(url.port)
console.log(`listening at port ${url.port}`)
return null
},
})
}
测试
const apiUrl = Cypress.env('api_url'); // e.g "http://localhost:9000"
cy.task('mockServer', { interceptUrl: `${apiUrl}/post`, fixture: 'post.json' })
cy.visit('/post')
// a different fixture
cy.task('mockServer', { interceptUrl: `${apiUrl}/post`, fixture: 'post2.json' })
cy.visit('/post')
cypress.json
{
"baseUrl": "http://localhost:3000",
"env": {
"api_url": "http://localhost:9000"
}
}
注意
apiUrl
另一种方法
见Control Next.js Server-Side Data During Cypress Tests。
这个想法是在页面从服务器到达时拦截它并修改它的水化功能。
您让生产 API 服务器运行以进行测试,以便 SSR 正常获取。
function interceptHydration( interceptUrl, fixture, key ) {
cy.fixture(fixture).then(mockData => {
cy.intercept(
interceptUrl,
(req) => {
req.continue(res => {
// look for "key" in page body, replace with fixture
const regex = new RegExp(`${key}:\s*{([^}]*)}`)
const mock = `${key}: ${JSON.stringify(mockData)}`
res.body = res.body.replace(regex, mock)
})
}
)
})
}
it('changes hydration data', () => {
interceptHydration( '/post', 'post', 'post' )
cy.visit('/post')
cy.get('h1').contains('post #2') // value from fixture
})