Jas*_* FB 2 javascript reactjs nock next.js cypress
我正在尝试使用这个名为Nock JS的工具
\nhttps://www.npmjs.com/package/nock
\n使用Next JS,使用Cypress测试React演示应用程序
\n\xe2\x80\xa2 下一个 JS 13.4
\n\xe2\x80\xa2\xc2\xa0赛普拉斯 12.17.1
\n\xe2\x80\xa2 反应 18.2
\ne2e/homepage.cy.js
\n\n\ndescribe(\'weather app spec\', () => {\n it(\'can load the current weather\', () => {\n\n\n const nock = require(\'nock\')\n\n const scope = nock(\'https://api.openweathermap.org\')\n .get(\'/data/2.5/weather\')\n .reply(200, {\n "coord": {\n "lon": -73.9629,\n "lat": 40.6884\n },\n "weather" :\n [{"id": 211, "main": "scattered clouds", "description": "scattered clouds", "icon": "11d"}, {\n "id": 500,\n "main": "Rain",\n "description": "scattered clouds",\n "icon": "10d"\n }],\n "base" : "stations",\n "main":\n {\n "temp": 299.25,\n "feels_like": 299.25,\n "temp_min": 296.15,\n "temp_max": 303.46,\n "pressure": 1014,\n "humidity": 75\n }\n\n })\n\n cy.visit(\'/\')\n cy.get(\'#__next\').should(\'contain\', "Click to get your weather")\n cy.contains(\'Get Weather\').click()\n\n cy.contains("Current weather is scattered clouds")\n })\n})\n\nRun Code Online (Sandbox Code Playgroud)\n如果测试没有 nock,则测试通过(预期行为):
\n\n当然,我不想每次运行测试时都调用开放天气 API,现在测试被硬编码为“分散的云”,它会随着天气的变化而变化。
\n所以我希望 Nock 模拟来自外部 API 的 HTTP 响应,为所有测试运行修复它
\n但是,如果我添加该行scope = nock(\'https://api.openweathermap.org\')(如上所示),我会得到:
Right-hand side of \'instanceof\' is not an object\nRun Code Online (Sandbox Code Playgroud)\n\n虽然我不认为这与 Nock 给我这个错误的原因无关,但作为参考,这里是实现代码:
\n\nimport {useRouter} from \'next/router\'\nimport {useState, useEffect, useRef} from \'react\'\n\nexport async function getServerSideProps(context) {\n // Fetch data from external API\n const OPEN_WEATHER_MAP_API_KEY = process.env.OPEN_WEATHER_APP_API_KEY\n\n const query = context.query\n\n const lat = query.lat\n const long = query.long\n\n if (lat && long) {\n const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${OPEN_WEATHER_MAP_API_KEY}`;\n\n const res = await fetch(url)\n .then(res => res.json())\n .then(\n (result) => {\n if (Number(result.cod) === 200) {\n // success result\n const weatherSummary = result.weather[0].description;\n const k_temp = result.main.temp;\n return {forecastSuccess: true, weatherSummary, temp: k_temp}\n } else {\n return {forecastSuccess: false}\n }\n }\n )\n return {props: res}\n } else {\n return {props: {}}\n }\n}\n\n\nexport default function Home({forecastSuccess, weatherSummary, temp}) {\n const router = useRouter();\n\n const [lat, setLat] = useState(undefined);\n const [long, setLong] = useState(undefined);\n\n const getLocationAndWeather = () => {\n navigator.geolocation.getCurrentPosition(async (location) => {\n setLat(location.coords.latitude)\n setLong(location.coords.longitude)\n })\n }\n\n useEffect(() => {\n if (lat && long) {\n refreshData();\n }\n }, [lat, long])\n const refreshData = () => {\n router.replace(`${router.asPath}?lat=${lat}&long=${long}`);\n }\n\n return (\n <>\n <p>Click to get your weather:</p>\n <br />\n <input type={"submit"} onClick={ getLocationAndWeather } data-test-id={\'get-weather-button\'} value={"Get Weather"}/>\n\n <h1>\n { forecastSuccess && `Current weather is ${weatherSummary}`}\n </h1>\n <h2>\n { forecastSuccess && `${temp} \xc2\xb0F`}\n </h2>\n <br />\n </>\n )\n}\nRun Code Online (Sandbox Code Playgroud)\n
NockJS 是一个 Node 库,因此您很可能无法将其导入测试(在浏览器中运行)并在那里运行。
我在这里有一个半答案Mocking Next.js getInitialProps in _app这可能适合您的需要。
本质上,
在 NextJs SSR 中,几乎不可能在 Cypress 中模拟 API 请求,因为服务器在 Cypress 能够打开网页之前执行请求。
您可以相当轻松地使用 NextJs 自定义服务器设置“静态”模拟,但这只允许一组模拟数据。
理论上,您可以在设置模拟数据以适合特定测试cy.exec()之前使用 和 来配置模拟服务器以从测试内部启动和停止。cy.visit()
Gleb Bahmutov 有一个使用 Cypress 任务中的 NockJs 的示例,但它是用 Cypress v9 编写的,我无法将其升级到最新版本。但如果您想使用旧版本,这是一种可行的方法,也是您可以适应的将 NockJs 与 Cypress 结合使用的一个很好的示例。
我忘记提及的一件事是 NextJsfetch()在他们的示例中展示了实验性的 NodeJs(参见上面的链接)
import { NextPageContext } from 'next'
Page.getInitialProps = async (ctx: NextPageContext) => {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
...
Run Code Online (Sandbox Code Playgroud)
但诺克说
警告nock 目前与Node 的实验性本机 fetch实现 不兼容。
参见#2397
我提到这一点是为了防止您遵循 NextJs 示例。
您可以使用NodeJs http作为替代方案,但这需要您降级您的应用程序。
| 归档时间: |
|
| 查看次数: |
160 次 |
| 最近记录: |