0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 04:02:30 +08:00
discourse/spec/system/permanently_delete_spec.rb
Régis Hanol 28dae66fb1
UX: Migrate permanently-delete confirmation to DModal (#39896)
The "Permanently delete" confirmation was rendered through the legacy
dialog service, which hard-coded `width: 25vw` on the container. On
narrow mobile viewports (e.g. Edge at ~320px) that collapsed to ~80px,
clipping the modal and rendering the danger button unusable.

Rebuild the confirmation as a proper DModal so it picks up responsive
sizing, mobile keyboard handling, and footer wrapping for free.

- Add `components/modal/permanently-delete-confirm.gjs` with the
type-to-confirm input, btn-danger confirm, cancel, and the easter egg.
- Update the two call sites (`controllers/topic.js`,
`components/modal/history.gjs`) to invoke it via `modal.show(...)`
instead of `dialog.confirm(...)`, and delete the now-unused
`dialog-messages/permanently-delete-confirm.gjs`.
- Move the related styles to `.permanently-delete-confirm-modal` in
modal.scss, drop the 25vw width override, and allow the long danger
label to wrap so it no longer overflows on small screens.
- Replace the dialog-holder coverage with a dedicated
`PermanentlyDeleteConfirm` page object and route the system specs
through it.

https://meta.discourse.org/t/402663

**BEFORE**

<img width="402" height="690" alt="2026-05-11 @ 20 05 10"
src="https://github.com/user-attachments/assets/fb9dbfa7-4070-4557-87ea-0c73dc2be728"
/>

**AFTER**

<img width="410" height="693" alt="2026-05-11 @ 20 04 03"
src="https://github.com/user-attachments/assets/ab975c45-d4aa-43e5-80dc-67578da2f25d"
/>
2026-05-12 11:42:52 +02:00

121 lines
3.7 KiB
Ruby
Vendored

# frozen_string_literal: true
describe "Permanently delete" do
fab!(:admin)
fab!(:other_admin, :admin)
fab!(:topic)
fab!(:post) { Fabricate(:post, topic:) }
let(:topic_page) { PageObjects::Pages::Topic.new }
let(:dialog) { PageObjects::Components::Dialog.new }
let(:confirm_modal) { PageObjects::Modals::PermanentlyDeleteConfirm.new }
let(:confirmation_phrase) { I18n.t("js.post.controls.permanently_delete_confirm_phrase") }
before { SiteSetting.can_permanently_delete = true }
context "when permanently deleting a post" do
before do
PostDestroyer.new(other_admin, post).destroy
sign_in(admin)
topic_page.visit_topic(topic)
expect(topic_page).to have_deleted_post(post)
end
it "permanently deletes the post after confirmation" do
topic_page.permanently_delete_post(post)
confirm_modal.fill_in_confirmation_phrase(confirmation_phrase)
confirm_modal.click_danger
expect(page).to have_no_css("#post_#{post.post_number}")
expect(Post.unscoped.exists?(post.id)).to eq(false)
end
it "does not delete the post when cancelling" do
topic_page.permanently_delete_post(post)
confirm_modal.cancel
expect(confirm_modal).to be_closed
expect(topic_page).to have_deleted_post(post)
expect(Post.unscoped.exists?(post.id)).to eq(true)
end
end
context "when the same admin tries to permanently delete too soon" do
before do
PostDestroyer.new(admin, post).destroy
sign_in(admin)
topic_page.visit_topic(topic)
expect(topic_page).to have_deleted_post(post)
end
it "shows a cooldown message instead of the confirmation dialog" do
topic_page.permanently_delete_post(post)
expect(dialog).to be_open
expect(dialog).to have_content("before permanently deleting this post")
dialog.click_ok
expect(Post.with_deleted.exists?(post.id)).to eq(true)
end
end
context "when permanently deleting a topic via first post" do
fab!(:first_post) { topic.first_post }
before do
PostDestroyer.new(other_admin, post).destroy
PostDestroyer.new(other_admin, first_post).destroy
sign_in(admin)
visit(topic.url)
end
it "permanently deletes the topic after confirmation" do
topic_page.permanently_delete_post(first_post)
confirm_modal.fill_in_confirmation_phrase(confirmation_phrase)
confirm_modal.click_danger
expect(page).to have_current_path("/")
expect(Topic.unscoped.exists?(topic.id)).to eq(false)
end
end
context "when permanently deleting post revisions" do
fab!(:post_with_revisions) { Fabricate(:post, topic:, user: admin, version: 2) }
fab!(:revision) do
Fabricate(
:post_revision,
post: post_with_revisions,
user: admin,
number: 2,
modifications: {
"raw" => %w[original edited],
},
)
end
let(:post_history_modal) { PageObjects::Modals::PostHistory.new }
before do
sign_in(admin)
topic_page.visit_topic(topic)
end
it "permanently deletes revisions after confirmation" do
revision_id = revision.id
topic_page.open_post_history(post_with_revisions)
expect(post_history_modal).to be_open
post_history_modal.hide_revision
expect(post_history_modal).to have_destroy_revisions_button
post_history_modal.destroy_revisions
expect(confirm_modal).to be_open
confirm_modal.fill_in_confirmation_phrase(confirmation_phrase)
confirm_modal.click_danger
expect(page).to have_no_css("#post_#{post_with_revisions.post_number} .post-info.edits")
expect(PostRevision.exists?(revision_id)).to eq(false)
end
end
end