DEV: Speed up "having working core features" shared example by ~30% (#32666)

Doing a full page load in system test is expensive and takes about 1
second on average. Since this shared example is being run across 70
official
plugins, the additional time to execute these full page loads adds up.

Therefore, we are trading off some readability here for CI runtime.

Before:

```
Randomized with seed 7202
..................

Finished in 21.26 seconds (files took 1.72 seconds to load)
18 examples, 0 failures
```

After:

```
Randomized with seed 7202
........

Finished in 14.28 seconds (files took 1.74 seconds to load)
8 examples, 0 failures
```
This commit is contained in:
Alan Guo Xiang Tan 2025-05-10 06:56:12 +08:00 committed by GitHub
parent fa03d7719f
commit eff31e0d42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 78 additions and 65 deletions

View File

@ -7,6 +7,8 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
fab!(:active_user) { Fabricate(:active_user, password: "secure_password") }
let(:composer) { PageObjects::Components::Composer.new }
let(:topic_list) { PageObjects::Components::TopicList.new }
let(:topic_page) { PageObjects::Pages::Topic.new }
if skip_examples.exclude?(:login)
describe "Login" do
@ -16,16 +18,15 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
it "logs in" do
visit("/")
expect(page).to have_css("header .login-button", visible: true)
login_form.open
login_form.fill_username(active_user.username)
login_form.fill_password("secure_password")
login_form.click_login
expect(page).to have_css(".current-user", visible: true)
end
it "displays a login button in the header" do
visit("/")
expect(page).to have_css("header .login-button", visible: true)
expect(page).to have_css(".current-user", visible: true)
end
end
end
@ -34,18 +35,17 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
describe "Topics" do
if skip_examples.exclude?(:"topics:read")
context "with an anonymous user" do
before { visit "/" }
it "correctly allows a user to interact with topics" do
visit "/"
it "lists latest topics" do
# List latest topics
expect(page).to have_css(".topic-list-item", count: 4)
end
it "lists topics for a category" do
# List topics for a category
within("#sidebar-section-content-categories") { click_on("General") }
expect(page).to have_css(".topic-list-item", count: 3)
end
it "displays a specific topic" do
# Display a specific topic
click_on(topics.first.title)
expect(page).to have_content(topics.first.title)
expect(page).to have_content(topics.first.first_post.raw)
@ -59,27 +59,26 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
visit "/"
end
if skip_examples.exclude?(:"topics:read")
it "lists latest topics" do
it "correctly allows a user to interact with topics" do
if skip_examples.exclude?(:"topics:read")
# List latest topics
expect(page).to have_css(".topic-list-item", count: 4)
end
it "lists topics for a category" do
# List topics for a category
within("#sidebar-section-content-categories") { click_on("General") }
expect(page).to have_css(".topic-list-item", count: 3)
end
it "displays a specific topic" do
click_on(topics.first.title)
# Display a specific topic
topic_list.visit_topic(topics.first)
expect(page).to have_content(topics.first.title)
expect(page).to have_content(topics.first.first_post.raw)
end
end
if skip_examples.exclude?(:"topics:reply")
it "replies in a topic" do
click_on(topics.first.title)
expect(page).to have_content(topics.first.first_post.raw)
if skip_examples.exclude?(:"topics:reply")
# Reply to a topic
within("#sidebar-section-content-categories") { click_on("General") }
expect(page).to have_css(".topic-list-item", count: 3)
topic_list.visit_topic(topics.first)
within(".actions") { click_button("Reply") }
composer.focus
send_keys("This is a long enough reply.")
@ -87,17 +86,24 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
within(".save-or-cancel") { click_button("Reply") }
expect(page).to have_content("This is a long enough reply.")
end
end
if skip_examples.exclude?(:"topics:create")
it "creates a new topic" do
if skip_examples.exclude?(:"topics:create")
# Creates a new topic
find("#site-logo", visible: true).click
find("#create-topic", visible: true).click
composer.fill_title("This is a new topic")
composer.fill_content("This is a long enough sentence.")
expect(page).to have_css(".d-editor-preview p", visible: true)
within(".save-or-cancel") { click_button("Create Topic") }
expect(page).to have_content("This is a new topic")
expect(page).to have_content("This is a long enough sentence.")
expect(topic_page).to have_title("This is a new topic")
expect(topic_page).to have_post_content(
post_number: 1,
content: "This is a long enough sentence.",
)
end
end
end
@ -136,15 +142,15 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
end
context "with a logged in user" do
before { sign_in(active_user) }
it "displays user profiles correctly" do
sign_in(active_user)
it "displays a users profile" do
# Another user's profile
visit("/u/#{user.username}/summary")
expect(page).to have_content(user.name)
expect(page).to have_content("Message")
end
it "displays the users own profile" do
# Own profile
visit("/u/#{active_user.username}/summary")
expect(page).to have_content(active_user.name)
expect(page).to have_content("Preferences")
@ -166,23 +172,24 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
after { SearchIndexer.disable }
context "with an anonymous user" do
if skip_examples.exclude?(:"search:quick_search")
it "searches using the quick search" do
visit("/")
search_page.click_search_icon
it "quick search and full page search works" do
visit("/")
if skip_examples.exclude?(:"search:quick_search")
search_page.expand_dropdown
expect(page).to have_css(".search-menu-container")
search_page.type_in_search_menu(topics.first.title)
search_page.click_search_menu_link
expect(search_page).to have_topic_title_for_first_search_result(topics.first.title)
end
end
if skip_examples.exclude?(:"search:full_page")
it "searches using the full page search" do
visit("/search")
search_page.type_in_search(topics.first.title)
search_page.click_search_button
if skip_examples.exclude?(:"search:full_page")
search_page
.expand_dropdown
.click_advanced_search_icon
.clear_search_input
.type_in_search(topics.first.title)
.click_search_button
expect(search_page).to have_search_result
end
@ -190,25 +197,27 @@ RSpec.shared_examples_for "having working core features" do |skip_examples: []|
end
context "with a logged in user" do
before { sign_in(active_user) }
before do
sign_in(active_user)
visit("/")
end
if skip_examples.exclude?(:"search:quick_search")
it "searches using the quick search" do
visit("/")
search_page.click_search_icon
it "quick search and full page search works" do
if skip_examples.exclude?(:"search:quick_search")
search_page.expand_dropdown
expect(page).to have_css(".search-menu-container")
search_page.type_in_search_menu(topics.first.title)
search_page.click_search_menu_link
expect(search_page).to have_topic_title_for_first_search_result(topics.first.title)
end
end
if skip_examples.exclude?(:"search:full_page")
it "searches using the full page search" do
visit("/search")
search_page.type_in_search(topics.first.title)
search_page.click_search_button
if skip_examples.exclude?(:"search:full_page")
search_page
.expand_dropdown
.click_advanced_search_icon
.clear_search_input
.type_in_search(topics.first.title)
.click_search_button
expect(search_page).to have_search_result
end

View File

@ -35,7 +35,7 @@ describe "Composer", type: :system do
op_post.reply
expect(composer).to be_opened
composer.fill_content("@")
composer.type_content("@")
expect(composer.mention_menu_autocomplete_username_list).to eq(
[op.username, second_reply_user.username], # must be first the topic owner
@ -47,7 +47,7 @@ describe "Composer", type: :system do
second_reply_post.reply
expect(composer).to be_opened
composer.fill_content("@")
composer.type_content("@")
expect(composer.mention_menu_autocomplete_username_list).to eq(
[second_reply_user.username, topic_user.username], # must be first the reply user
@ -66,7 +66,7 @@ describe "Composer", type: :system do
expect(composer).to be_opened
composer.fill_content(" @")
composer.type_content(" @")
expect(composer.mention_menu_autocomplete_username_list).to eq(
[second_reply_user.username, user.username, topic_user.username],

View File

@ -54,10 +54,7 @@ module PageObjects
end
def fill_content(content)
page.driver.with_playwright_page do |pw_page|
pw_page.locator("#{COMPOSER_ID} .d-editor .d-editor-input").press_sequentially(content)
end
find("#{COMPOSER_ID} .d-editor .d-editor-input").fill_in(with: content)
self
end

View File

@ -34,12 +34,19 @@ module PageObjects
find(".search-cta").click
end
def expand_dropdown
click_search_icon if !has_css?(".search-menu .search-menu-panel", wait: 0)
self
end
def click_search_icon
find(".d-header #search-button").click
self
end
def click_advanced_search_icon
find(".show-advanced-search").click
find(".d-header .show-advanced-search").click
self
end
def click_in_posts_by_user

View File

@ -43,8 +43,8 @@ module PageObjects
has_css?("h1 .fancy-title", text: text)
end
def has_post_content?(post)
post_by_number(post).has_content? post.raw
def has_post_content?(post_number:, content:)
find(post_by_number_selector(post_number)).has_content?(content)
end
def has_deleted_post?(post)