DEV: Call MessageBus.stop() after each system test (#21848)

## What is the problem?

MessageBus by default uses long polling which keeps a connection
open for 25 seconds by default. The problem here is that Capybara does not know about these
connections being kept opened by MessageBus and hence does not know how
to stop these connections at the end of each test. As a result, the long polling MessageBus connections are kept opened by the browser and we hit chrome's limit of 6 concurrent requests per host, new request made in the browser is marked as "pending" until a request is freed up. Since we keep a MessageBus long polling connection opened for 25 seconds, our finders in Capybara end up hitting Capybara's wait time out causing the tests to fail.  

## What is the fix?

Since we can't rely on Capybara to close all the existing Capybara
connections, we manually execute a script to stop all MessageBus
connections after each system test.

```
for i in {1..10}; do
  echo "Running iteration $i"
  PARALLEL_TEST_PROCESSORS=8 CAPYBARA_DEFAULT_MAX_WAIT_TIME=10 bin/turbo_rspec --seed=34908 --profile --verbose --format documentation spec/system
  if [ $? -ne 0 ]; then
    echo "Error encountered on iteration $i"
    exit 1
  fi
done
echo "All 10 iterations completed successfully"
```

Without the fix, the script fails consistently in the first few iterations. Running in non-headless mode with the "network" tab opened will reveal the requests that are marked as pending.
This commit is contained in:
Alan Guo Xiang Tan 2023-05-31 22:00:35 +09:00 committed by GitHub
parent e1ba4c6b73
commit 4dd053a69c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 25 deletions

View File

@ -442,6 +442,7 @@ RSpec.configure do |config|
end end
end end
page.execute_script("if (typeof MessageBus !== 'undefined') { MessageBus.stop(); }")
Capybara.reset_sessions! Capybara.reset_sessions!
Capybara.use_default_driver Capybara.use_default_driver
Discourse.redis.flushdb Discourse.redis.flushdb

View File

@ -9,10 +9,6 @@ describe "Admin Customize Form Templates", type: :system, js: true do
fab!(:category) { Fabricate(:category) } fab!(:category) { Fabricate(:category) }
before do before do
skip(<<~TEXT) if ENV["CI"]
The specs here are extremely flaky on CI for some reason.
TEXT
SiteSetting.experimental_form_templates = true SiteSetting.experimental_form_templates = true
sign_in(admin) sign_in(admin)
end end
@ -21,25 +17,29 @@ describe "Admin Customize Form Templates", type: :system, js: true do
before { category.update!(form_template_ids: [form_template.id]) } before { category.update!(form_template_ids: [form_template.id]) }
it "should show the existing form templates in a table" do it "should show the existing form templates in a table" do
visit("/admin/customize/form-templates") form_template_page.visit
expect(form_template_page).to have_form_template_table expect(form_template_page).to have_form_template_table
expect(form_template_page).to have_form_template(form_template.name) expect(form_template_page).to have_form_template(form_template.name)
end end
it "should show the categories the form template is used in" do it "should show the categories the form template is used in" do
visit("/admin/customize/form-templates") form_template_page.visit
expect(form_template_page).to have_form_template_table expect(form_template_page).to have_form_template_table
expect(form_template_page).to have_category_in_template_row(category.name) expect(form_template_page).to have_category_in_template_row(category.name)
end end
it "should show the form template structure in a modal" do it "should show the form template structure in a modal" do
visit("/admin/customize/form-templates") form_template_page.visit
form_template_page.click_view_form_template form_template_page.click_view_form_template
expect(form_template_page).to have_template_structure("- type: input") expect(form_template_page).to have_template_structure("- type: input")
end end
it "should show a preview of the template in a modal when toggling the preview" do it "should show a preview of the template in a modal when toggling the preview" do
visit("/admin/customize/form-templates") form_template_page.visit
form_template_page.click_view_form_template form_template_page.click_view_form_template
form_template_page.click_toggle_preview form_template_page.click_toggle_preview
expect(form_template_page).to have_input_field("input") expect(form_template_page).to have_input_field("input")
@ -55,7 +55,7 @@ describe "Admin Customize Form Templates", type: :system, js: true do
end end
def quick_insertion_test(field_type, content) def quick_insertion_test(field_type, content)
visit("/admin/customize/form-templates/new") form_template_page.visit_new
form_template_page.type_in_template_name("New Template") form_template_page.type_in_template_name("New Template")
form_template_page.click_quick_insert(field_type) form_template_page.click_quick_insert(field_type)
expect(ace_editor).to have_text(content) expect(ace_editor).to have_text(content)
@ -63,7 +63,7 @@ describe "Admin Customize Form Templates", type: :system, js: true do
describe "when visiting the page to create a new form template" do describe "when visiting the page to create a new form template" do
it "should allow admin to create a new form template" do it "should allow admin to create a new form template" do
visit("/admin/customize/form-templates/new") form_template_page.visit_new
sample_name = "My First Template" sample_name = "My First Template"
sample_template = "- type: input" sample_template = "- type: input"
@ -75,40 +75,41 @@ describe "Admin Customize Form Templates", type: :system, js: true do
end end
it "should disable the save button until form is filled out" do it "should disable the save button until form is filled out" do
visit("/admin/customize/form-templates/new") form_template_page.visit_new
expect(form_template_page).to have_save_button_with_state(true) expect(form_template_page).to have_save_button_with_state(disabled: true)
form_template_page.type_in_template_name("New Template") form_template_page.type_in_template_name("New Template")
expect(form_template_page).to have_save_button_with_state(true) expect(form_template_page).to have_save_button_with_state(disabled: true)
ace_editor.type_input("- type: input") ace_editor.type_input("- type: input")
expect(form_template_page).to have_save_button_with_state(false) expect(form_template_page).to have_save_button_with_state(disabled: false)
end end
it "should disable the preview button until form is filled out" do it "should disable the preview button until form is filled out" do
visit("/admin/customize/form-templates/new") form_template_page.visit_new
expect(form_template_page).to have_preview_button_with_state(true) expect(form_template_page).to have_preview_button_with_state(disabled: true)
form_template_page.type_in_template_name("New Template") form_template_page.type_in_template_name("New Template")
expect(form_template_page).to have_preview_button_with_state(true) expect(form_template_page).to have_preview_button_with_state(disabled: true)
ace_editor.type_input("- type: input") ace_editor.type_input("- type: input")
expect(form_template_page).to have_preview_button_with_state(false) expect(form_template_page).to have_preview_button_with_state(disabled: false)
end end
it "should show validation options in a modal when clicking the validations button" do it "should show validation options in a modal when clicking the validations button" do
visit("/admin/customize/form-templates/new") form_template_page.visit_new
form_template_page.click_validations_button form_template_page.click_validations_button
expect(form_template_page).to have_validations_modal expect(form_template_page).to have_validations_modal
end end
it "should show a preview of the template in a modal when clicking the preview button" do it "should show a preview of the template in a modal when clicking the preview button" do
visit("/admin/customize/form-templates/new") form_template_page.visit_new
form_template_page.type_in_template_name("New Template") form_template_page.type_in_template_name("New Template")
ace_editor.type_input("- type: input") ace_editor.type_input("- type: input")
form_template_page.click_preview_button form_template_page.click_preview_button
expect(form_template_page).to have_preview_modal expect(form_template_page).to have_preview_modal
expect(form_template_page).to have_input_field("input") expect(form_template_page).to have_input_field("input")
end end
it "should render all the input field types in the preview" do it "should render all the input field types in the preview" do
visit("/admin/customize/form-templates/new") form_template_page.visit_new
form_template_page.type_in_template_name("New Template") form_template_page.type_in_template_name("New Template")
ace_editor.type_input( ace_editor.type_input(
"- type: input\n- type: textarea\n- type: checkbox\n- type: dropdown\n- type: upload\n- type: multi-select", "- type: input\n- type: textarea\n- type: checkbox\n- type: dropdown\n- type: upload\n- type: multi-select",

View File

@ -3,6 +3,16 @@
module PageObjects module PageObjects
module Pages module Pages
class FormTemplate < PageObjects::Pages::Base class FormTemplate < PageObjects::Pages::Base
def visit
page.visit("/admin/customize/form-templates")
self
end
def visit_new
page.visit("/admin/customize/form-templates/new")
self
end
# Form Template Index # Form Template Index
def has_form_template_table? def has_form_template_table?
page.has_selector?("table.form-templates__table") page.has_selector?("table.form-templates__table")
@ -67,12 +77,12 @@ module PageObjects
find(".form-templates__form-name-input").value == name find(".form-templates__form-name-input").value == name
end end
def has_save_button_with_state?(state) def has_save_button_with_state?(disabled:)
find_button("Save", disabled: state) find_button("Save", disabled:)
end end
def has_preview_button_with_state?(state) def has_preview_button_with_state?(disabled:)
find_button("Preview", disabled: state) find_button("Preview", disabled:)
end end
end end
end end