0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-06 04:48:33 +08:00
discourse/spec/lib/ical_encoder_spec.rb
Bannon Tanner f5203dfcca
FIX: Preserve URI delimiters in ICS URL properties, removing TEXT escaping (#42107)
## Summary

Correctly emit `URL` properties in ICS export without RFC 5545 TEXT
escaping by introducing `IcalEncoder.encode_uri`, which decodes HTML
entities, strips CR/LF characters, and leaves valid URI delimiters such
as commas and semicolons intact. This change is applied to both the
Discourse Events calendar feed and the user bookmarks ICS feed; all
textual properties (`SUMMARY`, `LOCATION`, `DESCRIPTION`) continue to
use the existing TEXT encoder.

## Source

- Patch Triage: https://patch.discourse.org/patch-triage/1547

Co-authored-by: discourse-patch-triage
<272280883+discourse-patch-triage[bot]@users.noreply.github.com>
2026-07-28 14:53:16 -05:00

78 lines
2.6 KiB
Ruby
Vendored

# frozen_string_literal: true
RSpec.describe IcalEncoder do
describe ".encode" do
it "returns empty string for nil" do
expect(described_class.encode(nil)).to eq("")
end
it "returns empty string for blank string" do
expect(described_class.encode("")).to eq("")
end
it "passes through plain text" do
expect(described_class.encode("Hello World")).to eq("Hello World")
end
it "strips HTML tags" do
expect(described_class.encode("<b>Bold</b> and <i>italic</i>")).to eq("Bold and italic")
end
it "decodes HTML entities" do
expect(described_class.encode("Tom &amp; Jerry")).to eq("Tom & Jerry")
expect(described_class.encode("1 &lt; 2 &gt; 0")).to eq("1 < 2 > 0")
expect(described_class.encode("&quot;quoted&quot;")).to eq('"quoted"')
end
it "strips HTML tags then decodes entities" do
expect(
described_class.encode("&lt;a href=&quot;https://example.com&quot;&gt;link&lt;/a&gt;"),
).to eq('<a href="https://example.com">link</a>')
end
it "escapes commas" do
expect(described_class.encode("New York, NY")).to eq("New York\\, NY")
end
it "escapes semicolons" do
expect(described_class.encode("one; two")).to eq("one\\; two")
end
it "escapes backslashes" do
expect(described_class.encode("path\\to\\file")).to eq("path\\\\to\\\\file")
end
it "escapes newlines" do
expect(described_class.encode("line one\nline two")).to eq("line one\\nline two")
expect(described_class.encode("line one\r\nline two")).to eq("line one\\nline two")
end
it "returns html_safe strings to prevent double-escaping in ERB templates" do
expect(described_class.encode("Tom & Jerry")).to be_html_safe
end
it "handles complex HTML content from Discourse posts" do
html =
'&lt;a class=&quot;lightbox&quot; href=&quot;https://example.com/image.jpg&quot;&gt;[Image]&lt;/a&gt; \nSome text with &amp; special chars'
result = described_class.encode(html)
expect(result).not_to include("&lt;")
expect(result).not_to include("&amp;")
expect(result).not_to include("&quot;")
expect(result).to include("& special chars")
end
end
describe ".encode_uri" do
it "preserves URI delimiters and removes newlines" do
result =
described_class.encode_uri(
"https://example.com/events?tags=one,two;sort=asc&amp;name=Tom\r\nATTACH:https://bad.example",
)
expect(result).to eq(
"https://example.com/events?tags=one,two;sort=asc&name=TomATTACH:https://bad.example",
)
expect(result).to be_html_safe
end
end
end