discourse/spec/system/admin_users_list_spec.rb
Joffrey JAFFEUX b6aad28ccf
DEV: replace selenium driver with playwright (#31977)
This commit is replacing the system specs driver (selenium) by
Playwright: https://playwright.dev/

We are still using Capybara to write the specs but they will now be run
by Playwright. To achieve this we are using the non official ruby
driver: https://github.com/YusukeIwaki/capybara-playwright-driver

### Notable changes

- `CHROME_DEV_TOOLS` has been removed, it's not working well with
playwright use `pause_test` and inspect browser for now.

- `fill_in` is not generating key events in playwright, use `send_keys`
if you need this.

### New spec options

#### trace

Allows to capture a trace in a zip file which you can load at
https://trace.playwright.dev or locally through `npx playwright
show-trace /path/to/trace.zip`

_Example usage:_

```ruby
it "shows bar", trace: true do
  visit("/")

  find(".foo").click

  expect(page).to have_css(".bar")
end
```

#### video

Allows to capture a video of your spec.

_Example usage:_

```ruby
it "shows bar", video: true do
  visit("/")

  find(".foo").click

  expect(page).to have_css(".bar")
end
```

### New env variable

#### PLAYWRIGHT_SLOW_MO_MS

Allow to force playwright to wait DURATION (in ms) at each action.

_Example usage:_

```
PLAYWRIGHT_SLOW_MO_MS=1000 rspec foo_spec.rb
```

#### PLAYWRIGHT_HEADLESS

Allow to be in headless mode or not. Default will be headless.

_Example usage:_

```
PLAYWRIGHT_HEADLESS=0 rspec foo_spec.rb # will show the browser
```

### New helpers

#### with_logs

Allows to access the browser logs and check if something specific has
been logged.

_Example usage:_

```ruby
with_logs do |logger|
  # do something

  expect(logger.logs.map { |log| log[:message] }).to include("foo")
end
```

#### add_cookie

Allows to add a cookie on the browser session.

_Example usage:_

```ruby
add_cookie(name: "destination_url", value: "/new")
```

#### get_style

Get the property style value of an element.

_Example usage:_

```ruby
expect(get_style(find(".foo"), "height")).to eq("200px")
```

#### get_rgb_color

Get the rgb color of an element.

_Example usage:_

```ruby
expect(get_rgb_color(find("html"), "backgroundColor")).to eq("rgb(170, 51, 159)")
```
2025-05-06 10:44:14 +02:00

233 lines
8.3 KiB
Ruby

# frozen_string_literal: true
describe "Admin Users Page", type: :system do
fab!(:current_user) { Fabricate(:admin) }
fab!(:another_admin) { Fabricate(:admin) }
fab!(:user_1) { Fabricate(:user) }
fab!(:user_2) { Fabricate(:user) }
fab!(:user_3) { Fabricate(:user) }
let(:admin_users_page) { PageObjects::Pages::AdminUsers.new }
before { sign_in(current_user) }
it "show correct breadcrumbs" do
admin_users_page.visit
expect(admin_users_page).to have_correct_breadcrumbs
end
describe "bulk user delete" do
let(:confirmation_modal) { PageObjects::Modals::BulkUserDeleteConfirmation.new }
it "disables checkboxes for users that can't be deleted" do
admin_users_page.visit
admin_users_page.bulk_select_button.click
expect(admin_users_page.user_row(current_user.id).bulk_select_checkbox.disabled?).to eq(true)
expect(admin_users_page.user_row(another_admin.id).bulk_select_checkbox.disabled?).to eq(true)
expect(admin_users_page.user_row(user_1.id).bulk_select_checkbox.disabled?).to eq(false)
admin_users_page.user_row(another_admin.id).bulk_select_checkbox.hover
expect(PageObjects::Components::Tooltips.new("bulk-delete-unavailable-reason")).to be_present(
text: I18n.t("admin_js.admin.users.bulk_actions.admin_cant_be_deleted"),
)
end
it "has a button that toggles the bulk select checkboxes" do
admin_users_page.visit
expect(admin_users_page).to have_users([user_1.id, user_2.id, user_3.id])
expect(admin_users_page.user_row(user_1.id)).to have_no_bulk_select_checkbox
expect(admin_users_page.user_row(user_2.id)).to have_no_bulk_select_checkbox
expect(admin_users_page.user_row(user_3.id)).to have_no_bulk_select_checkbox
admin_users_page.bulk_select_button.click
expect(admin_users_page.user_row(user_1.id)).to have_bulk_select_checkbox
expect(admin_users_page.user_row(user_2.id)).to have_bulk_select_checkbox
expect(admin_users_page.user_row(user_3.id)).to have_bulk_select_checkbox
expect(admin_users_page).to have_no_bulk_actions_dropdown
admin_users_page.user_row(user_1.id).bulk_select_checkbox.click
expect(admin_users_page).to have_bulk_actions_dropdown
admin_users_page.user_row(user_2.id).bulk_select_checkbox.click
admin_users_page.bulk_actions_dropdown.expand
admin_users_page.bulk_actions_dropdown.option(".bulk-delete").click
expect(confirmation_modal).to be_open
expect(confirmation_modal).to have_confirm_button_disabled
confirmation_modal.fill_in_confirmation_phase(user_count: 3)
expect(confirmation_modal).to have_confirm_button_disabled
confirmation_modal.fill_in_confirmation_phase(user_count: 2)
expect(confirmation_modal).to have_confirm_button_enabled
confirmation_modal.confirm
expect(confirmation_modal).to have_successful_log_entry_for_user(
user: user_1,
position: 1,
total: 2,
)
expect(confirmation_modal).to have_successful_log_entry_for_user(
user: user_2,
position: 2,
total: 2,
)
expect(confirmation_modal).to have_no_error_log_entries
confirmation_modal.close
expect(admin_users_page).to have_no_users([user_1.id, user_2.id])
expect(User.where(id: [user_1.id, user_2.id]).count).to eq(0)
end
it "remembers selected users when the user list refreshes due to search" do
admin_users_page.visit
admin_users_page.bulk_select_button.click
admin_users_page.search_input.fill_in(with: user_1.username)
admin_users_page.user_row(user_1.id).bulk_select_checkbox.click
admin_users_page.search_input.fill_in(with: user_2.username)
admin_users_page.user_row(user_2.id).bulk_select_checkbox.click
admin_users_page.search_input.fill_in(with: "")
expect(admin_users_page).to have_users([user_1.id, user_2.id, user_3.id])
expect(admin_users_page.user_row(user_1.id).bulk_select_checkbox).to be_checked
expect(admin_users_page.user_row(user_2.id).bulk_select_checkbox).to be_checked
expect(admin_users_page.user_row(user_3.id).bulk_select_checkbox).not_to be_checked
admin_users_page.bulk_actions_dropdown.expand
admin_users_page.bulk_actions_dropdown.option(".bulk-delete").click
expect(confirmation_modal).to be_open
confirmation_modal.fill_in_confirmation_phase(user_count: 2)
confirmation_modal.confirm
expect(confirmation_modal).to have_content("Starting bulk delete…")
expect(confirmation_modal).to have_successful_log_entry_for_user(
user: user_1,
position: 1,
total: 2,
)
expect(confirmation_modal).to have_successful_log_entry_for_user(
user: user_2,
position: 2,
total: 2,
)
confirmation_modal.close
expect(admin_users_page).to have_no_users([user_1.id, user_2.id])
expect(User.where(id: [user_1.id, user_2.id]).count).to eq(0)
end
it "displays an error message if bulk delete fails" do
admin_users_page.visit
admin_users_page.bulk_select_button.click
admin_users_page.user_row(user_1.id).bulk_select_checkbox.click
admin_users_page.bulk_actions_dropdown.expand
admin_users_page.bulk_actions_dropdown.option(".bulk-delete").click
confirmation_modal.fill_in_confirmation_phase(user_count: 1)
user_1.update!(admin: true)
confirmation_modal.confirm
expect(confirmation_modal).to have_error_log_entry(
I18n.t("js.generic_error_with_reason", error: I18n.t("user.cannot_bulk_delete")),
)
confirmation_modal.close
expect(admin_users_page).to have_users([user_1.id])
end
it "has an option to block IPs and emails" do
user_1.update!(ip_address: IPAddr.new("44.22.11.33"))
admin_users_page.visit
admin_users_page.bulk_select_button.click
admin_users_page.user_row(user_1.id).bulk_select_checkbox.click
admin_users_page.bulk_actions_dropdown.expand
admin_users_page.bulk_actions_dropdown.option(".bulk-delete").click
confirmation_modal.fill_in_confirmation_phase(user_count: 1)
confirmation_modal.block_ip_and_email_checkbox.click
confirmation_modal.confirm
expect(confirmation_modal).to have_successful_log_entry_for_user(
user: user_1,
position: 1,
total: 1,
)
expect(
ScreenedIpAddress.exists?(
ip_address: user_1.ip_address,
action_type: ScreenedIpAddress.actions[:block],
),
).to be_truthy
expect(
ScreenedEmail.exists?(email: user_1.email, action_type: ScreenedEmail.actions[:block]),
).to be_truthy
end
end
context "when visiting an admin's page" do
it "shows list of active users" do
admin_users_page.visit
expect(admin_users_page).to have_active_tab("active")
expect(page).to have_css(".directory-table__cell.username")
expect(admin_users_page).to have_users(
[current_user.id, another_admin.id, user_1.id, user_2.id, user_3.id],
)
end
it "shows list of suspended users" do
admin_users_page.visit
admin_users_page.click_tab("suspended")
expect(admin_users_page).to have_active_tab("suspended")
expect(admin_users_page).to have_none_users
end
it "shows list of silenced users" do
admin_users_page.visit
user_1.update!(silenced_till: 1.day.from_now)
admin_users_page.click_tab("silenced")
expect(admin_users_page).to have_active_tab("silenced")
expect(page).to have_css(".users-list.silenced")
expect(admin_users_page).to have_users([user_1.id])
end
it "shows emails" do
admin_users_page.visit
expect(admin_users_page).to have_no_emails
admin_users_page.click_show_emails
expect(admin_users_page).to have_emails
end
it "redirects to groups page" do
admin_users_page.visit
admin_users_page.click_tab("groups")
expect(page).to have_current_path("/g")
end
it "redirect to invites page" do
admin_users_page.visit
admin_users_page.click_send_invites
expect(page).to have_current_path("/u/#{current_user.username}/invited/pending")
end
it "allows to export users" do
admin_users_page.visit
admin_users_page.click_export
expect(page).to have_css(".dialog-body")
expect(page).to have_content(I18n.t("admin_js.admin.export_csv.success"))
end
end
end