Class: Brut::SpecSupport::RSpecSetup
- Inherits:
-
Object
- Object
- Brut::SpecSupport::RSpecSetup
- Defined in:
- lib/brut/spec_support/rspec_setup.rb
Overview
Configures RSpec for Brut. This provides several bits of infrastructure only present when the app is running, as well as quality of life improvements to make testing Brut components a bit easier. Even though Brut classes are all normal classes, it's convenient to have extraneous classes set up for you.
- Metadata is added based on the class names under test:
*Component
->:component
*Page
->:component
*Page
->:page
*Handler
->:handler
- If you add the
:page
metadata automatically,:component
is added as well. - Tests in
specs/e2e
or any subfolder ->:e2e
- Note that you are free to explicitly add these tags to your test metadata. That will cause the inclusion of modules as described below
- Modules are included to provide additional support for writing tests:
- GeneralSupport included in all tests
- ComponentSupport included when
:component
metadata is set (generally, this is for page and component tests) - HandlerSupport included when
:handler
is set. - included when
:e2e
is set, which allows use of the Ruby binding for Playwright.
- Non end-to-end tests will be run inside a database transaction to allow all database changes to be instantly undone. This does mean that any tests that tests database transaction behavior will not work as expected.
- In component tests (which generally includes page tests), a {Brut::FrontEnd::RequestContext is created for you and placed into
the thread local storage. This allows any component that is injected with data from the
RequestContext
to access it as it would normally. You can also seed this with data that a component may need. - Handles all infrastructure for end-to-end tests:
- starting a test server using E2ETestServer
- launching Chromium via Playwright
- If using Sidekiq:
- Jobs are cleared before each test
- For end-to-end tests, Redis is flushed and actual Sidekiq is used instead of testing mode
You can set certain metadata to change behavior:
e2e_timeout
- number of milliseconds to wait until an end-to-end test gives up on a selector being found. The default is 5,000 (5 seconds). Use this only if there's no other way to keep your test from needing more than 5 seconds.
Defined Under Namespace
Classes: OptionalSidekiqSupport
Instance Method Summary collapse
-
#initialize(rspec_config:, monkey_patch_summary_notification: true) ⇒ RSpecSetup
constructor
Create the setup with the given RSpec configuration.
-
#setup!(inside_db_transaction: ->() {}) ⇒ Object
Sets up RSpec with variouis configurations needed by Brut to run your tests.
Constructor Details
#initialize(rspec_config:, monkey_patch_summary_notification: true) ⇒ RSpecSetup
Create the setup with the given RSpec configuration.
RSpec's Notifications::SumaryNotification will be monkey-patched to show
bin/test
in the summary instead of ./rspec
, as that is how you would
re-run a test. But, it's still monkey-patching.
50 51 52 53 54 55 56 57 |
# File 'lib/brut/spec_support/rspec_setup.rb', line 50 def initialize(rspec_config:, monkey_patch_summary_notification: true) @config = rspec_config @monkey_patch_summary_notification = monkey_patch_summary_notification SemanticLogger.default_level = ENV.fetch("LOGGER_LEVEL_FOR_TESTS","warn") end |
Instance Method Details
#setup!(inside_db_transaction: ->() {}) ⇒ Object
Sets up RSpec with variouis configurations needed by Brut to run your tests.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/brut/spec_support/rspec_setup.rb', line 62 def setup!(inside_db_transaction: ->() {}) Brut::FactoryBot.new.setup! optional_sidekiq_support = OptionalSidekiqSupport.new @config. do || if [:described_class].to_s =~ /[a-z0-9]Component$/ || [:described_class].to_s =~ /[a-z0-9]Page$/ || [:page] == true [:component] = true end if [:described_class].to_s =~ /[a-z0-9]Page$/ || [:page] == true [:page] = true end if [:described_class].to_s =~ /[a-z0-9]Handler$/ [:handler] = true end relative_path = Pathname([:absolute_file_path]).relative_path_from(Brut.container.app_specs_dir) top_level_directory = relative_path.each_filename.to_a[0].to_s if top_level_directory == "e2e" [:e2e] = true end end @config.include Brut::SpecSupport::GeneralSupport @config.include Brut::SpecSupport::ComponentSupport, component: true @config.include Brut::SpecSupport::HandlerSupport, handler: true @config.include Brut::SpecSupport::E2eSupport, e2e: true @config.include Playwright::Test::Matchers, e2e: true @config.around do |example| needs_request_context = example.[:component] || example.[:handler] || example.[:page] if needs_request_context session = { "session_id" => "test-session-id", "csrf" => "test-csrf-token" } env = { "rack.session" => session } app_session = Brut.container.session_class.new(rack_session: session) request_context = Brut::FrontEnd::RequestContext.new( env: env, session: app_session, flash: empty_flash, body: nil, xhr: false, host: URI("https://example.com") ) Thread.current.thread_variable_set(:request_context, request_context) example.example_group.let(:request_context) { request_context } end if example.[:component] example.example_group.let(:component_name) { described_class.component_name } end if example.[:page] example.example_group.let(:page_name) { described_class.page_name } end if example.[:e2e] e2e_timeout = (ENV["E2E_TIMEOUT_MS"] || example.[:e2e_timeout] || 5_000).to_i optional_sidekiq_support.disable_sidekiq_testing do Brut::SpecSupport::E2ETestServer.instance.start Playwright.create(playwright_cli_executable_path: "./node_modules/.bin/playwright") do |playwright| launch_args = { headless: true, } if ENV["E2E_SLOW_MO"] launch_args[:slowMo] = ENV["E2E_SLOW_MO"].to_i end playwright.chromium.launch(**launch_args) do |browser| = { baseURL: "http://0.0.0.0:6503/", } if ENV["E2E_RECORD_VIDEOS"] [:record_video_dir] = Brut.container.tmp_dir / "e2e-videos" end browser_context = browser.new_context(**) browser_context.default_timeout = e2e_timeout example.example_group.let(:page) { browser_context.new_page } example.run browser_context.close browser.close end end end else optional_sidekiq_support.clear_background_jobs Sequel::Model.db.transaction do inside_db_transaction.() example.run raise Sequel::Rollback end end end @config.after(:suite) do Brut::SpecSupport::E2ETestServer.instance.stop end if @monkey_patch_summary_notification monkey_patch_summary_notification! end end |