使用 Rails、Capybara 和 React Component 进行集成测试

Integration test with Rails, Capybara with React Component

我使用 Rails 创建了一个用于创建帖子的小脚手架,但使用标准形式 erb 我创建了一个简单的 React 组件(我使用 gem react-rails and browserify-rails).

您可以找到包含所有源代码的示例存储库 here!

React 组件如下所示:

class NewPostForm extends React.Component {

  constructor(props) {
    super(props)
    this.state = {}
  }

  render() {
    return(
      <form action="/posts" accept-charset="UTF-8" method="post">
        <input name="utf8" type="hidden" value="✓"/>
        <input type="hidden" name="authenticity_token" value={this.props.authenticityToken}/>

        <div className="field">
          <label for="post_title">Title</label>
          <input type="text" name="post[title]" id="post_title" onChange={(e) => this.setState({title: e.target.value})} />
        </div>

        <div className="field">
          <label for="post_body">Body</label>
          <textarea name="post[body]" id="post_body" onChange={(e) => this.setState({body: e.target.value})}></textarea>
        </div>

        { this.state.title &&
          <div class="actions">
            <input type="submit" name="commit" value="Create Post" data-disable-with="Create Post"/>
          </div>
        }
      </form>
    )
  }

}

请注意,仅当标题输入字段已填写时,才会将提交按钮添加到 DOM。

文件app/views/posts/_form.html.erb是这样的:

<%= react_component 'NewPostForm', {authenticityToken: form_authenticity_token.to_s}, {prerender: true} %>

现在我已经创建了这个使用 Capybara 的集成测试:

require 'test_helper'

class PostCreationTest < ActionDispatch::IntegrationTest

  test "post creation" do
    visit new_post_path
    fill_in 'post[title]', with: 'Big News'
    fill_in 'post[body]', with: 'Superman is dead!'
    click_button 'Create Post' # <=== DO NOT FIND THIS BUTTON CAUSE IS ADDED WITH REACT
    assert page.has_content?('Post was successfully created.')
  end

end

测试失败并出现此错误:

Run options: --seed 21811

# Running:

E

Error:
PostCreationTest#test_post_creation:
Capybara::ElementNotFound: Unable to find visible button "Create Post"
    test/integration/post_creation_test.rb:9:in `block in <class:PostCreationTest>'


bin/rails test test/integration/post_creation_test.rb:5

在 test_helper.rb 中,我已将 Capybara 配置为使用 poltergeist driver。

Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, {
    js_errors: false,
    phantomjs_options: ['--ignore-ssl-errors=yes', '--ssl-protocol=any'],
    debug: false,
    timeout: 500,
    phantomjs: File.absolute_path(Phantomjs.path)
  })
end
Capybara.javascript_driver = :poltergeist
Capybara.server_port = 3001

如果我在 React 组件中始终显示提交按钮(删除 { this.state.title &&),则测试成功通过。

那么,有没有办法让这个测试与这个设置和 React 组件一起工作?

你有几个问题。首先是您实际上 运行 没有使用支持 JS 的驱动程序进行测试。您已配置 poltergeist 以与 Capybara 一起使用,但您从未通过设置 Capybara.current_driver 告诉 Capybara 使用 if 进行特定测试 - 请参阅 https://github.com/teamcapybara/capybara#using-capybara-with-minitest 为失败的测试添加 Capybara.current_driver = Capybara.javascript_driver 会引发您遇到的下一个问题。

PhantomJS(由 Poltergeist 使用)当前不支持 ES5.1+ JS 或现代 CSS 因此如果您想使用它,您需要填充并转译回 ES5 级别。如果您停止在 Poltergeist 配置中隐藏 JS 错误 (js_errors: true),这一点会立即变得清晰。因此,最初的错误是您的代码使用 Map class 直到 ES6/2015 才添加,因此 Poltergeist 不支持它(没有 polyfill)。

作为 Capybara JS 测试的初学者,您最好开始使用 selenium 进行需要测试的 JS(这样您就可以准确地看到正在发生的事情并支持现代 JS/CSS),然后在测试时可能会继续使用 selenium 和 headless chrome 或 headless FF.

Capybara.javascript_driver = :selenium # or :selenium_chrome