mirror of
https://github.com/discourse/discourse.git
synced 2026-03-04 01:15:08 +08:00
Reported here: https://meta.discourse.org/t/understanding-opacity-in-hidden-revisions/397345 We're currently using `nth-of-type` selectors to reduce the opacity of hidden revisions in the history modal... but these can be fragile and are prone to regression if we change anything in the DOM. Adding class names provides more predictable targets — this adds `--previous` and `--current` and fixes the misplaced style. Before (title of current revision also has reduced opacity) <img width="2212" height="710" alt="image" src="https://github.com/user-attachments/assets/5cd746ca-3bc8-4c3f-b6a6-aac525d3e0a0" /> After (only the hidden revision has the opacity reduced) <img width="2292" height="830" alt="image" src="https://github.com/user-attachments/assets/c5eb1731-2d3c-4d5c-9905-c8c8b9b7a33d" />
196 lines
9.2 KiB
Ruby
196 lines
9.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "discourse_diff"
|
|
|
|
RSpec.describe DiscourseDiff do
|
|
describe "inline_html" do
|
|
it "does not lead to XSS" do
|
|
a = "<test>start</test>"
|
|
b = "<test>end</test>"
|
|
prev = "<div>#{CGI.escapeHTML(a)}</div>"
|
|
cur = "<div>#{CGI.escapeHTML(b)}</div>"
|
|
|
|
diff = DiscourseDiff.new(prev, cur)
|
|
expect(diff.inline_html).not_to match(%r{</?test>})
|
|
expect(diff.side_by_side_html).not_to match(%r{</?test>})
|
|
end
|
|
|
|
it "returns an empty div when no content is diffed" do
|
|
expect(DiscourseDiff.new("", "").inline_html).to eq("<div class=\"inline-diff\"></div>")
|
|
end
|
|
|
|
it "returns the diffed content when there is no difference" do
|
|
before = after = "<p>this is a paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).inline_html).to eq(
|
|
"<div class=\"inline-diff\"><p>this is a paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds <ins> tags around added text" do
|
|
before = "<p>this is a paragraph</p>"
|
|
after = "<p>this is a great paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).inline_html).to eq(
|
|
"<div class=\"inline-diff\"><p>this is a <ins>great </ins>paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds <del> tags around removed text" do
|
|
before = "<p>this is a great paragraph</p>"
|
|
after = "<p>this is a paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).inline_html).to eq(
|
|
"<div class=\"inline-diff\"><p>this is a <del>great </del>paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds .diff-ins class when a paragraph is added" do
|
|
before = "<p>this is the first paragraph</p>"
|
|
after = "<p>this is the first paragraph</p><p>this is the second paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).inline_html).to eq(
|
|
"<div class=\"inline-diff\"><p>this is the first paragraph</p><p class=\"diff-ins\">this is the second paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds .diff-del class when a paragraph is removed" do
|
|
before = "<p>this is the first paragraph</p><p>this is the second paragraph</p>"
|
|
after = "<p>this is the second paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).inline_html).to eq(
|
|
"<div class=\"inline-diff\"><p class=\"diff-del\">this is the first paragraph</p><p>this is the second paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "does not break diff on character references" do
|
|
before = "<p>'</p>"
|
|
after = "<p></p>"
|
|
expect(DiscourseDiff.new(before, after).inline_html).to eq(
|
|
"<div class=\"inline-diff\"><p><del>'</del></p></div>",
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "side_by_side_html" do
|
|
it "returns two empty divs when no content is diffed" do
|
|
expect(DiscourseDiff.new("", "").side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"></div><div class=\"revision-content --current\"></div>",
|
|
)
|
|
end
|
|
|
|
it "returns the diffed content on both sides when there is no difference" do
|
|
before = after = "<p>this is a paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"><p>this is a paragraph</p></div><div class=\"revision-content --current\"><p>this is a paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds <ins> tags around added text on the right div" do
|
|
before = "<p>this is a paragraph</p>"
|
|
after = "<p>this is a great paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"><p>this is a paragraph</p></div><div class=\"revision-content --current\"><p>this is a <ins>great </ins>paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds <ins> and <del> tags on consecutive paragraphs" do
|
|
before = "<p>this is one paragraph</p><p>here is yet another</p>"
|
|
after = "<p>this is one great paragraph</p><p>here is another</p>"
|
|
got = DiscourseDiff.new(before, after).side_by_side_html
|
|
expect(got).to eq(
|
|
"<div class=\"revision-content --previous\"><p>this is one paragraph</p><p>here is <del>yet </del>another</p></div><div class=\"revision-content --current\"><p>this is one <ins>great </ins>paragraph</p><p>here is another</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds <del> tags around removed text on the left div" do
|
|
before = "<p>this is a great paragraph</p>"
|
|
after = "<p>this is a paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"><p>this is a <del>great </del>paragraph</p></div><div class=\"revision-content --current\"><p>this is a paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds .diff-ins class when a paragraph is added" do
|
|
before = "<p>this is the first paragraph</p>"
|
|
after = "<p>this is the first paragraph</p><p>this is the second paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"><p>this is the first paragraph</p></div><div class=\"revision-content --current\"><p>this is the first paragraph</p><p class=\"diff-ins\">this is the second paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "adds .diff-del class when a paragraph is removed" do
|
|
before = "<p>this is the first paragraph</p><p>this is the second paragraph</p>"
|
|
after = "<p>this is the second paragraph</p>"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"><p class=\"diff-del\">this is the first paragraph</p><p>this is the second paragraph</p></div><div class=\"revision-content --current\"><p>this is the second paragraph</p></div>",
|
|
)
|
|
end
|
|
|
|
it "does not break diff on character references" do
|
|
before = "<p>'</p>"
|
|
after = "<p></p>"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"><p><del>'</del></p></div><div class=\"revision-content --current\"><p></p></div>",
|
|
)
|
|
end
|
|
|
|
it "escapes attribute values" do
|
|
before = "<p data-attr='Some \"quoted\" string'></p>"
|
|
after = "<p data-attr='Some \"quoted\" string'></p>"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_html).to eq(
|
|
"<div class=\"revision-content --previous\"><p data-attr=\"Some "quoted" string\"></p></div><div class=\"revision-content --current\"><p data-attr=\"Some "quoted" string\"></p></div>",
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "side_by_side_markdown" do
|
|
it "returns an empty table when no content is diffed" do
|
|
expect(DiscourseDiff.new("", "").side_by_side_markdown).to eq(
|
|
"<table class=\"markdown\"></table>",
|
|
)
|
|
end
|
|
|
|
it "properly escape html tags" do
|
|
before = ""
|
|
after = "<img src=\"//domain.com/image.png>\""
|
|
expect(DiscourseDiff.new(before, after).side_by_side_markdown).to eq(
|
|
"<table class=\"markdown\"><tr><td class=\"--previous\"></td><td class=\"--current diff-ins\"><img src="//domain.com/image.png>"</td></tr></table>",
|
|
)
|
|
end
|
|
|
|
it "returns the diffed content on both columns when there is no difference" do
|
|
before = after = "this is a paragraph"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_markdown).to eq(
|
|
"<table class=\"markdown\"><tr><td class=\"--previous\">this is a paragraph</td><td class=\"--current\">this is a paragraph</td></tr></table>",
|
|
)
|
|
end
|
|
|
|
it "adds <ins> tags around added text on the second column" do
|
|
before = "this is a paragraph"
|
|
after = "this is a great paragraph"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_markdown).to eq(
|
|
"<table class=\"markdown\"><tr><td class=\"--previous diff-del\">this is a paragraph</td><td class=\"--current diff-ins\">this is a <ins>great </ins>paragraph</td></tr></table>",
|
|
)
|
|
end
|
|
|
|
it "adds <del> tags around removed text on the first column" do
|
|
before = "this is a great paragraph"
|
|
after = "this is a paragraph"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_markdown).to eq(
|
|
"<table class=\"markdown\"><tr><td class=\"--previous diff-del\">this is a <del>great </del>paragraph</td><td class=\"--current diff-ins\">this is a paragraph</td></tr></table>",
|
|
)
|
|
end
|
|
|
|
it "adds .diff-ins class when a paragraph is added" do
|
|
before = "this is the first paragraph"
|
|
after = "this is the first paragraph\nthis is the second paragraph"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_markdown).to eq(
|
|
"<table class=\"markdown\"><tr><td class=\"--previous diff-del\">this is the first paragraph</td><td class=\"--current diff-ins\">this is the first paragraph<ins>\nthis is the second paragraph</ins></td></tr></table>",
|
|
)
|
|
end
|
|
|
|
it "adds .diff-del class when a paragraph is removed" do
|
|
before = "this is the first paragraph\nthis is the second paragraph"
|
|
after = "this is the second paragraph"
|
|
expect(DiscourseDiff.new(before, after).side_by_side_markdown).to eq(
|
|
"<table class=\"markdown\"><tr><td class=\"--previous diff-del\">this is the first paragraph\n</td><td class=\"--current\"></td></tr><tr><td class=\"--previous\">this is the second paragraph</td><td class=\"--current\">this is the second paragraph</td></tr></table>",
|
|
)
|
|
end
|
|
end
|
|
end
|