discourse/plugins/poll/spec/lib/pretty_text_spec.rb
Sam 9e241e82e9
DEV: use HTML5 version of loofah (#21522)
https://meta.discourse.org/t/markdown-preview-and-result-differ/263878

The result of this markdown had different results in the composer preview and the post. This is solved by updating Loofah to the latest version and using html5 fragments like our user had reported. While the change was only needed in cooked_post_processor.rb for this fix, other areas also had to be updated due to various side effects.
2023-06-20 09:49:22 +08:00

217 lines
5.9 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
RSpec.describe PrettyText do
def n(html)
html.strip
end
it "supports multi choice polls" do
cooked = PrettyText.cook <<~MD
[poll type=multiple min=1 max=3 public=true]
* option 1
* option 2
* option 3
[/poll]
MD
expect(cooked).to include('class="poll"')
expect(cooked).to include('data-poll-status="open"')
expect(cooked).to include('data-poll-name="poll"')
expect(cooked).to include('data-poll-type="multiple"')
expect(cooked).to include('data-poll-min="1"')
expect(cooked).to include('data-poll-max="3"')
expect(cooked).to include('data-poll-public="true"')
end
it "can dynamically generate a poll" do
cooked = PrettyText.cook <<~MD
[poll type=number min=1 max=20 step=1]
[/poll]
MD
expect(cooked.scan("<li").length).to eq(20)
end
it "can properly bake 2 polls" do
md = <<~MD
this is a test
- i am a list
[poll]
1. test 1
2. test 2
[/poll]
[poll name=poll2]
1. test 1
2. test 2
[/poll]
MD
cooked = PrettyText.cook(md)
expect(cooked.scan('class="poll"').length).to eq(2)
end
it "does not break poll options when going from loose to tight" do
md = <<~MD
[poll type=multiple]
1. test 1 :) <b>test</b>
2. test 2
[/poll]
MD
tight_cooked = PrettyText.cook(md)
md = <<~MD
[poll type=multiple]
1. test 1 :) <b>test</b>
2. test 2
[/poll]
MD
loose_cooked = PrettyText.cook(md)
tight_hashes = tight_cooked.scan(/data-poll-option-id=['"]([^'"]+)/)
loose_hashes = loose_cooked.scan(/data-poll-option-id=['"]([^'"]+)/)
expect(tight_hashes).to eq(loose_hashes)
end
it "can correctly cook polls" do
md = <<~MD
[poll type=multiple]
1. test 1 :) <b>test</b>
2. test 2
[/poll]
MD
cooked = PrettyText.cook md
expected = <<~HTML
<div class="poll" data-poll-status="open" data-poll-type="multiple" data-poll-name="poll">
<div>
<div class="poll-container"><ol>
<li data-poll-option-id="b6475cbf6acb8676b20c60582cfc487a">test 1 <img src="/images/emoji/twitter/slight_smile.png?v=#{Emoji::EMOJI_VERSION}" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> <b>test</b></li>
<li data-poll-option-id="7158af352698eb1443d709818df097d4">test 2</li>
</ol>
</div>
<div class="poll-info">
<p>
<span class="info-number">0</span>
<span class="info-label">voters</span>
</p>
</div>
</div>
</div>
HTML
# note, hashes should remain stable even if emoji changes cause text content is hashed
expect(n cooked).to eq(n expected)
end
it "can onebox posts" do
post = Fabricate(:post, raw: <<~MD)
A post with a poll
[poll type=regular]
* Hello
* World
[/poll]
MD
onebox = Oneboxer.onebox_raw(post.full_url, user_id: Fabricate(:user).id)
doc = Nokogiri.HTML5(onebox[:preview])
expect(onebox[:preview]).to include("A post with a poll")
expect(onebox[:preview]).to include("<a href=\"#{post.url}\">poll</a>")
end
it "can reduce excerpts" do
post = Fabricate(:post, raw: <<~MD)
A post with a poll
[poll type=regular]
* Hello
* World
[/poll]
MD
excerpt = PrettyText.excerpt(post.cooked, SiteSetting.post_onebox_maxlength, post: post)
expect(excerpt).to eq("A post with a poll \n<a href=\"#{post.url}\">poll</a>")
excerpt = PrettyText.excerpt(post.cooked, SiteSetting.post_onebox_maxlength)
expect(excerpt).to eq("A post with a poll \npoll")
end
it "supports the title attribute" do
cooked = PrettyText.cook <<~MD
[poll]
# What's your favorite *berry*? :wink: https://google.com/
* Strawberry
* Raspberry
* Blueberry
[/poll]
MD
expect(cooked).to include(
"<div class=\"poll-title\">Whats your favorite <em>berry</em>? <img src=\"/images/emoji/twitter/wink.png?v=#{Emoji::EMOJI_VERSION}\" title=\":wink:\" class=\"emoji\" alt=\":wink:\" loading=\"lazy\" width=\"20\" height=\"20\"> <a href=\"https://google.com/\" rel=\"noopener nofollow ugc\">https://google.com/</a></div>",
)
end
it "does not break when there are headings before/after a poll with a title" do
cooked = PrettyText.cook <<~MD
# Pre-heading
[poll]
# What's your favorite *berry*? :wink: https://google.com/
* Strawberry
* Raspberry
* Blueberry
[/poll]
# Post-heading
MD
expect(cooked).to include(
"<div class=\"poll-title\">Whats your favorite <em>berry</em>? <img src=\"/images/emoji/twitter/wink.png?v=#{Emoji::EMOJI_VERSION}\" title=\":wink:\" class=\"emoji\" alt=\":wink:\" loading=\"lazy\" width=\"20\" height=\"20\"> <a href=\"https://google.com/\" rel=\"noopener nofollow ugc\">https://google.com/</a></div>",
)
expect(cooked).to include(
"<h1><a name=\"pre-heading-1\" class=\"anchor\" href=\"#pre-heading-1\"></a>Pre-heading</h1>",
)
expect(cooked).to include(
"<h1><a name=\"post-heading-2\" class=\"anchor\" href=\"#post-heading-2\"></a>Post-heading</h1>",
)
end
it "does not break when there are headings before/after a poll without a title" do
cooked = PrettyText.cook <<~MD
# Pre-heading
[poll]
* Strawberry
* Raspberry
* Blueberry
[/poll]
# Post-heading
MD
expect(cooked).to_not include('<div class="poll-title">')
expect(cooked).to include(<<~HTML)
<div class="poll" data-poll-status="open" data-poll-name="poll">
HTML
expect(cooked).to include(
"<h1><a name=\"pre-heading-1\" class=\"anchor\" href=\"#pre-heading-1\"></a>Pre-heading</h1>",
)
expect(cooked).to include(
"<h1><a name=\"post-heading-2\" class=\"anchor\" href=\"#post-heading-2\"></a>Post-heading</h1>",
)
end
end