问题
当在我的Rails/React应用程序中使用Capybara运行e2e测试时,每当javascript使用React时,它都会在执行代码时遇到问题。当代码在本地和docker中正确呈现时,<div id="root"></div>
保持为空。我在本地进行水豚测试时也重复了这一点。奇怪的是,如果我添加一个document.getElementById("root").innerText = "Foo bar"
,它就会运行javascript,要么不知道如何执行ReactDOM.render
位,要么就是不知道。当针对Stimulus代码运行测试时,它会正确呈现。对于葬礼,我降级为反应16,但也有同样的问题。
背景:
我们使用Vite js来捆绑javascript,我不认为与之相关,但肯定可以。该应用程序在高山码头环境中运行,但我可以在本地复制它,所以我不认为它的特定环境与之相关。Rails路由是空的端点,它为一个空的html页面提供一个#rootdiv,供React水合并相应地路由。我们没有使用react-rails
宝石。在html页面的输出中,资产都指向正确的js文件,并且代码确实存在于这些文件中。
代码
水豚测试的主要运行时代码。我已经包含了我用水豚测试测试的小react片段的代码和print page.html
的输出。
app/javascript/entrypoints/test.jsx
import React from "react"
import ReactDOM from "react-dom"
// If this is uncommented, this line runs correctly but is not
// replaced by the "Hello World" in the `render` method
// document.getElementById("root").innerText = "Foo bar"
// This never gets run or is run incorrectly
ReactDOM.render(
<div>Hello World</div>,
document.getElementById("root")
)
test.html.haml
(是的,我知道haml很糟糕)
!!!
%html{lang: :en}
%head
= vite_client_tag
= vite_react_refresh_tag
= vite_javascript_tag "test.jsx"
%body
#root
react_test_spec.rb
require "rails_helper"
RSpec.describe "Testing react", type: :feature, js: true do
describe "just checking", :with_csrf do
before { visit test_home_path }
subject { page }
it "renders react" do
print page.html
expect(page).to have_content "Hello World"
end
end
end
print page.html output
<html lang="en"><head>
<script src="/vite-test/assets/test.92ee76c9.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite-test/assets/jsx-dev-runtime.ddafb254.js" as="script" crossorigin="anonymous">
</head>
<body>
<div id="root"></div>
</body></html>
配置/设置代码。包装版本、水豚/卵黄蛋白配置等
package.json
// react related packages
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "6",
// vite related packages
"stimulus-vite-helpers": "^3.0.0",
"vite": "^2.9.1",
"vite-plugin-ruby": "^3.0.9",
"vite-plugin-stimulus-hmr": "^3.0.0",
"@vitejs/plugin-react": "^1.3.2",
// babel related packages
"@babel/core": "^7.0.0-0",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.17.12",
"@babel/eslint-parser": "^7.17.0",
"@babel/plugin-transform-runtime": "^7.18.2",
"@babel/preset-env": "^7.17.10",
"babel-jest": "^27.5.1",
"babel-plugin-macros": "^3.1.0",
capybara.rb
Capybara.register_driver :chrome_headless do |app|
options = ::Selenium::WebDriver::Chrome::Options.new
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--window-size=1400,1400")
Capybara::Selenium::Driver.new(app, browser: :chrome, capabilities: [options])
end
Capybara.javascript_driver = :chrome_headless
vite.config.ts
export default defineConfig({
build: {
sourcemap: true,
},
plugins: [RubyPlugin(), react(), StimulusHMR()],
})
vite.json
{
"all": {
"sourceCodeDir": "app/javascript",
"watchAdditionalPaths": []
},
"development": {
"autoBuild": true,
"publicOutputDir": "vite-dev",
"port": 3036
},
"test": {
"autoBuild": true,
"publicOutputDir": "vite-test",
"port": 3037
}
}
some packages in Dockerfile.development
。还使用chromedriver
在本地复制了此问题
RUN apk add
build-base
chromium
chromium-chromedriver
您的JS资产在开发和测试模式中可能会以不同的方式构建,这听起来像是您有一个阻止水合的JS错误。在测试中添加一个暂停,在非无头模式下运行,并在开发人员控制台上查看JS/网络错误