diff options
Diffstat (limited to 'spec')
19 files changed, 540 insertions, 46 deletions
diff --git a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb index ebd462a03..4fa6fbcf4 100644 --- a/spec/controllers/api/v1/accounts/credentials_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/credentials_controller_spec.rb @@ -74,7 +74,9 @@ describe Api::V1::Accounts::CredentialsController do describe 'with invalid data' do before do - patch :update, params: { note: 'This is too long. ' * 30 } + note = 'This is too long. ' + note = note + 'a' * (Account::MAX_NOTE_LENGTH - note.length + 1) + patch :update, params: { note: note } end it 'returns http unprocessable entity' do diff --git a/spec/controllers/api/v1/mutes_controller_spec.rb b/spec/controllers/api/v1/mutes_controller_spec.rb index a2b814a69..95ec17d6f 100644 --- a/spec/controllers/api/v1/mutes_controller_spec.rb +++ b/spec/controllers/api/v1/mutes_controller_spec.rb @@ -60,4 +60,25 @@ RSpec.describe Api::V1::MutesController, type: :controller do end end end + + describe 'GET #details' do + before do + Fabricate(:mute, account: user.account, hide_notifications: false) + get :details, params: { limit: 1 } + end + + let(:mutes) { JSON.parse(response.body) } + + it 'returns http success' do + expect(response).to have_http_status(:success) + end + + it 'returns one mute' do + expect(mutes.size).to be(1) + end + + it 'returns whether the mute hides notifications' do + expect(mutes.first["hide_notifications"]).to be(false) + end + end end diff --git a/spec/controllers/api/v1/timelines/direct_controller_spec.rb b/spec/controllers/api/v1/timelines/direct_controller_spec.rb new file mode 100644 index 000000000..a22c2cbea --- /dev/null +++ b/spec/controllers/api/v1/timelines/direct_controller_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Api::V1::Timelines::DirectController, type: :controller do + let(:user) { Fabricate(:user) } + let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') } + + describe 'GET #show' do + it 'returns 200' do + allow(controller).to receive(:doorkeeper_token) { token } + get :show + + expect(response).to have_http_status(200) + end + end +end diff --git a/spec/controllers/api/v1/timelines/public_controller_spec.rb b/spec/controllers/api/v1/timelines/public_controller_spec.rb index 737aedba6..b8e9d8674 100644 --- a/spec/controllers/api/v1/timelines/public_controller_spec.rb +++ b/spec/controllers/api/v1/timelines/public_controller_spec.rb @@ -44,6 +44,10 @@ describe Api::V1::Timelines::PublicController do context 'without a user context' do let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil) } + before do + Setting.timeline_preview = true + end + describe 'GET #show' do it 'returns http success' do get :show diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 63ae27a92..686ae70fb 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -87,37 +87,41 @@ describe ApplicationController, type: :controller do end end - describe 'helper_method :current_theme' do - it 'returns "default" when theme wasn\'t changed in admin settings' do - allow(Setting).to receive(:default_settings).and_return({ 'theme' => 'default' }) + describe 'helper_method :current_flavour' do + it 'returns "glitch" when theme wasn\'t changed in admin settings' do + allow(Setting).to receive(:default_settings).and_return({'skin' => 'default'}) + allow(Setting).to receive(:default_settings).and_return({'flavour' => 'glitch'}) - expect(controller.view_context.current_theme).to eq 'default' + expect(controller.view_context.current_flavour).to eq 'glitch' end - it 'returns instances\'s theme when user is not signed in' do - allow(Setting).to receive(:[]).with('theme').and_return 'contrast' + it 'returns instances\'s flavour when user is not signed in' do + allow(Setting).to receive(:[]).with('skin').and_return 'default' + allow(Setting).to receive(:[]).with('flavour').and_return 'vanilla' - expect(controller.view_context.current_theme).to eq 'contrast' + expect(controller.view_context.current_flavour).to eq 'vanilla' end - it 'returns instances\'s default theme when user didn\'t set theme' do + it 'returns instances\'s default flavour when user didn\'t set theme' do current_user = Fabricate(:user) sign_in current_user - allow(Setting).to receive(:[]).with('theme').and_return 'contrast' + allow(Setting).to receive(:[]).with('skin').and_return 'default' + allow(Setting).to receive(:[]).with('flavour').and_return 'vanilla' allow(Setting).to receive(:[]).with('noindex').and_return false - expect(controller.view_context.current_theme).to eq 'contrast' + expect(controller.view_context.current_flavour).to eq 'vanilla' end - it 'returns user\'s theme when it is set' do + it 'returns user\'s flavour when it is set' do current_user = Fabricate(:user) - current_user.settings['theme'] = 'mastodon-light' + current_user.settings['flavour'] = 'glitch' sign_in current_user - allow(Setting).to receive(:[]).with('theme').and_return 'contrast' + allow(Setting).to receive(:[]).with('skin').and_return 'default' + allow(Setting).to receive(:[]).with('flavour').and_return 'vanilla' - expect(controller.view_context.current_theme).to eq 'mastodon-light' + expect(controller.view_context.current_flavour).to eq 'glitch' end end diff --git a/spec/controllers/health_check_controller_spec.rb b/spec/controllers/health_check_controller_spec.rb new file mode 100644 index 000000000..c00600c9b --- /dev/null +++ b/spec/controllers/health_check_controller_spec.rb @@ -0,0 +1,13 @@ +require 'rails_helper' + +describe HealthCheck::HealthCheckController do + render_views + + describe 'GET #show' do + subject(:response) { get :index, params: { format: :json } } + + it 'returns the right response' do + expect(response).to have_http_status 200 + end + end +end diff --git a/spec/controllers/settings/flavours_controller_spec.rb b/spec/controllers/settings/flavours_controller_spec.rb new file mode 100644 index 000000000..f89bde1f9 --- /dev/null +++ b/spec/controllers/settings/flavours_controller_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe Settings::FlavoursController, type: :controller do + let(:user) { Fabricate(:user) } + + before do + sign_in user, scope: :user + end + + describe 'PUT #update' do + describe 'without a user[setting_skin] parameter' do + it 'sets the selected flavour' do + put :update, params: { flavour: 'schnozzberry' } + + user.reload + + expect(user.setting_flavour).to eq 'schnozzberry' + end + end + + describe 'with a user[setting_skin] parameter' do + before do + put :update, params: { flavour: 'schnozzberry', user: { setting_skin: 'wallpaper' } } + + user.reload + end + + it 'sets the selected flavour' do + expect(user.setting_flavour).to eq 'schnozzberry' + end + + it 'sets the selected skin' do + expect(user.setting_skin).to eq 'wallpaper' + end + end + end +end diff --git a/spec/helpers/settings/keyword_mutes_helper_spec.rb b/spec/helpers/settings/keyword_mutes_helper_spec.rb new file mode 100644 index 000000000..a19d518dd --- /dev/null +++ b/spec/helpers/settings/keyword_mutes_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the Settings::KeywordMutesHelper. For example: +# +# describe Settings::KeywordMutesHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe Settings::KeywordMutesHelper, type: :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb index 51e0b8caf..6e9f6cfa5 100644 --- a/spec/lib/activitypub/activity/create_spec.rb +++ b/spec/lib/activitypub/activity/create_spec.rb @@ -146,6 +146,31 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'limited when direct message assertion is false' do + let(:recipient) { Fabricate(:account) } + + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + directMessage: false, + to: ActivityPub::TagManager.instance.uri_for(recipient), + tag: { + type: 'Mention', + href: ActivityPub::TagManager.instance.uri_for(recipient), + }, + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'limited' + end + end + context 'direct' do let(:recipient) { Fabricate(:account) } @@ -170,6 +195,27 @@ RSpec.describe ActivityPub::Activity::Create do end end + context 'direct when direct message assertion is true' do + let(:recipient) { Fabricate(:account) } + + let(:object_json) do + { + id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join, + type: 'Note', + content: 'Lorem ipsum', + to: ActivityPub::TagManager.instance.uri_for(recipient), + directMessage: true, + } + end + + it 'creates status' do + status = sender.statuses.first + + expect(status).to_not be_nil + expect(status.visibility).to eq 'direct' + end + end + context 'as a reply' do let(:original_status) { Fabricate(:status) } diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 22eddd2ab..40e8214b6 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -119,6 +119,13 @@ RSpec.describe FeedManager do expect(FeedManager.instance.filter?(:home, status, bob.id)).to be true end + it 'returns true for status by followee mentioning muted account' do + bob.mute!(jeff) + bob.follow!(alice) + status = PostStatusService.new.call(alice, text: 'Hey @jeff') + expect(FeedManager.instance.filter?(:home, status, bob.id)).to be true + end + it 'returns true for reblog of a personally blocked domain' do alice.block_domain!('example.com') alice.follow!(jeff) @@ -309,14 +316,109 @@ RSpec.describe FeedManager do end describe '#push_to_list' do + let(:owner) { Fabricate(:account, username: 'owner') } + let(:alice) { Fabricate(:account, username: 'alice') } + let(:bob) { Fabricate(:account, username: 'bob') } + let(:eve) { Fabricate(:account, username: 'eve') } + let(:list) { Fabricate(:list, account: owner) } + + before do + owner.follow!(alice) + owner.follow!(bob) + owner.follow!(eve) + + list.accounts << alice + list.accounts << bob + end + it "does not push when the given status's reblog is already inserted" do - list = Fabricate(:list) reblog = Fabricate(:status) status = Fabricate(:status, reblog: reblog) FeedManager.instance.push_to_list(list, status) expect(FeedManager.instance.push_to_list(list, reblog)).to eq false end + + context 'when replies policy is set to no replies' do + before do + list.replies_policy = :no_replies + end + + it 'pushes statuses that are not replies' do + status = Fabricate(:status, text: 'Hello world', account: bob) + expect(FeedManager.instance.push_to_list(list, status)).to eq true + end + + it 'pushes statuses that are replies to list owner' do + status = Fabricate(:status, text: 'Hello world', account: owner) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + + it 'does not push replies to another member of the list' do + status = Fabricate(:status, text: 'Hello world', account: alice) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq false + end + end + + context 'when replies policy is set to list-only replies' do + before do + list.replies_policy = :list_replies + end + + it 'pushes statuses that are not replies' do + status = Fabricate(:status, text: 'Hello world', account: bob) + expect(FeedManager.instance.push_to_list(list, status)).to eq true + end + + it 'pushes statuses that are replies to list owner' do + status = Fabricate(:status, text: 'Hello world', account: owner) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + + it 'pushes replies to another member of the list' do + status = Fabricate(:status, text: 'Hello world', account: alice) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + + it 'does not push replies to someone not a member of the list' do + status = Fabricate(:status, text: 'Hello world', account: eve) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq false + end + end + + context 'when replies policy is set to any reply' do + before do + list.replies_policy = :all_replies + end + + it 'pushes statuses that are not replies' do + status = Fabricate(:status, text: 'Hello world', account: bob) + expect(FeedManager.instance.push_to_list(list, status)).to eq true + end + + it 'pushes statuses that are replies to list owner' do + status = Fabricate(:status, text: 'Hello world', account: owner) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + + it 'pushes replies to another member of the list' do + status = Fabricate(:status, text: 'Hello world', account: alice) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + + it 'pushes replies to someone not a member of the list' do + status = Fabricate(:status, text: 'Hello world', account: eve) + reply = Fabricate(:status, text: 'Nay', thread: status, account: bob) + expect(FeedManager.instance.push_to_list(list, reply)).to eq true + end + end end describe '#merge_into_timeline' do diff --git a/spec/lib/sanitize_config_spec.rb b/spec/lib/sanitize_config_spec.rb index d66302e64..da24f67d6 100644 --- a/spec/lib/sanitize_config_spec.rb +++ b/spec/lib/sanitize_config_spec.rb @@ -4,27 +4,17 @@ require 'rails_helper' require Rails.root.join('app', 'lib', 'sanitize_config.rb') describe Sanitize::Config do - describe '::MASTODON_STRICT' do - subject { Sanitize::Config::MASTODON_STRICT } - - it 'converts h1 to p' do - expect(Sanitize.fragment('<h1>Foo</h1>', subject)).to eq '<p>Foo</p>' - end - - it 'converts ul to p' do - expect(Sanitize.fragment('<p>Check out:</p><ul><li>Foo</li><li>Bar</li></ul>', subject)).to eq '<p>Check out:</p><p>Foo<br>Bar</p>' - end - - it 'converts p inside ul' do - expect(Sanitize.fragment('<ul><li><p>Foo</p><p>Bar</p></li><li>Baz</li></ul>', subject)).to eq '<p>Foo<br>Bar<br>Baz</p>' + shared_examples 'common HTML sanitization' do + it 'keeps h1' do + expect(Sanitize.fragment('<h1>Foo</h1>', subject)).to eq '<h1>Foo</h1>' end - it 'converts ul inside ul' do - expect(Sanitize.fragment('<ul><li>Foo</li><li><ul><li>Bar</li><li>Baz</li></ul></li></ul>', subject)).to eq '<p>Foo<br>Bar<br>Baz</p>' + it 'keeps ul' do + expect(Sanitize.fragment('<p>Check out:</p><ul><li>Foo</li><li>Bar</li></ul>', subject)).to eq '<p>Check out:</p><ul><li>Foo</li><li>Bar</li></ul>' end - it 'keep links in lists' do - expect(Sanitize.fragment('<p>Check out:</p><ul><li><a href="https://joinmastodon.org" rel="nofollow noopener noreferrer" target="_blank">joinmastodon.org</a></li><li>Bar</li></ul>', subject)).to eq '<p>Check out:</p><p><a href="https://joinmastodon.org" rel="nofollow noopener noreferrer" target="_blank">joinmastodon.org</a><br>Bar</p>' + it 'keeps start and reversed attributes of ol' do + expect(Sanitize.fragment('<p>Check out:</p><ol start="3" reversed=""><li>Foo</li><li>Bar</li></ol>', subject)).to eq '<p>Check out:</p><ol start="3" reversed=""><li>Foo</li><li>Bar</li></ol>' end it 'removes a without href' do @@ -42,5 +32,40 @@ describe Sanitize::Config do it 'keeps a with href' do expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>' end + + it 'removes a with unparsable href' do + expect(Sanitize.fragment('<a href=" https://google.fr">Test</a>', subject)).to eq 'Test' + end + + it 'keeps a with supported scheme and no host' do + expect(Sanitize.fragment('<a href="dweb:/a/foo">Test</a>', subject)).to eq '<a href="dweb:/a/foo" rel="nofollow noopener noreferrer" target="_blank">Test</a>' + end + end + + describe '::MASTODON_STRICT' do + subject { Sanitize::Config::MASTODON_STRICT } + + it_behaves_like 'common HTML sanitization' + + it 'keeps a with href and rel tag' do + expect(Sanitize.fragment('<a href="http://example.com" rel="tag">Test</a>', subject)).to eq '<a href="http://example.com" rel="tag nofollow noopener noreferrer" target="_blank">Test</a>' + end + end + + describe '::MASTODON_STRICT with outgoing toots' do + subject { Sanitize::Config::MASTODON_STRICT.merge(outgoing: true) } + + around do |example| + original_web_domain = Rails.configuration.x.web_domain + example.run + Rails.configuration.x.web_domain = original_web_domain + end + + it_behaves_like 'common HTML sanitization' + + it 'keeps a with href and rel tag, not adding to rel if url is local' do + Rails.configuration.x.web_domain = 'domain.test' + expect(Sanitize.fragment('<a href="http://domain.test/tags/foo" rel="tag">Test</a>', subject)).to eq '<a href="http://domain.test/tags/foo" rel="tag" target="_blank">Test</a>' + end end end diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb index e8ef61f66..36e346f14 100644 --- a/spec/models/concerns/account_interactions_spec.rb +++ b/spec/models/concerns/account_interactions_spec.rb @@ -12,12 +12,19 @@ describe AccountInteractions do subject { Account.following_map(target_account_ids, account_id) } context 'account with Follow' do - it 'returns { target_account_id => true }' do + it 'returns { target_account_id => { reblogs: true } }' do Fabricate(:follow, account: account, target_account: target_account) is_expected.to eq(target_account_id => { reblogs: true }) end end + context 'account with Follow but with reblogs disabled' do + it 'returns { target_account_id => { reblogs: false } }' do + Fabricate(:follow, account: account, target_account: target_account, show_reblogs: false) + is_expected.to eq(target_account_id => { reblogs: false }) + end + end + context 'account without Follow' do it 'returns {}' do is_expected.to eq({}) @@ -569,7 +576,44 @@ describe AccountInteractions do end it 'does mute notifications' do - expect(me.muting_notifications?(you)).to be true + expect(me.muting_notifications?(you)).to be true + end + end + end + + describe 'ignoring reblogs from an account' do + before do + @me = Fabricate(:account, username: 'Me') + @you = Fabricate(:account, username: 'You') + end + + context 'with the reblogs option unspecified' do + before do + @me.follow!(@you) + end + + it 'defaults to showing reblogs' do + expect(@me.muting_reblogs?(@you)).to be(false) + end + end + + context 'with the reblogs option set to false' do + before do + @me.follow!(@you, reblogs: false) + end + + it 'does mute reblogs' do + expect(@me.muting_reblogs?(@you)).to be(true) + end + end + + context 'with the reblogs option set to true' do + before do + @me.follow!(@you, reblogs: true) + end + + it 'does not mute reblogs' do + expect(@me.muting_reblogs?(@you)).to be(false) end end end diff --git a/spec/models/follow_request_spec.rb b/spec/models/follow_request_spec.rb index 2cf28b263..4b824c0db 100644 --- a/spec/models/follow_request_spec.rb +++ b/spec/models/follow_request_spec.rb @@ -13,6 +13,13 @@ RSpec.describe FollowRequest, type: :model do follow_request.authorize! end + it 'generates a Follow' do + follow_request = Fabricate.create(:follow_request) + follow_request.authorize! + target = follow_request.target_account + expect(follow_request.account.following?(target)).to be true + end + it 'correctly passes show_reblogs when true' do follow_request = Fabricate.create(:follow_request, show_reblogs: true) follow_request.authorize! diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 4aee14cbd..041021d34 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -203,6 +203,43 @@ RSpec.describe Status, type: :model do end end + describe 'on create' do + let(:local_account) { Fabricate(:account, username: 'local', domain: nil) } + let(:remote_account) { Fabricate(:account, username: 'remote', domain: 'example.com') } + + subject { Status.new } + + describe 'on a status that ends with the local-only emoji' do + before do + subject.text = 'A toot ' + subject.local_only_emoji + end + + context 'if the status originates from this instance' do + before do + subject.account = local_account + end + + it 'is marked local-only' do + subject.save! + + expect(subject).to be_local_only + end + end + + context 'if the status is remote' do + before do + subject.account = remote_account + end + + it 'is not marked local-only' do + subject.save! + + expect(subject).to_not be_local_only + end + end + end + end + describe '.mutes_map' do let(:status) { Fabricate(:status) } let(:account) { Fabricate(:account) } @@ -267,6 +304,56 @@ RSpec.describe Status, type: :model do end end + describe '.as_direct_timeline' do + let(:account) { Fabricate(:account) } + let(:followed) { Fabricate(:account) } + let(:not_followed) { Fabricate(:account) } + + before do + Fabricate(:follow, account: account, target_account: followed) + + @self_public_status = Fabricate(:status, account: account, visibility: :public) + @self_direct_status = Fabricate(:status, account: account, visibility: :direct) + @followed_public_status = Fabricate(:status, account: followed, visibility: :public) + @followed_direct_status = Fabricate(:status, account: followed, visibility: :direct) + @not_followed_direct_status = Fabricate(:status, account: not_followed, visibility: :direct) + + @results = Status.as_direct_timeline(account) + end + + it 'does not include public statuses from self' do + expect(@results).to_not include(@self_public_status) + end + + it 'includes direct statuses from self' do + expect(@results).to include(@self_direct_status) + end + + it 'does not include public statuses from followed' do + expect(@results).to_not include(@followed_public_status) + end + + it 'does not include direct statuses not mentioning recipient from followed' do + expect(@results).to_not include(@followed_direct_status) + end + + it 'does not include direct statuses not mentioning recipient from non-followed' do + expect(@results).to_not include(@not_followed_direct_status) + end + + it 'includes direct statuses mentioning recipient from followed' do + Fabricate(:mention, account: account, status: @followed_direct_status) + results2 = Status.as_direct_timeline(account) + expect(results2).to include(@followed_direct_status) + end + + it 'includes direct statuses mentioning recipient from non-followed' do + Fabricate(:mention, account: account, status: @not_followed_direct_status) + results2 = Status.as_direct_timeline(account) + expect(results2).to include(@not_followed_direct_status) + end + end + describe '.as_public_timeline' do it 'only includes statuses with public visibility' do public_status = Fabricate(:status, visibility: :public) @@ -479,6 +566,32 @@ RSpec.describe Status, type: :model do end end end + + context 'with local-only statuses' do + let(:status) { Fabricate(:status, local_only: true) } + + subject { Status.as_public_timeline(viewer) } + + context 'without a viewer' do + let(:viewer) { nil } + + it 'excludes local-only statuses' do + expect(subject).to_not include(status) + end + end + + context 'with a viewer' do + let(:viewer) { Fabricate(:account, username: 'viewer') } + + it 'includes local-only statuses' do + expect(subject).to include(status) + end + end + + # TODO: What happens if the viewer is remote? + # Can the viewer be remote? + # What prevents the viewer from being remote? + end end describe '.as_tag_timeline' do @@ -500,6 +613,27 @@ RSpec.describe Status, type: :model do results = Status.as_tag_timeline(tag) expect(results).to include(status) end + + context 'on a local-only status' do + let(:tag) { Fabricate(:tag) } + let(:status) { Fabricate(:status, local_only: true, tags: [tag]) } + + context 'without a viewer' do + let(:viewer) { nil } + + it 'filters the local-only status out of the result set' do + expect(Status.as_tag_timeline(tag, viewer)).not_to include(status) + end + end + + context 'with a viewer' do + let(:viewer) { Fabricate(:account, username: 'viewer', domain: nil) } + + it 'keeps the local-only status in the result set' do + expect(Status.as_tag_timeline(tag, viewer)).to include(status) + end + end + end end describe '.permitted_for' do diff --git a/spec/policies/status_policy_spec.rb b/spec/policies/status_policy_spec.rb index 1cddf4abd..8bce29cad 100644 --- a/spec/policies/status_policy_spec.rb +++ b/spec/policies/status_policy_spec.rb @@ -73,6 +73,18 @@ RSpec.describe StatusPolicy, type: :model do expect(subject).to_not permit(viewer, status) end + + it 'denies access when local-only and the viewer is not logged in' do + allow(status).to receive(:local_only?) { true } + + expect(subject).to_not permit(nil, status) + end + + it 'denies access when local-only and the viewer is from another domain' do + viewer = Fabricate(:account, domain: 'remote-domain') + allow(status).to receive(:local_only?) { true } + expect(subject).to_not permit(viewer, status) + end end permissions :reblog? do diff --git a/spec/presenters/instance_presenter_spec.rb b/spec/presenters/instance_presenter_spec.rb index 93a4e88e4..81d8d0e98 100644 --- a/spec/presenters/instance_presenter_spec.rb +++ b/spec/presenters/instance_presenter_spec.rb @@ -91,8 +91,8 @@ describe InstancePresenter do end describe '#source_url' do - it 'returns "https://github.com/tootsuite/mastodon"' do - expect(instance_presenter.source_url).to eq('https://github.com/tootsuite/mastodon') + it 'returns "https://github.com/glitch-soc/mastodon"' do + expect(instance_presenter.source_url).to eq('https://github.com/glitch-soc/mastodon') end end diff --git a/spec/services/notify_service_spec.rb b/spec/services/notify_service_spec.rb index 440018ac9..b09d335ba 100644 --- a/spec/services/notify_service_spec.rb +++ b/spec/services/notify_service_spec.rb @@ -47,7 +47,7 @@ RSpec.describe NotifyService, type: :service do recipient.suspend! is_expected.to_not change(Notification, :count) end - + context 'for direct messages' do let(:activity) { Fabricate(:mention, account: recipient, status: Fabricate(:status, account: sender, visibility: :direct)) } diff --git a/spec/validators/status_length_validator_spec.rb b/spec/validators/status_length_validator_spec.rb index 11e55f933..62791cd2f 100644 --- a/spec/validators/status_length_validator_spec.rb +++ b/spec/validators/status_length_validator_spec.rb @@ -16,26 +16,31 @@ describe StatusLengthValidator do expect(status).not_to receive(:errors) end - it 'adds an error when content warning is over 500 characters' do - status = double(spoiler_text: 'a' * 520, text: '', errors: double(add: nil), local?: true, reblog?: false) + it 'adds an error when content warning is over MAX_CHARS characters' do + chars = StatusLengthValidator::MAX_CHARS + 1 + status = double(spoiler_text: 'a' * chars, text: '', errors: double(add: nil), local?: true, reblog?: false) subject.validate(status) expect(status.errors).to have_received(:add) end - it 'adds an error when text is over 500 characters' do - status = double(spoiler_text: '', text: 'a' * 520, errors: double(add: nil), local?: true, reblog?: false) + it 'adds an error when text is over MAX_CHARS characters' do + chars = StatusLengthValidator::MAX_CHARS + 1 + status = double(spoiler_text: '', text: 'a' * chars, errors: double(add: nil), local?: true, reblog?: false) subject.validate(status) expect(status.errors).to have_received(:add) end - it 'adds an error when text and content warning are over 500 characters total' do - status = double(spoiler_text: 'a' * 250, text: 'b' * 251, errors: double(add: nil), local?: true, reblog?: false) + it 'adds an error when text and content warning are over MAX_CHARS characters total' do + chars1 = 20 + chars2 = StatusLengthValidator::MAX_CHARS + 1 - chars1 + status = double(spoiler_text: 'a' * chars1, text: 'b' * chars2, errors: double(add: nil), local?: true, reblog?: false) subject.validate(status) expect(status.errors).to have_received(:add) end it 'counts URLs as 23 characters flat' do - text = ('a' * 476) + " http://#{'b' * 30}.com/example" + chars = StatusLengthValidator::MAX_CHARS - 1 - 23 + text = ('a' * chars) + " http://#{'b' * 30}.com/example" status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false) subject.validate(status) @@ -43,7 +48,9 @@ describe StatusLengthValidator do end it 'counts only the front part of remote usernames' do - text = ('a' * 475) + " @alice@#{'b' * 30}.com" + username = '@alice' + chars = StatusLengthValidator::MAX_CHARS - 1 - username.length + text = ('a' * 475) + " #{username}@#{'b' * 30}.com" status = double(spoiler_text: '', text: text, errors: double(add: nil), local?: true, reblog?: false) subject.validate(status) diff --git a/spec/views/about/show.html.haml_spec.rb b/spec/views/about/show.html.haml_spec.rb index c75c28759..26b131977 100644 --- a/spec/views/about/show.html.haml_spec.rb +++ b/spec/views/about/show.html.haml_spec.rb @@ -3,6 +3,8 @@ require 'rails_helper' describe 'about/show.html.haml', without_verify_partial_doubles: true do + let(:commit_hash) { '8925731c9869f55780644304e4420a1998e52607' } + before do allow(view).to receive(:site_hostname).and_return('example.com') allow(view).to receive(:site_title).and_return('example site') @@ -25,6 +27,7 @@ describe 'about/show.html.haml', without_verify_partial_doubles: true do user_count: 420, status_count: 69, active_user_count: 420, + commit_hash: commit_hash, contact_account: nil, sample_accounts: [] ) |