在 Rails 引擎中,Rspec 是否可以利用其他引擎的 Rspec 支持系统助手?

发布于 2025-01-12 08:07:15 字数 1607 浏览 3 评论 0原文

给定一个 Rails engine_one,它有一个规范支持文件 engine_one/spec/support/system/order_functions.rb,其中包含支持测试各种订单系统测试的功能,例如模拟登录用户、添加产品到订单等,并包含诸如 log_visitor_in 之类的方法,这些方法在测试订单处理等时被广泛使用...

所以现在在 engine_two 中,从 engine_one 扩展了一些订购功能,我希望添加一个新的系统测试,首先必须记录访客那么我如何利用engine_one 的支持方法呢?

到目前为止,我已经在虚拟应用程序中安装了引擎 我在engine_two/lib/engine.rb 中需要engine_one 我在相关测试中需要支持文件,但找不到它,显然我

中将engine_one添加到engine_two.gemspec engine_two/spec/rails_helper.rb

require 'engine_one' # and any other gems you need

engine_two/lib/engine_two/engine.rb

require 'engine_one'

已在相关系统测试 以下

engine_two/spec/system/new_ payment_methods_spec.rb

require 'rails_helper'
include EngineOne::System

    RSpec.describe "order_payment_feature", type: :system do
      before do
        driven_by(:rack_test)
      end
    
      it "has order payment options" do
        log_visitor_in
      end
    end

这会导致以下错误

Failure/Error: include EngineOne::System

NameError:
  uninitialized constant EngineOne::System
  Did you mean?  SystemExit

并且我尝试使用 require 而不是 include 的帮助器

module System
  def log_visitor_in()
    administrator = create(:visitor)
    visit ccs_cms.login_url
    fill_in 'login_name', with: visitor.login_name
    fill_in 'Password', with: visitor.password
    click_button 'Login'
  end

end

,但这会导致文件不发现错误 另外,我尝试将包含路径更改为

include EngineOne::Spec::Support::System 导致相同的错误

所以我想我正在寻找正确的路径,但我被卡住或丢失了一些其他包含助手的方式。 这些是 Rails 7 引擎。

Given a Rails engine_one that has a spec support file engine_one/spec/support/system/order_functions.rb, containing functionality to support the testing of various order system tests such as simulating a logged in user, adding products to an order etc and contains methods such as log_visitor_in that get used extensively when testing order processing etc...

So now in engine_two that extends some ordering functionality from engine_one I wish to add a new system test that first has to log a visitor in. So how can I make use of that support method from from engine_one?

So far I have mounted the engines in the dummy app
I have required engine_one in engine_two/lib/engine.rb
I have required the support file in the relevant test but it can't be found and obviously I have added engine_one to engine_two.gemspec

engine_two/spec/rails_helper.rb

require 'engine_one' # and any other gems you need

engine_two/lib/engine_two/engine.rb

require 'engine_one'

in the relevant system test I have the following

engine_two/spec/system/new_payment_methods_spec.rb

require 'rails_helper'
include EngineOne::System

    RSpec.describe "order_payment_feature", type: :system do
      before do
        driven_by(:rack_test)
      end
    
      it "has order payment options" do
        log_visitor_in
      end
    end

This results in the following error

Failure/Error: include EngineOne::System

NameError:
  uninitialized constant EngineOne::System
  Did you mean?  SystemExit

And the helper

module System
  def log_visitor_in()
    administrator = create(:visitor)
    visit ccs_cms.login_url
    fill_in 'login_name', with: visitor.login_name
    fill_in 'Password', with: visitor.password
    click_button 'Login'
  end

end

I have tried with a require instead of an include but that results in a file not found error
Plus I have tried changing the include path to

include EngineOne::Spec::Support::System resulting in the same error

So I guess I'm looking for the correct path but I am stuck or missing some other way to include the helper.
These are Rails 7 engines.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

物价感观 2025-01-19 08:07:15

当您require一个文件时,Ruby会相对于$LOAD_PATH中的路径搜索它; spec/ 或 test/ 不是其中的一部分。

app 目录是rails 中的一个特殊目录,任何子目录都会自动成为autoload_paths 的一部分。自动加载路径可以在此处查看ActiveSupport::Dependency.autoload_paths

可以使用 app/* 目录中定义的任何类/模块,而不需要相应的文件。 Rails v7 使用 zeitwerk 依靠“文件名”到“常量名称”关系来自动加载/重新加载文件。这就是文件夹映射到命名空间、文件映射到类/模块的原因。

要解决您的问题,请将任何共享代码放在可以通过 require 获取的位置。在控制台中输入$LOAD_PATH

>> $LOAD_PATH
=> 
["/home/alex/code/stackoverflow/lib",
 "/home/alex/code/stackoverflow/vendor",
 "/home/alex/code/stackoverflow/app/channels",
 "/home/alex/code/stackoverflow/app/controllers",
 "/home/alex/code/stackoverflow/app/controllers/concerns",
 "/home/alex/code/stackoverflow/app/helpers",
 "/home/alex/code/stackoverflow/app/jobs",
 "/home/alex/code/stackoverflow/app/mailers",
 "/home/alex/code/stackoverflow/app/models",
 "/home/alex/code/stackoverflow/app/models/concerns",

 "/home/alex/code/stackoverflow/engines/question/lib",   # <= engine's lib looks good

 "/home/alex/code/stackoverflow/engines/question/app/components",
 "/home/alex/code/stackoverflow/engines/question/app/controllers",
 "/home/alex/code/stackoverflow/engines/question/app/controllers/concerns",
 ...

将共享文件放入引擎的lib目录中。由于我们位于 app 目录之外,rails 不再是老大,任何路径和文件名组合都可以使用。

# question/lib/testing_support/blah.rb                   # <= note the filename
module System
  def log_visitor_in
    administrator = create(:visitor)
    visit ccs_cms.login_url
    fill_in 'login_name', with: visitor.login_name
    fill_in 'Password', with: visitor.password
    click_button 'Login'
  end
end

现在可以要求该文件

# test/test_helper.rb or spec/rails_helper.rb 
# after environment and rails requires

require "testing_support/blah"                           # => loads System module

# ...

了,就这样,在您的规范中使用它

require 'rails_helper'
RSpec.describe "order_payment_feature", type: :system do
  include System # include is for modules; now we have its functions in this spec

  before { log_visitor_in }

  it 'should accept this answer' do
    visit 'questions/71362333'
    expect(page).to have_content('accepted')
  end
end

此外,您可以使用绝对路径以任何您希望的方式要求您的文件,而不管$LOAD_PATH

require EngineOne::Engine.root + 'spec/support/system/order_functions.rb'

# or something else
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }

When you require a file, ruby searches for it relative to paths in $LOAD_PATH; spec/ or test/ are not part of it.

app directory is a special one in rails, any subdirectory automatically becomes part of autoload_paths. Auto load paths can be seen here ActiveSupport::Dependencies.autoload_paths.

Any classes/modules defined inside app/* directories can be used without requiring corresponding files. Rails v7 uses zeitwerk to automatically load/reload files by relying on the 'file name' to 'constant name' relationship. That's why folders map to namespaces and files map to classes/modules.

To fix your issue put any shared code where it can be grabbed with require. Type $LOAD_PATH in the console:

>> $LOAD_PATH
=> 
["/home/alex/code/stackoverflow/lib",
 "/home/alex/code/stackoverflow/vendor",
 "/home/alex/code/stackoverflow/app/channels",
 "/home/alex/code/stackoverflow/app/controllers",
 "/home/alex/code/stackoverflow/app/controllers/concerns",
 "/home/alex/code/stackoverflow/app/helpers",
 "/home/alex/code/stackoverflow/app/jobs",
 "/home/alex/code/stackoverflow/app/mailers",
 "/home/alex/code/stackoverflow/app/models",
 "/home/alex/code/stackoverflow/app/models/concerns",

 "/home/alex/code/stackoverflow/engines/question/lib",   # <= engine's lib looks good

 "/home/alex/code/stackoverflow/engines/question/app/components",
 "/home/alex/code/stackoverflow/engines/question/app/controllers",
 "/home/alex/code/stackoverflow/engines/question/app/controllers/concerns",
 ...

Put shared files in engines's lib directory. Since we're outside of app directory, rails is not the boss anymore, any path and filename combination will work.

# question/lib/testing_support/blah.rb                   # <= note the filename
module System
  def log_visitor_in
    administrator = create(:visitor)
    visit ccs_cms.login_url
    fill_in 'login_name', with: visitor.login_name
    fill_in 'Password', with: visitor.password
    click_button 'Login'
  end
end

Now that file can be required

# test/test_helper.rb or spec/rails_helper.rb 
# after environment and rails requires

require "testing_support/blah"                           # => loads System module

# ...

That's it, use it in your spec

require 'rails_helper'
RSpec.describe "order_payment_feature", type: :system do
  include System # include is for modules; now we have its functions in this spec

  before { log_visitor_in }

  it 'should accept this answer' do
    visit 'questions/71362333'
    expect(page).to have_content('accepted')
  end
end

Additionally you can require your files any way you wish with an absolute path, regardless of $LOAD_PATH.

require EngineOne::Engine.root + 'spec/support/system/order_functions.rb'

# or something else
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文