diff options
Diffstat (limited to 'spec/models')
-rw-r--r-- | spec/models/account_spec.rb | 100 | ||||
-rw-r--r-- | spec/models/concerns/account_interactions_spec.rb | 18 | ||||
-rw-r--r-- | spec/models/custom_emoji_spec.rb | 29 | ||||
-rw-r--r-- | spec/models/email_domain_block_spec.rb | 5 | ||||
-rw-r--r-- | spec/models/follow_request_spec.rb | 32 | ||||
-rw-r--r-- | spec/models/media_attachment_spec.rb | 77 | ||||
-rw-r--r-- | spec/models/notification_spec.rb | 113 | ||||
-rw-r--r-- | spec/models/remote_follow_spec.rb | 67 | ||||
-rw-r--r-- | spec/models/remote_profile_spec.rb | 143 | ||||
-rw-r--r-- | spec/models/session_activation_spec.rb | 124 | ||||
-rw-r--r-- | spec/models/setting_spec.rb | 184 | ||||
-rw-r--r-- | spec/models/site_upload_spec.rb | 8 | ||||
-rw-r--r-- | spec/models/status_spec.rb | 30 | ||||
-rw-r--r-- | spec/models/stream_entry_spec.rb | 115 | ||||
-rw-r--r-- | spec/models/tag_spec.rb | 7 | ||||
-rw-r--r-- | spec/models/user_spec.rb | 39 |
16 files changed, 1010 insertions, 81 deletions
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 361577eff..7501c498c 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -93,21 +93,44 @@ RSpec.describe Account, type: :model do end describe '#save_with_optional_media!' do - it 'sets default avatar, header, avatar_remote_url, and header_remote_url if some of them are invalid' do + before do stub_request(:get, 'https://remote/valid_avatar').to_return(request_fixture('avatar.txt')) stub_request(:get, 'https://remote/invalid_avatar').to_return(request_fixture('feed.txt')) - account = Fabricate(:account, - avatar_remote_url: 'https://remote/valid_avatar', - header_remote_url: 'https://remote/valid_avatar') + end + + let(:account) do + Fabricate(:account, + avatar_remote_url: 'https://remote/valid_avatar', + header_remote_url: 'https://remote/valid_avatar') + end + + let!(:expectation) { account.dup } + + context 'with valid properties' do + before do + account.save_with_optional_media! + end + + it 'unchanges avatar, header, avatar_remote_url, and header_remote_url' do + expect(account.avatar_remote_url).to eq expectation.avatar_remote_url + expect(account.header_remote_url).to eq expectation.header_remote_url + expect(account.avatar_file_name).to eq expectation.avatar_file_name + expect(account.header_file_name).to eq expectation.header_file_name + end + end - account.avatar_remote_url = 'https://remote/invalid_avatar' - account.save_with_optional_media! + context 'with invalid properties' do + before do + account.avatar_remote_url = 'https://remote/invalid_avatar' + account.save_with_optional_media! + end - account.reload - expect(account.avatar_remote_url).to eq '' - expect(account.header_remote_url).to eq '' - expect(account.avatar_file_name).to eq nil - expect(account.header_file_name).to eq nil + it 'sets default avatar, header, avatar_remote_url, and header_remote_url' do + expect(account.avatar_remote_url).to eq '' + expect(account.header_remote_url).to eq '' + expect(account.avatar_file_name).to eq nil + expect(account.header_file_name).to eq nil + end end end @@ -123,6 +146,61 @@ RSpec.describe Account, type: :model do end end + describe '#possibly_stale?' do + let(:account) { Fabricate(:account, last_webfingered_at: last_webfingered_at) } + + context 'last_webfingered_at is nil' do + let(:last_webfingered_at) { nil } + + it 'returns true' do + expect(account.possibly_stale?).to be true + end + end + + context 'last_webfingered_at is more than 24 hours before' do + let(:last_webfingered_at) { 25.hours.ago } + + it 'returns true' do + expect(account.possibly_stale?).to be true + end + end + + context 'last_webfingered_at is less than 24 hours before' do + let(:last_webfingered_at) { 23.hours.ago } + + it 'returns false' do + expect(account.possibly_stale?).to be false + end + end + end + + describe '#refresh!' do + let(:account) { Fabricate(:account, domain: domain) } + let(:acct) { account.acct } + + context 'domain is nil' do + let(:domain) { nil } + + it 'returns nil' do + expect(account.refresh!).to be_nil + end + + it 'calls not ResolveRemoteAccountService#call' do + expect_any_instance_of(ResolveRemoteAccountService).not_to receive(:call).with(acct) + account.refresh! + end + end + + context 'domain is present' do + let(:domain) { 'example.com' } + + it 'calls ResolveRemoteAccountService#call' do + expect_any_instance_of(ResolveRemoteAccountService).to receive(:call).with(acct).once + account.refresh! + end + end + end + describe '#to_param' do it 'returns username' do account = Fabricate(:account, username: 'alice') diff --git a/spec/models/concerns/account_interactions_spec.rb b/spec/models/concerns/account_interactions_spec.rb index f47d9d057..1e238e27c 100644 --- a/spec/models/concerns/account_interactions_spec.rb +++ b/spec/models/concerns/account_interactions_spec.rb @@ -2,38 +2,36 @@ require 'rails_helper' describe AccountInteractions do describe 'muting an account' do - before do - @me = Fabricate(:account, username: 'Me') - @you = Fabricate(:account, username: 'You') - end + let(:me) { Fabricate(:account, username: 'Me') } + let(:you) { Fabricate(:account, username: 'You') } context 'with the notifications option unspecified' do before do - @me.mute!(@you) + me.mute!(you) end it 'defaults to muting notifications' do - expect(@me.muting_notifications?(@you)).to be(true) + expect(me.muting_notifications?(you)).to be true end end context 'with the notifications option set to false' do before do - @me.mute!(@you, notifications: false) + me.mute!(you, notifications: false) end it 'does not mute notifications' do - expect(@me.muting_notifications?(@you)).to be(false) + expect(me.muting_notifications?(you)).to be false end end context 'with the notifications option set to true' do before do - @me.mute!(@you, notifications: true) + me.mute!(you, notifications: true) 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 diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb index cb51e9519..bb150b837 100644 --- a/spec/models/custom_emoji_spec.rb +++ b/spec/models/custom_emoji_spec.rb @@ -1,6 +1,35 @@ require 'rails_helper' RSpec.describe CustomEmoji, type: :model do + describe '#local?' do + let(:custom_emoji) { Fabricate(:custom_emoji, domain: domain) } + + subject { custom_emoji.local? } + + context 'domain is nil' do + let(:domain) { nil } + + it 'returns true' do + is_expected.to be true + end + end + + context 'domain is present' do + let(:domain) { 'example.com' } + + it 'returns false' do + is_expected.to be false + end + end + end + + describe '#object_type' do + it 'returns :emoji' do + custom_emoji = Fabricate(:custom_emoji) + expect(custom_emoji.object_type).to be :emoji + end + end + describe '.from_text' do let!(:emojo) { Fabricate(:custom_emoji) } diff --git a/spec/models/email_domain_block_spec.rb b/spec/models/email_domain_block_spec.rb index 5f5d189d9..efd2853a9 100644 --- a/spec/models/email_domain_block_spec.rb +++ b/spec/models/email_domain_block_spec.rb @@ -13,9 +13,10 @@ RSpec.describe EmailDomainBlock, type: :model do Fabricate(:email_domain_block, domain: 'example.com') expect(EmailDomainBlock.block?('nyarn@example.com')).to eq true end + it 'returns true if the domain is not registed' do - Fabricate(:email_domain_block, domain: 'domain') - expect(EmailDomainBlock.block?('example')).to eq false + Fabricate(:email_domain_block, domain: 'example.com') + expect(EmailDomainBlock.block?('nyarn@example.net')).to eq false end end end diff --git a/spec/models/follow_request_spec.rb b/spec/models/follow_request_spec.rb index 62bd724d7..7bc93a2aa 100644 --- a/spec/models/follow_request_spec.rb +++ b/spec/models/follow_request_spec.rb @@ -2,6 +2,17 @@ require 'rails_helper' RSpec.describe FollowRequest, type: :model do describe '#authorize!' do + let(:follow_request) { Fabricate(:follow_request, account: account, target_account: target_account) } + let(:account) { Fabricate(:account) } + let(:target_account) { Fabricate(:account) } + + it 'calls Account#follow!, MergeWorker.perform_async, and #destroy!' do + expect(account).to receive(:follow!).with(target_account, reblogs: true) + expect(MergeWorker).to receive(:perform_async).with(target_account.id, account.id) + expect(follow_request).to receive(:destroy!) + follow_request.authorize! + end + it 'generates a Follow' do follow_request = Fabricate.create(:follow_request) follow_request.authorize! @@ -23,25 +34,4 @@ RSpec.describe FollowRequest, type: :model do expect(follow_request.account.muting_reblogs?(target)).to be true end end - - describe '#reject!' - - describe 'validations' do - it 'has a valid fabricator' do - follow_request = Fabricate.build(:follow_request) - expect(follow_request).to be_valid - end - - it 'is invalid without an account' do - follow_request = Fabricate.build(:follow_request, account: nil) - follow_request.valid? - expect(follow_request).to model_have_error_on_field(:account) - end - - it 'is invalid without a target account' do - follow_request = Fabricate.build(:follow_request, target_account: nil) - follow_request.valid? - expect(follow_request).to model_have_error_on_field(:target_account) - end - end end diff --git a/spec/models/media_attachment_spec.rb b/spec/models/media_attachment_spec.rb index 435b4f326..b40a641f7 100644 --- a/spec/models/media_attachment_spec.rb +++ b/spec/models/media_attachment_spec.rb @@ -1,6 +1,83 @@ require 'rails_helper' RSpec.describe MediaAttachment, type: :model do + describe 'local?' do + let(:media_attachment) { Fabricate(:media_attachment, remote_url: remote_url) } + + subject { media_attachment.local? } + + context 'remote_url is blank' do + let(:remote_url) { '' } + + it 'returns true' do + is_expected.to be true + end + end + + context 'remote_url is present' do + let(:remote_url) { 'remote_url' } + + it 'returns false' do + is_expected.to be false + end + end + end + + describe 'needs_redownload?' do + let(:media_attachment) { Fabricate(:media_attachment, remote_url: remote_url, file: file) } + + subject { media_attachment.needs_redownload? } + + context 'file is blank' do + let(:file) { nil } + + context 'remote_url is blank' do + let(:remote_url) { '' } + + it 'returns false' do + is_expected.to be false + end + end + + context 'remote_url is present' do + let(:remote_url) { 'remote_url' } + + it 'returns true' do + is_expected.to be true + end + end + end + + context 'file is present' do + let(:file) { attachment_fixture('avatar.gif') } + + context 'remote_url is blank' do + let(:remote_url) { '' } + + it 'returns false' do + is_expected.to be false + end + end + + context 'remote_url is present' do + let(:remote_url) { 'remote_url' } + + it 'returns true' do + is_expected.to be false + end + end + end + end + + describe '#to_param' do + let(:media_attachment) { Fabricate(:media_attachment) } + let(:shortcode) { media_attachment.shortcode } + + it 'returns shortcode' do + expect(media_attachment.to_param).to eq shortcode + end + end + describe 'animated gif conversion' do let(:media) { MediaAttachment.create(account: Fabricate(:account), file: attachment_fixture('avatar.gif')) } diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 97e8095cd..763b1523f 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -5,6 +5,74 @@ RSpec.describe Notification, type: :model do pending end + describe '#target_status' do + before do + allow(notification).to receive(:type).and_return(type) + allow(notification).to receive(:activity).and_return(activity) + end + + let(:notification) { Fabricate(:notification) } + let(:status) { instance_double('Status') } + let(:favourite) { instance_double('Favourite') } + let(:mention) { instance_double('Mention') } + + context 'type is :reblog' do + let(:type) { :reblog } + let(:activity) { status } + + it 'calls activity.reblog' do + expect(activity).to receive(:reblog) + notification.target_status + end + end + + context 'type is :favourite' do + let(:type) { :favourite } + let(:activity) { favourite } + + it 'calls activity.status' do + expect(activity).to receive(:status) + notification.target_status + end + end + + context 'type is :mention' do + let(:type) { :mention } + let(:activity) { mention } + + it 'calls activity.status' do + expect(activity).to receive(:status) + notification.target_status + end + end + end + + describe '#browserable?' do + let(:notification) { Fabricate(:notification) } + + subject { notification.browserable? } + + context 'type is :follow_request' do + before do + allow(notification).to receive(:type).and_return(:follow_request) + end + + it 'returns false' do + is_expected.to be false + end + end + + context 'type is not :follow_request' do + before do + allow(notification).to receive(:type).and_return(:else) + end + + it 'returns true' do + is_expected.to be true + end + end + end + describe '#type' do it 'returns :reblog for a Status' do notification = Notification.new(activity: Status.new) @@ -26,4 +94,49 @@ RSpec.describe Notification, type: :model do expect(notification.type).to eq :follow end end + + describe '.reload_stale_associations!' do + context 'account_ids are empty' do + let(:cached_items) { [] } + + subject { described_class.reload_stale_associations!(cached_items) } + + it 'returns nil' do + is_expected.to be nil + end + end + + context 'account_ids are present' do + before do + allow(accounts_with_ids).to receive(:[]).with(stale_account1.id).and_return(account1) + allow(accounts_with_ids).to receive(:[]).with(stale_account2.id).and_return(account2) + allow(Account).to receive_message_chain(:where, :map, :to_h).and_return(accounts_with_ids) + end + + let(:cached_items) do + [ + Fabricate(:notification, activity: Fabricate(:status)), + Fabricate(:notification, activity: Fabricate(:follow)), + ] + end + + let(:stale_account1) { cached_items[0].from_account } + let(:stale_account2) { cached_items[1].from_account } + + let(:account1) { Fabricate(:account) } + let(:account2) { Fabricate(:account) } + + let(:accounts_with_ids) { { account1.id => account1, account2.id => account2 } } + + it 'reloads associations' do + expect(cached_items[0].from_account).to be stale_account1 + expect(cached_items[1].from_account).to be stale_account2 + + described_class.reload_stale_associations!(cached_items) + + expect(cached_items[0].from_account).to be account1 + expect(cached_items[1].from_account).to be account2 + end + end + end end diff --git a/spec/models/remote_follow_spec.rb b/spec/models/remote_follow_spec.rb new file mode 100644 index 000000000..7a4597ee7 --- /dev/null +++ b/spec/models/remote_follow_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe RemoteFollow do + before do + stub_request(:get, 'https://quitter.no/.well-known/webfinger?resource=acct:gargron@quitter.no').to_return(request_fixture('webfinger.txt')) + end + + let(:attrs) { nil } + let(:remote_follow) { described_class.new(attrs) } + + describe '.initialize' do + subject { remote_follow.acct } + + context 'attrs with acct' do + let(:attrs) { { acct: 'gargron@quitter.no' } } + + it 'returns acct' do + is_expected.to eq 'gargron@quitter.no' + end + end + + context 'attrs without acct' do + let(:attrs) { {} } + + it do + is_expected.to be_nil + end + end + end + + describe '#valid?' do + subject { remote_follow.valid? } + + context 'attrs with acct' do + let(:attrs) { { acct: 'gargron@quitter.no' }} + + it do + is_expected.to be true + end + end + + context 'attrs without acct' do + let(:attrs) { { } } + + it do + is_expected.to be false + end + end + end + + describe '#subscribe_address_for' do + before do + remote_follow.valid? + end + + let(:attrs) { { acct: 'gargron@quitter.no' } } + let(:account) { Fabricate(:account, username: 'alice') } + + subject { remote_follow.subscribe_address_for(account) } + + it 'returns subscribe address' do + is_expected.to eq 'https://quitter.no/main/ostatussub?profile=alice%40cb6e6126.ngrok.io' + end + end +end diff --git a/spec/models/remote_profile_spec.rb b/spec/models/remote_profile_spec.rb new file mode 100644 index 000000000..da5048f0a --- /dev/null +++ b/spec/models/remote_profile_spec.rb @@ -0,0 +1,143 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe RemoteProfile do + let(:remote_profile) { RemoteProfile.new(body) } + let(:body) do + <<-XML + <feed xmlns="http://www.w3.org/2005/Atom"> + <author>John</author> + XML + end + + describe '.initialize' do + it 'calls Nokogiri::XML.parse' do + expect(Nokogiri::XML).to receive(:parse).with(body, nil, 'utf-8') + RemoteProfile.new(body) + end + + it 'sets document' do + remote_profile = RemoteProfile.new(body) + expect(remote_profile).not_to be nil + end + end + + describe '#root' do + let(:document) { remote_profile.document } + + it 'callse document.at_xpath' do + expect(document).to receive(:at_xpath).with( + '/atom:feed|/atom:entry', + atom: OStatus::TagManager::XMLNS + ) + + remote_profile.root + end + end + + describe '#author' do + let(:root) { remote_profile.root } + + it 'calls root.at_xpath' do + expect(root).to receive(:at_xpath).with( + './atom:author|./dfrn:owner', + atom: OStatus::TagManager::XMLNS, + dfrn: OStatus::TagManager::DFRN_XMLNS + ) + + remote_profile.author + end + end + + describe '#hub_link' do + let(:root) { remote_profile.root } + + it 'calls #link_href_from_xml' do + expect(remote_profile).to receive(:link_href_from_xml).with(root, 'hub') + remote_profile.hub_link + end + end + + describe '#display_name' do + let(:author) { remote_profile.author } + + it 'calls author.at_xpath.content' do + expect(author).to receive_message_chain(:at_xpath, :content).with( + './poco:displayName', + poco: OStatus::TagManager::POCO_XMLNS + ).with(no_args) + + remote_profile.display_name + end + end + + describe '#note' do + let(:author) { remote_profile.author } + + it 'calls author.at_xpath.content' do + expect(author).to receive_message_chain(:at_xpath, :content).with( + './atom:summary|./poco:note', + atom: OStatus::TagManager::XMLNS, + poco: OStatus::TagManager::POCO_XMLNS + ).with(no_args) + + remote_profile.note + end + end + + describe '#scope' do + let(:author) { remote_profile.author } + + it 'calls author.at_xpath.content' do + expect(author).to receive_message_chain(:at_xpath, :content).with( + './mastodon:scope', + mastodon: OStatus::TagManager::MTDN_XMLNS + ).with(no_args) + + remote_profile.scope + end + end + + describe '#avatar' do + let(:author) { remote_profile.author } + + it 'calls #link_href_from_xml' do + expect(remote_profile).to receive(:link_href_from_xml).with(author, 'avatar') + remote_profile.avatar + end + end + + describe '#header' do + let(:author) { remote_profile.author } + + it 'calls #link_href_from_xml' do + expect(remote_profile).to receive(:link_href_from_xml).with(author, 'header') + remote_profile.header + end + end + + describe '#locked?' do + before do + allow(remote_profile).to receive(:scope).and_return(scope) + end + + subject { remote_profile.locked? } + + context 'scope is private' do + let(:scope) { 'private' } + + it 'returns true' do + is_expected.to be true + end + end + + context 'scope is not private' do + let(:scope) { 'public' } + + it 'returns false' do + is_expected.to be false + end + end + end +end diff --git a/spec/models/session_activation_spec.rb b/spec/models/session_activation_spec.rb index 49c72fbd4..2aa695037 100644 --- a/spec/models/session_activation_spec.rb +++ b/spec/models/session_activation_spec.rb @@ -1,5 +1,127 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe SessionActivation, type: :model do - pending "add some examples to (or delete) #{__FILE__}" + describe '#detection' do + let(:session_activation) { Fabricate(:session_activation, user_agent: 'Chrome/62.0.3202.89') } + + it 'sets a Browser instance as detection' do + expect(session_activation.detection).to be_kind_of Browser::Chrome + end + end + + describe '#browser' do + before do + allow(session_activation).to receive(:detection).and_return(detection) + end + + let(:detection) { double(id: 1) } + let(:session_activation) { Fabricate(:session_activation) } + + it 'returns detection.id' do + expect(session_activation.browser).to be 1 + end + end + + describe '#platform' do + before do + allow(session_activation).to receive(:detection).and_return(detection) + end + + let(:session_activation) { Fabricate(:session_activation) } + let(:detection) { double(platform: double(id: 1)) } + + it 'returns detection.platform.id' do + expect(session_activation.platform).to be 1 + end + end + + describe '.active?' do + subject { described_class.active?(id) } + + context 'id is absent' do + let(:id) { nil } + + it 'returns nil' do + is_expected.to be nil + end + end + + context 'id is present' do + let(:id) { '1' } + let!(:session_activation) { Fabricate(:session_activation, session_id: id) } + + context 'id exists as session_id' do + it 'returns true' do + is_expected.to be true + end + end + + context 'id does not exist as session_id' do + before do + session_activation.update!(session_id: '2') + end + + it 'returns false' do + is_expected.to be false + end + end + end + end + + describe '.activate' do + let(:options) { { user: Fabricate(:user), session_id: '1' } } + + it 'calls create! and purge_old' do + expect(described_class).to receive(:create!).with(options) + expect(described_class).to receive(:purge_old) + described_class.activate(options) + end + + it 'returns an instance of SessionActivation' do + expect(described_class.activate(options)).to be_kind_of SessionActivation + end + end + + describe '.deactivate' do + context 'id is absent' do + let(:id) { nil } + + it 'returns nil' do + expect(described_class.deactivate(id)).to be nil + end + end + + context 'id exists' do + let(:id) { '1' } + + it 'calls where.destroy_all' do + expect(described_class).to receive_message_chain(:where, :destroy_all) + .with(session_id: id).with(no_args) + + described_class.deactivate(id) + end + end + end + + describe '.purge_old' do + it 'calls order.offset.destroy_all' do + expect(described_class).to receive_message_chain(:order, :offset, :destroy_all) + .with('created_at desc').with(Rails.configuration.x.max_session_activations).with(no_args) + + described_class.purge_old + end + end + + describe '.exclusive' do + let(:id) { '1' } + + it 'calls where.destroy_all' do + expect(described_class).to receive_message_chain(:where, :destroy_all) + .with('session_id != ?', id).with(no_args) + + described_class.exclusive(id) + end + end end diff --git a/spec/models/setting_spec.rb b/spec/models/setting_spec.rb new file mode 100644 index 000000000..e99dfc0d7 --- /dev/null +++ b/spec/models/setting_spec.rb @@ -0,0 +1,184 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Setting, type: :model do + describe '#to_param' do + let(:setting) { Fabricate(:setting, var: var) } + let(:var) { 'var' } + + it 'returns setting.var' do + expect(setting.to_param).to eq var + end + end + + describe '.[]' do + before do + allow(described_class).to receive(:rails_initialized?).and_return(rails_initialized) + end + + let(:key) { 'key' } + + context 'rails_initialized? is falsey' do + let(:rails_initialized) { false } + + it 'calls RailsSettings::Base#[]' do + expect(RailsSettings::Base).to receive(:[]).with(key) + described_class[key] + end + end + + context 'rails_initialized? is truthy' do + before do + allow(RailsSettings::Base).to receive(:cache_key).with(key, nil).and_return(cache_key) + end + + let(:rails_initialized) { true } + let(:cache_key) { 'cache-key' } + let(:cache_value) { 'cache-value' } + + it 'calls not RailsSettings::Base#[]' do + expect(RailsSettings::Base).not_to receive(:[]).with(key) + described_class[key] + end + + it 'calls Rails.cache.fetch' do + expect(Rails).to receive_message_chain(:cache, :fetch).with(cache_key) + described_class[key] + end + + context 'Rails.cache does not exists' do + before do + allow(RailsSettings::Settings).to receive(:object).with(key).and_return(object) + allow(described_class).to receive(:default_settings).and_return(default_settings) + allow_any_instance_of(Settings::ScopedSettings).to receive(:thing_scoped).and_return(records) + Rails.cache.clear(cache_key) + end + + let(:object) { nil } + let(:default_value) { 'default_value' } + let(:default_settings) { { key => default_value } } + let(:records) { [Fabricate(:setting, var: key, value: nil)] } + + it 'calls RailsSettings::Settings.object' do + expect(RailsSettings::Settings).to receive(:object).with(key) + described_class[key] + end + + context 'RailsSettings::Settings.object returns truthy' do + let(:object) { db_val } + let(:db_val) { double(value: 'db_val') } + + context 'default_value is a Hash' do + let(:default_value) { { default_value: 'default_value' } } + + it 'calls default_value.with_indifferent_access.merge!' do + expect(default_value).to receive_message_chain(:with_indifferent_access, :merge!) + .with(db_val.value) + + described_class[key] + end + end + + context 'default_value is not a Hash' do + let(:default_value) { 'default_value' } + + it 'returns db_val.value' do + expect(described_class[key]).to be db_val.value + end + end + end + + context 'RailsSettings::Settings.object returns falsey' do + let(:object) { nil } + + it 'returns default_settings[key]' do + expect(described_class[key]).to be default_settings[key] + end + end + end + + context 'Rails.cache exists' do + before do + Rails.cache.write(cache_key, cache_value) + end + + it 'returns the cached value' do + expect(described_class[key]).to eq cache_value + end + end + end + end + + describe '.all_as_records' do + before do + allow_any_instance_of(Settings::ScopedSettings).to receive(:thing_scoped).and_return(records) + allow(described_class).to receive(:default_settings).and_return(default_settings) + end + + let(:key) { 'key' } + let(:default_value) { 'default_value' } + let(:default_settings) { { key => default_value } } + let(:original_setting) { Fabricate(:setting, var: key, value: nil) } + let(:records) { [original_setting] } + + it 'returns a Hash' do + expect(described_class.all_as_records).to be_kind_of Hash + end + + context 'records includes Setting with var as the key' do + let(:records) { [original_setting] } + + it 'includes the original Setting' do + setting = described_class.all_as_records[key] + expect(setting).to eq original_setting + end + end + + context 'records includes nothing' do + let(:records) { [] } + + context 'default_value is not a Hash' do + it 'includes Setting with value of default_value' do + setting = described_class.all_as_records[key] + + expect(setting).to be_kind_of Setting + expect(setting).to have_attributes(var: key) + expect(setting).to have_attributes(value: 'default_value') + end + end + + context 'default_value is a Hash' do + let(:default_value) { { 'foo' => 'fuga' } } + + it 'returns {}' do + expect(described_class.all_as_records).to eq({}) + end + end + end + end + + describe '.default_settings' do + before do + allow(RailsSettings::Default).to receive(:enabled?).and_return(enabled) + end + + subject { described_class.default_settings } + + context 'RailsSettings::Default.enabled? is false' do + let(:enabled) { false } + + it 'returns {}' do + is_expected.to eq({}) + end + end + + context 'RailsSettings::Settings.enabled? is true' do + let(:enabled) { true } + + it 'returns instance of RailsSettings::Default' do + is_expected.to be_kind_of RailsSettings::Default + end + end + end +end diff --git a/spec/models/site_upload_spec.rb b/spec/models/site_upload_spec.rb index 8745d54b8..f7ea06921 100644 --- a/spec/models/site_upload_spec.rb +++ b/spec/models/site_upload_spec.rb @@ -1,5 +1,13 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe SiteUpload, type: :model do + describe '#cache_key' do + let(:site_upload) { SiteUpload.new(var: 'var') } + it 'returns cache_key' do + expect(site_upload.cache_key).to eq 'site_uploads/var' + end + end end diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index 12e857169..91fd13c94 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -69,6 +69,36 @@ RSpec.describe Status, type: :model do end end + describe '#hidden?' do + context 'if private_visibility?' do + it 'returns true' do + subject.visibility = :private + expect(subject.hidden?).to be true + end + end + + context 'if direct_visibility?' do + it 'returns true' do + subject.visibility = :direct + expect(subject.hidden?).to be true + end + end + + context 'if public_visibility?' do + it 'returns false' do + subject.visibility = :public + expect(subject.hidden?).to be false + end + end + + context 'if unlisted_visibility?' do + it 'returns false' do + subject.visibility = :unlisted + expect(subject.hidden?).to be false + end + end + end + describe '#content' do it 'returns the text of the status if it is not a reblog' do expect(subject.content).to eql subject.text diff --git a/spec/models/stream_entry_spec.rb b/spec/models/stream_entry_spec.rb index 3b7ff5143..8f8bfbd58 100644 --- a/spec/models/stream_entry_spec.rb +++ b/spec/models/stream_entry_spec.rb @@ -6,6 +6,121 @@ RSpec.describe StreamEntry, type: :model do let(:status) { Fabricate(:status, account: alice) } let(:reblog) { Fabricate(:status, account: bob, reblog: status) } let(:reply) { Fabricate(:status, account: bob, thread: status) } + let(:stream_entry) { Fabricate(:stream_entry, activity: activity) } + let(:activity) { reblog } + + describe '#object_type' do + before do + allow(stream_entry).to receive(:orphaned?).and_return(orphaned) + allow(stream_entry).to receive(:targeted?).and_return(targeted) + end + + subject { stream_entry.object_type } + + context 'orphaned? is true' do + let(:orphaned) { true } + let(:targeted) { false } + + it 'returns :activity' do + is_expected.to be :activity + end + end + + context 'targeted? is true' do + let(:orphaned) { false } + let(:targeted) { true } + + it 'returns :activity' do + is_expected.to be :activity + end + end + + context 'orphaned? and targeted? are false' do + let(:orphaned) { false } + let(:targeted) { false } + + context 'activity is reblog' do + let(:activity) { reblog } + + it 'returns :note' do + is_expected.to be :note + end + end + + context 'activity is reply' do + let(:activity) { reply } + + it 'returns :comment' do + is_expected.to be :comment + end + end + end + end + + describe '#verb' do + before do + allow(stream_entry).to receive(:orphaned?).and_return(orphaned) + end + + subject { stream_entry.verb } + + context 'orphaned? is true' do + let(:orphaned) { true } + + it 'returns :delete' do + is_expected.to be :delete + end + end + + context 'orphaned? is false' do + let(:orphaned) { false } + + context 'activity is reblog' do + let(:activity) { reblog } + + it 'returns :share' do + is_expected.to be :share + end + end + + context 'activity is reply' do + let(:activity) { reply } + + it 'returns :post' do + is_expected.to be :post + end + end + end + end + + describe '#mentions' do + before do + allow(stream_entry).to receive(:orphaned?).and_return(orphaned) + end + + subject { stream_entry.mentions } + + context 'orphaned? is true' do + let(:orphaned) { true } + + it 'returns []' do + is_expected.to eq [] + end + end + + context 'orphaned? is false' do + before do + reblog.mentions << Fabricate(:mention, account: alice) + reblog.mentions << Fabricate(:mention, account: bob) + end + + let(:orphaned) { false } + + it 'returns [Account] includes alice and bob' do + is_expected.to eq [alice, bob] + end + end + end describe '#targeted?' do it 'returns true for a reblog' do diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb index f727fa1dd..1ca50cc29 100644 --- a/spec/models/tag_spec.rb +++ b/spec/models/tag_spec.rb @@ -35,6 +35,13 @@ RSpec.describe Tag, type: :model do end end + describe '#to_param' do + it 'returns name' do + tag = Fabricate(:tag, name: 'foo') + expect(tag.to_param).to eq 'foo' + end + end + describe '.search_for' do it 'finds tag records with matching names' do tag = Fabricate(:tag, name: "match") diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 99aeca01b..77a12c26d 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -177,27 +177,10 @@ RSpec.describe User, type: :model do end end - describe '#setting_auto_play_gif' do - it 'returns auto-play gif setting' do + describe 'settings' do + it 'is instance of Settings::ScopedSettings' do user = Fabricate(:user) - user.settings[:auto_play_gif] = false - expect(user.setting_auto_play_gif).to eq false - end - end - - describe '#setting_system_font_ui' do - it 'returns system font ui setting' do - user = Fabricate(:user) - user.settings[:system_font_ui] = false - expect(user.setting_system_font_ui).to eq false - end - end - - describe '#setting_boost_modal' do - it 'returns boost modal setting' do - user = Fabricate(:user) - user.settings[:boost_modal] = false - expect(user.setting_boost_modal).to eq false + expect(user.settings).to be_kind_of Settings::ScopedSettings end end @@ -219,22 +202,6 @@ RSpec.describe User, type: :model do end end - describe '#setting_unfollow_modal' do - it 'returns unfollow modal setting' do - user = Fabricate(:user) - user.settings[:unfollow_modal] = true - expect(user.setting_unfollow_modal).to eq true - end - end - - describe '#setting_delete_modal' do - it 'returns delete modal setting' do - user = Fabricate(:user) - user.settings[:delete_modal] = false - expect(user.setting_delete_modal).to eq false - end - end - describe 'whitelist' do around(:each) do |example| old_whitelist = Rails.configuration.x.email_whitelist |