Merge commit '4aea3f88a6d30f102a79c2da7fcfac96465ba1a8' into merging-upstream
This commit is contained in:
@ -6,6 +6,7 @@ RSpec.describe HomeController, type: :controller do
|
||||
describe 'GET #index' do
|
||||
context 'when not signed in' do
|
||||
it 'redirects to about page' do
|
||||
@request.path = '/'
|
||||
get :index
|
||||
expect(response).to redirect_to(about_path)
|
||||
end
|
||||
@ -13,6 +14,7 @@ RSpec.describe HomeController, type: :controller do
|
||||
|
||||
context 'when signed in' do
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
subject do
|
||||
sign_in(user)
|
||||
get :index
|
||||
|
5
spec/fabricators/custom_emoji_fabricator.rb
Normal file
5
spec/fabricators/custom_emoji_fabricator.rb
Normal file
@ -0,0 +1,5 @@
|
||||
Fabricator(:custom_emoji) do
|
||||
shortcode 'coolcat'
|
||||
domain nil
|
||||
image { File.open(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png')) }
|
||||
end
|
3
spec/fabricators/site_upload_fabricator.rb
Normal file
3
spec/fabricators/site_upload_fabricator.rb
Normal file
@ -0,0 +1,3 @@
|
||||
Fabricator(:site_upload) do
|
||||
|
||||
end
|
BIN
spec/fixtures/files/emojo.png
vendored
Normal file
BIN
spec/fixtures/files/emojo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
9
spec/fixtures/requests/activitypub-actor-noinbox.txt
vendored
Normal file
9
spec/fixtures/requests/activitypub-actor-noinbox.txt
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
HTTP/1.1 200 OK
|
||||
Date: Sun, 17 Sep 2017 06:51:23 GMT
|
||||
Content-Type: application/json; charset=utf-8
|
||||
X-XSS-Protection: 1; mode=block
|
||||
Link: <https://ap.example.com/.well-known/webfinger?resource=acct%3Afoo%40ap.example.com>; rel="lrdd"; type="application/xrd+xml", <https://ap.example.com/users/foo.atom>; rel="alternate"; type="application/atom+xml"
|
||||
Vary: Accept-Encoding
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
|
||||
{"@context":"https://www.w3.org/ns/activitystreams","id":"https://ap.example.com/users/foo","type":"Person","following":"https://ap.example.com/users/foo/following","followers":"https://ap.example.com/users/foo/followers","inbox":null,"outbox":"https://ap.example.com/users/foo/outbox","preferredUsername":"foo","name":"","summary":"\u003cp\u003etest\u003c/p\u003e","icon":"https://quitter.no/avatar/7477-300-20160211190340.png","image":"/headers/original/missing.png","publicKey":{"id":"https://ap.example.com/users/foo#main-key","owner":"https://ap.example.com/users/foo","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3L4vnpNLzVH31MeWI39\n4F0wKeJFsLDAsNXGeOu0QF2x+h1zLWZw/agqD2R3JPU9/kaDJGPIV2Sn5zLyUA9S\n6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh\n8lDET6X4Pyw+ZJU0/OLo/41q9w+OrGtlsTm/PuPIeXnxa6BLqnDaxC+4IcjG/FiP\nahNCTINl/1F/TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq+t8nhQYkgAkt64euW\npva3qL5KD1mTIZQEP+LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3Qvu\nHQIDAQAB\n-----END PUBLIC KEY-----\n"}}
|
9
spec/fixtures/requests/activitypub-actor.txt
vendored
Normal file
9
spec/fixtures/requests/activitypub-actor.txt
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
HTTP/1.1 200 OK
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
Content-Type: application/activity+json; charset=utf-8
|
||||
Link: <https://ap.example.com/.well-known/webfinger?resource=acct%3Afoo%40ap.example.com>; rel="lrdd"; type="application/xrd+xml", <https://ap.example.com/users/foo.atom>; rel="alternate"; type="application/atom+xml", <https://ap.example.com/users/foo>; rel="alternate"; type="application/activity+json"
|
||||
Vary: Accept-Encoding
|
||||
X-Content-Type-Options: nosniff
|
||||
X-Xss-Protection: 1; mode=block
|
||||
|
||||
{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","sensitive":"as:sensitive","Hashtag":"as:Hashtag","ostatus":"http://ostatus.org#","atomUri":"ostatus:atomUri","inReplyToAtomUri":"ostatus:inReplyToAtomUri","conversation":"ostatus:conversation"}],"id":"https://ap.example.com/users/foo","type":"Person","following":"https://ap.example.com/users/foo/following","followers":"https://ap.example.com/users/foo/followers","inbox":"https://ap.example.com/users/foo/inbox","outbox":"https://ap.example.com/users/foo/outbox","preferredUsername":"foo","name":"","summary":"\u003cp\u003etest\u003c/p\u003e","url":"https://ap.example.com/@foo","manuallyApprovesFollowers":false,"publicKey":{"id":"https://ap.example.com/users/foo#main-key","owner":"https://ap.example.com/users/foo","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu3L4vnpNLzVH31MeWI39\n4F0wKeJFsLDAsNXGeOu0QF2x+h1zLWZw/agqD2R3JPU9/kaDJGPIV2Sn5zLyUA9S\n6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh\n8lDET6X4Pyw+ZJU0/OLo/41q9w+OrGtlsTm/PuPIeXnxa6BLqnDaxC+4IcjG/FiP\nahNCTINl/1F/TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq+t8nhQYkgAkt64euW\npva3qL5KD1mTIZQEP+LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3Qvu\nHQIDAQAB\n-----END PUBLIC KEY-----\n"},"endpoints":{"sharedInbox":"https://ap.example.com/inbox"},"icon":{"type":"Image","url":"https://quitter.no/avatar/7477-300-20160211190340.png"}}
|
47
spec/fixtures/requests/activitypub-feed.txt
vendored
Normal file
47
spec/fixtures/requests/activitypub-feed.txt
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
HTTP/1.1 200 OK
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
Content-Type: application/atom+xml; charset=utf-8
|
||||
Link: <https://ap.example.com/.well-known/webfinger?resource=acct%3Afoo%40ap.example.com>; rel="lrdd"; type="application/xrd+xml", <https://ap.example.com/users/foo.atom>; rel="alternate"; type="application/atom+xml", <https://ap.example.com/users/foo>; rel="alternate"; type="application/activity+json"
|
||||
Vary: Accept-Encoding
|
||||
Date: Sun, 17 Sep 2017 06:33:53 GMT
|
||||
|
||||
<?xml version="1.0"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:media="http://purl.org/syndication/atommedia" xmlns:ostatus="http://ostatus.org/schema/1.0" xmlns:mastodon="http://mastodon.social/schema/1.0">
|
||||
<id>https://ap.example.com/users/foo.atom</id>
|
||||
<title>foo</title>
|
||||
<subtitle>test</subtitle>
|
||||
<updated>2017-09-16T18:50:09Z</updated>
|
||||
<logo>https://ap.example.com/system/accounts/avatars/000/000/001/original/141ee5846d159cba.png?1505587809</logo>
|
||||
<author>
|
||||
<id>https://ap.example.com/users/foo</id>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
|
||||
<uri>https://ap.example.com/users/foo</uri>
|
||||
<name>foo</name>
|
||||
<email>foo@ap.example.com</email>
|
||||
<summary type="html"><p>test</p></summary>
|
||||
<link rel="alternate" type="text/html" href="https://ap.example.com/@foo"/>
|
||||
<link rel="avatar" type="image/jpeg" media:width="120" media:height="120" href="https://quitter.no/avatar/7477-300-20160211190340.png"/>
|
||||
<poco:preferredUsername>foo</poco:preferredUsername>
|
||||
<poco:note>test</poco:note>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
</author>
|
||||
<link rel="alternate" type="text/html" href="https://ap.example.com/@foo"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://ap.example.com/users/foo.atom"/>
|
||||
<link rel="hub" href="https://ap.example.com/api/push"/>
|
||||
<link rel="salmon" href="https://ap.example.com/api/salmon/1"/>
|
||||
<entry>
|
||||
<id>https://ap.example.com/users/foo/statuses/11076</id>
|
||||
<published>2017-09-13T01:23:19Z</published>
|
||||
<updated>2017-09-13T01:23:19Z</updated>
|
||||
<title>New status by foo</title>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="alternate" type="application/activity+json" href="https://ap.example.com/users/foo/statuses/11076"/>
|
||||
<content type="html" xml:lang="ja"><p>test</p></content>
|
||||
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
|
||||
<mastodon:scope>public</mastodon:scope>
|
||||
<link rel="alternate" type="text/html" href="https://ap.example.com/@foo/11076"/>
|
||||
<link rel="self" type="application/atom+xml" href="https://ap.example.com/users/foo/updates/11015.atom"/>
|
||||
<ostatus:conversation ref="tag:ap.example.com,2017-09-13:objectId=7412:objectType=Conversation"/>
|
||||
</entry>
|
||||
</feed>
|
7
spec/fixtures/requests/activitypub-webfinger.txt
vendored
Normal file
7
spec/fixtures/requests/activitypub-webfinger.txt
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
HTTP/1.1 200 OK
|
||||
Cache-Control: max-age=0, private, must-revalidate
|
||||
Content-Type: application/jrd+json; charset=utf-8
|
||||
X-Content-Type-Options: nosniff
|
||||
Date: Sun, 17 Sep 2017 06:22:50 GMT
|
||||
|
||||
{"subject":"acct:foo@ap.example.com","aliases":["https://ap.example.com/@foo","https://ap.example.com/users/foo"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://ap.example.com/@foo"},{"rel":"http://schemas.google.com/g/2010#updates-from","type":"application/atom+xml","href":"https://ap.example.com/users/foo.atom"},{"rel":"self","type":"application/activity+json","href":"https://ap.example.com/users/foo"},{"rel":"salmon","href":"https://ap.example.com/api/salmon/1"},{"rel":"magic-public-key","href":"data:application/magic-public-key,RSA.u3L4vnpNLzVH31MeWI394F0wKeJFsLDAsNXGeOu0QF2x-h1zLWZw_agqD2R3JPU9_kaDJGPIV2Sn5zLyUA9S6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh8lDET6X4Pyw-ZJU0_OLo_41q9w-OrGtlsTm_PuPIeXnxa6BLqnDaxC-4IcjG_FiPahNCTINl_1F_TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq-t8nhQYkgAkt64euWpva3qL5KD1mTIZQEP-LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3QvuHQ==.AQAB"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://ap.example.com/authorize_follow?acct={uri}"}]}
|
@ -17,6 +17,7 @@ RSpec.describe ActivityPub::Activity::Create do
|
||||
|
||||
before do
|
||||
stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
|
||||
stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png'))
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
@ -217,5 +218,29 @@ RSpec.describe ActivityPub::Activity::Create do
|
||||
expect(status.tags.map(&:name)).to include('test')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with emojis' do
|
||||
let(:object_json) do
|
||||
{
|
||||
id: 'bar',
|
||||
type: 'Note',
|
||||
content: 'Lorem ipsum :tinking:',
|
||||
tag: [
|
||||
{
|
||||
type: 'Emoji',
|
||||
href: 'http://example.com/emoji.png',
|
||||
name: 'tinking',
|
||||
},
|
||||
],
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates status' do
|
||||
status = sender.statuses.first
|
||||
|
||||
expect(status).to_not be_nil
|
||||
expect(status.emojis.map(&:shortcode)).to include('tinking')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -89,6 +89,54 @@ RSpec.describe Formatter do
|
||||
end
|
||||
end
|
||||
|
||||
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/%E6%97%A5%E6%9C%AC"'
|
||||
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/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD"'
|
||||
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/%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD"'
|
||||
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/%E8%87%BA%E7%81%A3"'
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
context 'contains HTML (script tag)' do
|
||||
let(:text) { '<script>alert("Hello")</script>' }
|
||||
|
||||
@ -175,6 +223,45 @@ RSpec.describe Formatter do
|
||||
|
||||
include_examples 'encode and link URLs'
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
context 'with remote status' do
|
||||
@ -183,6 +270,45 @@ RSpec.describe Formatter do
|
||||
it 'reformats' do
|
||||
is_expected.to eq 'Beep boop'
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -3,10 +3,10 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe LanguageDetector do
|
||||
describe 'prepared_text' do
|
||||
describe 'prepare_text' do
|
||||
it 'returns unmodified string without special cases' do
|
||||
string = 'just a regular string'
|
||||
result = described_class.new(string).prepared_text
|
||||
result = described_class.instance.send(:prepare_text, string)
|
||||
|
||||
expect(result).to eq string
|
||||
end
|
||||
@ -14,33 +14,35 @@ describe LanguageDetector do
|
||||
it 'collapses spacing in strings' do
|
||||
string = 'The formatting in this is very odd'
|
||||
|
||||
result = described_class.new(string).prepared_text
|
||||
result = described_class.instance.send(:prepare_text, string)
|
||||
expect(result).to eq 'The formatting in this is very odd'
|
||||
end
|
||||
|
||||
it 'strips usernames from strings before detection' do
|
||||
string = '@username Yeah, very surreal...! also @friend'
|
||||
|
||||
result = described_class.new(string).prepared_text
|
||||
result = described_class.instance.send(:prepare_text, string)
|
||||
expect(result).to eq 'Yeah, very surreal...! also'
|
||||
end
|
||||
|
||||
it 'strips URLs from strings before detection' do
|
||||
string = 'Our website is https://example.com and also http://localhost.dev'
|
||||
|
||||
result = described_class.new(string).prepared_text
|
||||
result = described_class.instance.send(:prepare_text, string)
|
||||
expect(result).to eq 'Our website is and also'
|
||||
end
|
||||
|
||||
it 'strips #hashtags from strings before detection' do
|
||||
string = 'Hey look at all the #animals and #fish'
|
||||
|
||||
result = described_class.new(string).prepared_text
|
||||
result = described_class.instance.send(:prepare_text, string)
|
||||
expect(result).to eq 'Hey look at all the and'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'to_iso_s' do
|
||||
describe 'detect' do
|
||||
let(:account_without_user_locale) { Fabricate(:user, locale: nil).account }
|
||||
|
||||
it 'detects english language for basic strings' do
|
||||
strings = [
|
||||
"Hello and welcome to mastodon how are you today?",
|
||||
@ -48,7 +50,7 @@ describe LanguageDetector do
|
||||
"a lot of people just want to feel righteous all the time and that's all that matters",
|
||||
]
|
||||
strings.each do |string|
|
||||
result = described_class.new(string).to_iso_s
|
||||
result = described_class.instance.detect(string, account_without_user_locale)
|
||||
|
||||
expect(result).to eq(:en), string
|
||||
end
|
||||
@ -56,14 +58,14 @@ describe LanguageDetector do
|
||||
|
||||
it 'detects spanish language' do
|
||||
string = 'Obtener un Hola y bienvenidos a Mastodon'
|
||||
result = described_class.new(string).to_iso_s
|
||||
result = described_class.instance.detect(string, account_without_user_locale)
|
||||
|
||||
expect(result).to eq :es
|
||||
end
|
||||
|
||||
describe 'when language can\'t be detected' do
|
||||
it 'uses nil when sent an empty document' do
|
||||
result = described_class.new('').to_iso_s
|
||||
result = described_class.instance.detect('', account_without_user_locale)
|
||||
expect(result).to eq nil
|
||||
end
|
||||
|
||||
@ -73,7 +75,7 @@ describe LanguageDetector do
|
||||
cld_result = CLD3::NNetLanguageIdentifier.new(0, 2048).find_language(string)
|
||||
expect(cld_result).not_to eq :en
|
||||
|
||||
result = described_class.new(string).to_iso_s
|
||||
result = described_class.instance.detect(string, account_without_user_locale)
|
||||
|
||||
expect(result).to eq nil
|
||||
end
|
||||
@ -82,14 +84,13 @@ describe LanguageDetector do
|
||||
describe 'with an account' do
|
||||
it 'uses the account locale when present' do
|
||||
account = double(user_locale: 'fr')
|
||||
result = described_class.new('', account).to_iso_s
|
||||
result = described_class.instance.detect('', account)
|
||||
|
||||
expect(result).to eq :fr
|
||||
end
|
||||
|
||||
it 'uses nil when account is present but has no locale' do
|
||||
account = double(user_locale: nil)
|
||||
result = described_class.new('', account).to_iso_s
|
||||
result = described_class.instance.detect('', account_without_user_locale)
|
||||
|
||||
expect(result).to eq nil
|
||||
end
|
||||
@ -97,8 +98,7 @@ describe LanguageDetector do
|
||||
|
||||
describe 'with an `en` default locale' do
|
||||
it 'uses nil for undetectable string' do
|
||||
string = ''
|
||||
result = described_class.new(string).to_iso_s
|
||||
result = described_class.instance.detect('', account_without_user_locale)
|
||||
|
||||
expect(result).to eq nil
|
||||
end
|
||||
@ -114,7 +114,7 @@ describe LanguageDetector do
|
||||
|
||||
it 'uses nil for undetectable string' do
|
||||
string = ''
|
||||
result = described_class.new(string).to_iso_s
|
||||
result = described_class.instance.detect(string, account_without_user_locale)
|
||||
|
||||
expect(result).to eq nil
|
||||
end
|
||||
|
@ -97,11 +97,23 @@ RSpec.describe OStatus::AtomSerializer do
|
||||
|
||||
mentioned = element.nodes.find do |node|
|
||||
node.name == 'link' &&
|
||||
node[:rel] == 'mentioned' &&
|
||||
node['ostatus:object-type'] == TagManager::TYPES[:person]
|
||||
node[:rel] == 'mentioned' &&
|
||||
node['ostatus:object-type'] == TagManager::TYPES[:person]
|
||||
end
|
||||
|
||||
expect(mentioned[:href]).to eq 'https://cb6e6126.ngrok.io/users/username'
|
||||
end
|
||||
|
||||
it 'appends link elements for emojis' do
|
||||
Fabricate(:custom_emoji)
|
||||
|
||||
status = Fabricate(:status, text: ':coolcat:')
|
||||
element = serialize(status)
|
||||
emoji = element.nodes.find { |node| node.name == 'link' && node[:rel] == 'emoji' }
|
||||
|
||||
expect(emoji[:name]).to eq 'coolcat'
|
||||
expect(emoji[:href]).to_not be_blank
|
||||
end
|
||||
end
|
||||
|
||||
describe 'render' do
|
||||
|
@ -63,23 +63,23 @@ RSpec.describe TagManager do
|
||||
|
||||
describe '#local_url?' do
|
||||
around do |example|
|
||||
original_local_domain = Rails.configuration.x.local_domain
|
||||
original_web_domain = Rails.configuration.x.web_domain
|
||||
example.run
|
||||
Rails.configuration.x.local_domain = original_local_domain
|
||||
Rails.configuration.x.web_domain = original_web_domain
|
||||
end
|
||||
|
||||
it 'returns true if the normalized string with port is local URL' do
|
||||
Rails.configuration.x.local_domain = 'domain:42'
|
||||
Rails.configuration.x.web_domain = 'domain:42'
|
||||
expect(TagManager.instance.local_url?('https://DoMaIn:42/')).to eq true
|
||||
end
|
||||
|
||||
it 'returns true if the normalized string without port is local URL' do
|
||||
Rails.configuration.x.local_domain = 'domain'
|
||||
Rails.configuration.x.web_domain = 'domain'
|
||||
expect(TagManager.instance.local_url?('https://DoMaIn/')).to eq true
|
||||
end
|
||||
|
||||
it 'returns false for string with irrelevant characters' do
|
||||
Rails.configuration.x.local_domain = 'domain'
|
||||
Rails.configuration.x.web_domain = 'domain'
|
||||
expect(TagManager.instance.local_url?('https://domainn/')).to eq false
|
||||
end
|
||||
end
|
||||
|
25
spec/models/custom_emoji_spec.rb
Normal file
25
spec/models/custom_emoji_spec.rb
Normal file
@ -0,0 +1,25 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe CustomEmoji, type: :model do
|
||||
describe '.from_text' do
|
||||
let!(:emojo) { Fabricate(:custom_emoji) }
|
||||
|
||||
subject { described_class.from_text(text, nil) }
|
||||
|
||||
context 'with plain text' do
|
||||
let(:text) { 'Hello :coolcat:' }
|
||||
|
||||
it 'returns records used via shortcodes in text' do
|
||||
is_expected.to include(emojo)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with html' do
|
||||
let(:text) { '<p>Hello :coolcat:</p>' }
|
||||
|
||||
it 'returns records used via shortcodes in text' do
|
||||
is_expected.to include(emojo)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
5
spec/models/site_upload_spec.rb
Normal file
5
spec/models/site_upload_spec.rb
Normal file
@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe SiteUpload, type: :model do
|
||||
|
||||
end
|
@ -173,19 +173,6 @@ RSpec.describe Status, type: :model do
|
||||
end
|
||||
end
|
||||
|
||||
describe '.local_only' do
|
||||
it 'returns only statuses from local accounts' do
|
||||
local_account = Fabricate(:account, domain: nil)
|
||||
remote_account = Fabricate(:account, domain: 'test.com')
|
||||
local_status = Fabricate(:status, account: local_account)
|
||||
remote_status = Fabricate(:status, account: remote_account)
|
||||
|
||||
results = described_class.local_only
|
||||
expect(results).to include(local_status)
|
||||
expect(results).not_to include(remote_status)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.as_home_timeline' do
|
||||
let(:account) { Fabricate(:account) }
|
||||
let(:followed) { Fabricate(:account) }
|
||||
@ -529,6 +516,14 @@ RSpec.describe Status, type: :model do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'validation' do
|
||||
it 'disallow empty uri for remote status' do
|
||||
alice.update(domain: 'example.com')
|
||||
status = Fabricate.build(:status, uri: '', account: alice)
|
||||
expect(status).to model_have_error_on_field(:uri)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'after_create' do
|
||||
it 'saves ActivityPub uri as uri for local status' do
|
||||
status = Status.create(account: alice, text: 'foo')
|
||||
|
@ -12,6 +12,8 @@ RSpec.describe FetchLinkCardService do
|
||||
stub_request(:get, 'http://example.com/sjis_with_wrong_charset').to_return(request_fixture('sjis_with_wrong_charset.txt'))
|
||||
stub_request(:head, 'http://example.com/koi8-r').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
|
||||
stub_request(:get, 'http://example.com/koi8-r').to_return(request_fixture('koi8-r.txt'))
|
||||
stub_request(:head, 'http://example.com/日本語').to_return(status: 200, headers: { 'Content-Type' => 'text/html' })
|
||||
stub_request(:get, 'http://example.com/日本語').to_return(request_fixture('sjis.txt'))
|
||||
stub_request(:head, 'https://github.com/qbi/WannaCry').to_return(status: 404)
|
||||
|
||||
subject.call(status)
|
||||
@ -52,6 +54,15 @@ RSpec.describe FetchLinkCardService do
|
||||
expect(status.preview_cards.first.title).to eq("Московя начинаетъ только въ XVI ст. привлекать внимане иностранцевъ.")
|
||||
end
|
||||
end
|
||||
|
||||
context do
|
||||
let(:status) { Fabricate(:status, text: 'テストhttp://example.com/日本語') }
|
||||
|
||||
it 'works with Japanese path string' do
|
||||
expect(a_request(:get, 'http://example.com/日本語')).to have_been_made.at_least_once
|
||||
expect(status.preview_cards.first.title).to eq("SJISのページ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in a remote status' do
|
||||
|
@ -65,15 +65,12 @@ RSpec.describe PostStatusService do
|
||||
end
|
||||
|
||||
it 'creates a status with a language set' do
|
||||
detector = double(to_iso_s: :en)
|
||||
allow(LanguageDetector).to receive(:new).and_return(detector)
|
||||
|
||||
account = Fabricate(:account)
|
||||
text = 'test status text'
|
||||
text = 'This is an English text.'
|
||||
|
||||
subject.call(account, text)
|
||||
status = subject.call(account, text)
|
||||
|
||||
expect(LanguageDetector).to have_received(:new).with(text, account)
|
||||
expect(status.language).to eq 'en'
|
||||
end
|
||||
|
||||
it 'processes mentions' do
|
||||
|
@ -72,6 +72,39 @@ RSpec.describe ResolveRemoteAccountService do
|
||||
end
|
||||
|
||||
context 'with an ActivityPub account' do
|
||||
before do
|
||||
stub_request(:get, "https://ap.example.com/.well-known/webfinger?resource=acct:foo@ap.example.com").to_return(request_fixture('activitypub-webfinger.txt'))
|
||||
stub_request(:get, "https://ap.example.com/users/foo").to_return(request_fixture('activitypub-actor.txt'))
|
||||
stub_request(:get, "https://ap.example.com/users/foo.atom").to_return(request_fixture('activitypub-feed.txt'))
|
||||
stub_request(:get, %r{https://ap.example.com/users/foo/\w+}).to_return(status: 404)
|
||||
end
|
||||
|
||||
it 'fallback to OStatus if actor json could not be fetched' do
|
||||
stub_request(:get, "https://ap.example.com/users/foo").to_return(status: 404)
|
||||
|
||||
account = subject.call('foo@ap.example.com')
|
||||
|
||||
expect(account.ostatus?).to eq true
|
||||
expect(account.remote_url).to eq 'https://ap.example.com/users/foo.atom'
|
||||
end
|
||||
|
||||
it 'fallback to OStatus if actor json did not have inbox_url' do
|
||||
stub_request(:get, "https://ap.example.com/users/foo").to_return(request_fixture('activitypub-actor-noinbox.txt'))
|
||||
|
||||
account = subject.call('foo@ap.example.com')
|
||||
|
||||
expect(account.ostatus?).to eq true
|
||||
expect(account.remote_url).to eq 'https://ap.example.com/users/foo.atom'
|
||||
end
|
||||
|
||||
it 'returns new remote account' do
|
||||
account = subject.call('foo@ap.example.com')
|
||||
|
||||
expect(account.activitypub?).to eq true
|
||||
expect(account.domain).to eq 'ap.example.com'
|
||||
expect(account.inbox_url).to eq 'https://ap.example.com/users/foo/inbox'
|
||||
end
|
||||
|
||||
pending
|
||||
end
|
||||
|
||||
|
@ -17,6 +17,7 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do
|
||||
version_number: '1.0',
|
||||
source_url: 'https://github.com/tootsuite/mastodon',
|
||||
open_registrations: false,
|
||||
thumbnail: nil,
|
||||
closed_registrations_message: 'yes',
|
||||
commit_hash: commit_hash)
|
||||
|
||||
|
@ -80,9 +80,9 @@ describe 'stream_entries/show.html.haml', without_verify_partial_doubles: true d
|
||||
|
||||
header_tags = view.content_for(:header_tags)
|
||||
|
||||
expect(header_tags).to match(%r{<meta content='.+' property='og:title'>})
|
||||
expect(header_tags).to match(%r{<meta content='article' property='og:type'>})
|
||||
expect(header_tags).to match(%r{<meta content='.+' property='og:image'>})
|
||||
expect(header_tags).to match(%r{<meta content='http://.+' property='og:url'>})
|
||||
expect(header_tags).to match(%r{<meta content=".+" property="og:title" />})
|
||||
expect(header_tags).to match(%r{<meta content="article" property="og:type" />})
|
||||
expect(header_tags).to match(%r{<meta content=".+" property="og:image" />})
|
||||
expect(header_tags).to match(%r{<meta content="http://.+" property="og:url" />})
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user