mirror of
https://github.com/discourse/discourse.git
synced 2024-12-05 09:56:30 +08:00
babbebfb35
Adds an optional title attribute to polls. The rationale for this addition is that polls themselves didn't contain context/question and relied on post body to explain them. That context wasn't always obvious (e.g. when there are multiple polls in a single post) or available (e.g. when you display the poll breakdown - you see the answers, but not the question) As a side note, here's a word on how the poll plugin works: > We have a markdown poll renderer, which we use in the builder UI and the composer preview, but… when you submit a post, raw markdown is cooked into html (twice), then we extract data from the generated html and save it to the database. When it's render time, we first display the cooked html poll, and then extract some data from that html, get the data from the post's JSON (and identify that poll using the extracted html stuff) to then render the poll using widgets and the JSON data.
173 lines
4.2 KiB
Ruby
173 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
require 'rails_helper'
|
||
|
||
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:"> <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(<<~HTML)
|
||
<div class="poll-title">What’s your favorite <em>berry</em>? <img src="/images/emoji/twitter/wink.png?v=9" title=":wink:" class="emoji" alt=":wink:"> <a href="https://google.com/" rel="noopener nofollow ugc">https://google.com/</a>
|
||
</div>
|
||
HTML
|
||
end
|
||
end
|