Newer
Older
require 'rails_helper'
RSpec.describe Formatter do
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
let(:local_account) { Fabricate(:account, domain: nil, username: 'alice') }
let(:remote_account) { Fabricate(:account, domain: 'remote', username: 'bob', url: 'https://remote/') }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
shared_examples 'encode and link URLs' do
context 'matches a stand-alone medium URL' do
let(:text) { 'https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="https://hackernoon.com/the-power-to-build-communities-a-response-to-mark-zuckerberg-3f2cac9148a4"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a stand-alone google URL' do
let(:text) { 'http://google.com' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="http://google.com"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
end
context 'matches a stand-alone IDN URL' do
let(:text) { 'https://nic.みんな/' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="https://nic.みんな/"'
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has display URL' do
is_expected.to include '<span class="">nic.みんな/</span>'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a URL without trailing period' do
let(:text) { 'http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona. ' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="http://www.mcmansionhell.com/post/156408871451/50-states-of-mcmansion-hell-scottsdale-arizona"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a URL without closing paranthesis' do
let(:text) { '(http://google.com/)' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="http://google.com/"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a URL without exclamation point' do
let(:text) { 'http://www.google.com!' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="http://www.google.com"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a URL without single quote' do
let(:text) { "http://www.google.com'" }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="http://www.google.com"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a URL without angle brackets' do
let(:text) { 'http://www.google.com>' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="http://www.google.com"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a URL with a query string' do
let(:text) { 'https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink' }
it 'has valid URL' do
is_expected.to include 'href="https://www.ruby-toolbox.com/search?utf8=%E2%9C%93&q=autolink"'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'matches a URL with parenthesis in it' do
let(:text) { 'https://en.wikipedia.org/wiki/Diaspora_(software)' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has valid URL' do
is_expected.to include 'href="https://en.wikipedia.org/wiki/Diaspora_(software)"'
context 'matches a URL with Japanese path string' do
let(:text) { 'https://ja.wikipedia.org/wiki/日本' }
it 'has valid URL' do
is_expected.to include 'href="https://ja.wikipedia.org/wiki/日本"'
end
end
context 'matches a URL with Korean path string' do
let(:text) { 'https://ko.wikipedia.org/wiki/대한민국' }
it 'has valid URL' do
is_expected.to include 'href="https://ko.wikipedia.org/wiki/대한민국"'
end
end
context 'matches a URL with Simplified Chinese path string' do
let(:text) { 'https://baike.baidu.com/item/中华人民共和国' }
it 'has valid URL' do
is_expected.to include 'href="https://baike.baidu.com/item/中华人民共和国"'
end
end
context 'matches a URL with Traditional Chinese path string' do
let(:text) { 'https://zh.wikipedia.org/wiki/臺灣' }
it 'has valid URL' do
is_expected.to include 'href="https://zh.wikipedia.org/wiki/臺灣"'
context 'contains unsafe URL (XSS attack, visible part)' do
let(:text) { %q{http://example.com/b<del>b</del>} }
it 'has escaped HTML' do
is_expected.to include '<del>b</del>'
end
end
context 'contains unsafe URL (XSS attack, invisible part)' do
let(:text) { %q{http://example.com/blahblahblahblah/a<script>alert("Hello")</script>} }
it 'has escaped HTML' do
is_expected.to include '<script>alert("Hello")</script>'
end
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'contains HTML (script tag)' do
let(:text) { '<script>alert("Hello")</script>' }
it 'has escaped HTML' do
is_expected.to include '<p><script>alert("Hello")</script></p>'
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'contains HTML (XSS attack)' do
let(:text) { %q{<img src="javascript:alert('XSS');">} }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has escaped HTML' do
is_expected.to include '<p><img src="javascript:alert('XSS');"></p>'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'contains invalid URL' do
let(:text) { 'http://www\.google\.com' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has raw URL' do
is_expected.to eq '<p>http://www\.google\.com</p>'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'contains a hashtag' do
let(:text) { '#hashtag' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'has a link' do
is_expected.to include '/tags/hashtag" class="mention hashtag" rel="tag">#<span>hashtag</span></a>'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
describe '#format' do
subject { Formatter.instance.format(status) }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
context 'with local status' do
context 'with reblog' do
let(:reblog) { Fabricate(:status, account: local_account, text: 'Hello world', uri: nil) }
let(:status) { Fabricate(:status, reblog: reblog) }
it 'returns original status with credit to its author' do
is_expected.to include 'RT <span class="h-card"><a href="https://cb6e6126.ngrok.io/@alice" class="u-url mention">@<span>alice</span></a></span> Hello world'
end
end
context 'contains plain text' do
let(:status) { Fabricate(:status, text: 'text', uri: nil) }
it 'paragraphizes' do
is_expected.to eq '<p>text</p>'
end
end
context 'contains line feeds' do
let(:status) { Fabricate(:status, text: "line\nfeed", uri: nil) }
it 'removes line feeds' do
is_expected.not_to include "\n"
end
end
context 'contains linkable mentions' do
let(:status) { Fabricate(:status, mentions: [ Fabricate(:mention, account: local_account) ], text: '@alice') }
it 'links' do
is_expected.to include '<a href="https://cb6e6126.ngrok.io/@alice" class="u-url mention">@<span>alice</span></a></span>'
end
end
context 'contains unlinkable mentions' do
let(:status) { Fabricate(:status, text: '@alice', uri: nil) }
it 'does not link' do
is_expected.to include '@alice'
end
end
context do
subject do
status = Fabricate(:status, text: text, uri: nil)
Formatter.instance.format(status)
end
include_examples 'encode and link URLs'
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
context 'with custom_emojify option' do
let!(:emoji) { Fabricate(:custom_emoji) }
let(:status) { Fabricate(:status, account: local_account, text: text) }
subject { Formatter.instance.format(status, custom_emojify: true) }
context 'with emoji at the start' do
let(:text) { ':coolcat: Beep boop' }
it 'converts shortcode to image tag' do
is_expected.to match(/<p><img draggable="false" class="emojione" alt=":coolcat:"/)
end
end
context 'with emoji in the middle' do
let(:text) { 'Beep :coolcat: boop' }
it 'converts shortcode to image tag' do
is_expected.to match(/Beep <img draggable="false" class="emojione" alt=":coolcat:"/)
end
end
context 'with concatenated emoji' do
let(:text) { ':coolcat::coolcat:' }
it 'does not touch the shortcodes' do
is_expected.to match(/:coolcat::coolcat:/)
end
end
context 'with emoji at the end' do
let(:text) { 'Beep boop :coolcat:' }
it 'converts shortcode to image tag' do
is_expected.to match(/boop <img draggable="false" class="emojione" alt=":coolcat:"/)
end
end
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'with remote status' do
Eugen Rochko
a validé
let(:status) { Fabricate(:status, account: remote_account, text: 'Beep boop') }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'reformats' do
is_expected.to eq 'Beep boop'
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
context 'with custom_emojify option' do
let!(:emoji) { Fabricate(:custom_emoji, domain: remote_account.domain) }
let(:status) { Fabricate(:status, account: remote_account, text: text) }
subject { Formatter.instance.format(status, custom_emojify: true) }
context 'with emoji at the start' do
let(:text) { '<p>:coolcat: Beep boop<br />' }
it 'converts shortcode to image tag' do
is_expected.to match(/<p><img draggable="false" class="emojione" alt=":coolcat:"/)
end
end
context 'with emoji in the middle' do
let(:text) { '<p>Beep :coolcat: boop</p>' }
it 'converts shortcode to image tag' do
is_expected.to match(/Beep <img draggable="false" class="emojione" alt=":coolcat:"/)
end
end
context 'with concatenated emoji' do
let(:text) { '<p>:coolcat::coolcat:</p>' }
it 'does not touch the shortcodes' do
is_expected.to match(/<p>:coolcat::coolcat:<\/p>/)
end
end
context 'with emoji at the end' do
let(:text) { '<p>Beep boop<br />:coolcat:</p>' }
it 'converts shortcode to image tag' do
is_expected.to match(/<br><img draggable="false" class="emojione" alt=":coolcat:"/)
end
end
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
end
describe '#reformat' do
subject { Formatter.instance.reformat(text) }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'contains plain text' do
let(:text) { 'Beep boop' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'contains plain text' do
is_expected.to include 'Beep boop'
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'contains scripts' do
let(:text) { '<script>alert("Hello")</script>' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'strips scripts' do
is_expected.to_not include '<script>alert("Hello")</script>'
context 'contains malicious classes' do
let(:text) { '<span class="mention status__content__spoiler-link">Show more</span>' }
it 'strips malicious classes' do
is_expected.to_not include 'status__content__spoiler-link'
end
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
describe '#plaintext' do
subject { Formatter.instance.plaintext(status) }
context 'with local status' do
let(:status) { Fabricate(:status, text: '<p>a text by a nerd who uses an HTML tag in text</p>', uri: nil) }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'returns raw text' do
is_expected.to eq '<p>a text by a nerd who uses an HTML tag in text</p>'
end
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'with remote status' do
Eugen Rochko
a validé
let(:status) { Fabricate(:status, account: remote_account, text: '<script>alert("Hello")</script>') }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'returns tag-stripped text' do
is_expected.to eq ''
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
describe '#simplified_format' do
subject { Formatter.instance.simplified_format(account) }
context 'with local status' do
let(:account) { Fabricate(:account, domain: nil, note: text) }
context 'contains linkable mentions for local accounts' do
let(:text) { '@alice' }
before { local_account }
it 'links' do
is_expected.to eq '<p><span class="h-card"><a href="https://cb6e6126.ngrok.io/@alice" class="u-url mention">@<span>alice</span></a></span></p>'
end
end
context 'contains linkable mentions for remote accounts' do
let(:text) { '@bob@remote' }
before { remote_account }
it 'links' do
is_expected.to eq '<p><span class="h-card"><a href="https://remote/" class="u-url mention">@<span>bob</span></a></span></p>'
end
end
context 'contains unlinkable mentions' do
let(:text) { '@alice' }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'returns raw mention texts' do
is_expected.to eq '<p>@alice</p>'
end
end
include_examples 'encode and link URLs'
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
context 'with remote status' do
let(:text) { '<script>alert("Hello")</script>' }
let(:account) { Fabricate(:account, domain: 'remote', note: text) }
it 'reformats' do
is_expected.to_not include '<script>alert("Hello")</script>'
end
end
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
end
describe '#sanitize' do
let(:html) { '<script>alert("Hello")</script>' }
subject { Formatter.instance.sanitize(html, Sanitize::Config::MASTODON_STRICT) }
Akihiko Odaki (@fn_aki@pawoo.net)
a validé
it 'sanitizes' do
is_expected.to eq 'alert("Hello")'
end
end
end