diff --git a/src/routes/_components/status/StatusPoll.html b/src/routes/_components/status/StatusPoll.html
index 1bfa0d83..4ab0943d 100644
--- a/src/routes/_components/status/StatusPoll.html
+++ b/src/routes/_components/status/StatusPoll.html
@@ -4,7 +4,7 @@
{#each options as option}
- {option.share}% {option.title}
+ {option.share}% {@html option.title}
{/each}
@@ -245,6 +245,8 @@
import { registerClickDelegate } from '../../_utils/delegate'
import { classname } from '../../_utils/classname'
import { getPoll, voteOnPoll } from '../../_actions/polls'
+ import escapeHtml from 'escape-html'
+ import { emojifyText } from '../../_utils/emojifyText'
const REFRESH_MIN_DELAY = 1000
@@ -284,10 +286,12 @@
computed: {
pollId: ({ originalStatus }) => originalStatus.poll.id,
poll: ({ originalStatus, $polls, pollId }) => $polls[pollId] || originalStatus.poll,
- options: ({ poll }) => poll.options.map(({ title, votes_count: votesCount }) => ({
- title,
- share: poll.votes_count ? Math.round(votesCount / poll.votes_count * 100) : 0
- })),
+ options: ({ poll, originalStatusEmojis, $autoplayGifs }) => (
+ poll.options.map(({ title, votes_count: votesCount }) => ({
+ title: emojifyText(escapeHtml(title), originalStatusEmojis, $autoplayGifs),
+ share: poll.votes_count ? Math.round(votesCount / poll.votes_count * 100) : 0
+ }))
+ ),
votesCount: ({ poll }) => poll.votes_count,
voted: ({ poll }) => poll.voted,
multiple: ({ poll }) => poll.multiple,
diff --git a/tests/spec/127-compose-polls.js b/tests/spec/127-compose-polls.js
index 92d80b69..57b9d45b 100644
--- a/tests/spec/127-compose-polls.js
+++ b/tests/spec/127-compose-polls.js
@@ -7,7 +7,13 @@ import {
getComposePollNthInput,
composePoll,
composePollMultipleChoice,
- composePollExpiry, composePollAddButton, getComposePollRemoveNthButton, postStatusButton, composeInput, sleep
+ composePollExpiry,
+ composePollAddButton,
+ getComposePollRemoveNthButton,
+ postStatusButton,
+ composeInput,
+ sleep,
+ getNthStatus
} from '../utils'
import { loginAsFoobar } from '../roles'
import { POLL_EXPIRY_DEFAULT } from '../../src/routes/_static/polls'
@@ -18,6 +24,7 @@ fixture`127-compose-polls.js`
test('Can add and remove poll', async t => {
await loginAsFoobar(t)
await t
+ .expect(getNthStatus(1).exists).ok()
.expect(composePoll.exists).notOk()
.expect(pollButton.getAttribute('aria-label')).eql('Add poll')
.click(pollButton)
@@ -36,6 +43,7 @@ test('Can add and remove poll', async t => {
test('Can add and remove poll options', async t => {
await loginAsFoobar(t)
await t
+ .expect(getNthStatus(1).exists).ok()
.expect(composePoll.exists).notOk()
.expect(pollButton.getAttribute('aria-label')).eql('Add poll')
.click(pollButton)
@@ -73,3 +81,22 @@ test('Can add and remove poll options', async t => {
.expect(getNthStatusPollResult(1, 4).exists).notOk()
.expect(getNthStatusPollVoteCount(1).innerText).eql('0 votes')
})
+
+test('Properly escapes HTML and emojos in polls', async t => {
+ await loginAsFoobar(t)
+ await t
+ .expect(getNthStatus(1).exists).ok()
+ .click(pollButton)
+ .expect(composePoll.exists).ok()
+ await sleep(1000)
+ await t
+ .typeText(composeInput, 'vote vote vote', { paste: true })
+ .typeText(getComposePollNthInput(1), '–', { paste: true })
+ .typeText(getComposePollNthInput(2), ':blobpeek:', { paste: true })
+ await sleep(1000)
+ await t
+ .click(postStatusButton)
+ .expect(getNthStatusPollResult(1, 1).innerText).contains('–')
+ .expect(getNthStatusPollResult(1, 2).find('img').exists).ok()
+ .expect(getNthStatusPollResult(1, 2).find('img').getAttribute('alt')).eql(':blobpeek:')
+})