]>
cat aescling's git repositories - mastodon.git/blob - spec/models/status_spec.rb
3 RSpec
.describe Status
, type
: :model do
4 let(:alice) { Fabricate(:account, username
: 'alice') }
5 let(:bob) { Fabricate(:account, username
: 'bob') }
6 let(:other) { Fabricate(:status, account
: bob
, text
: 'Skulls for the skull god! The enemy
\'s gates are sideways!
') }
8 subject { Fabricate(:status, account: alice) }
11 it
'returns true when no remote URI is set' do
12 expect(subject
.local
?).to be
true
15 it
'returns false if a remote URI is set' do
16 alice
.update(domain
: 'example.com')
18 expect(subject
.local
?).to be
false
21 it
'returns true if a URI is set and `local` is true' do
22 subject
.update(uri
: 'example.com', local
: true)
23 expect(subject
.local
?).to be
true
27 describe
'#reblog?' do
28 it
'returns true when the status reblogs another status' do
29 subject
.reblog
= other
30 expect(subject
.reblog
?).to be
true
33 it
'returns false if the status is self-contained' do
34 expect(subject
.reblog
?).to be
false
39 it
'returns true if the status references another' do
40 subject
.thread
= other
41 expect(subject
.reply
?).to be
true
44 it
'returns false if the status is self-contained' do
45 expect(subject
.reply
?).to be
false
50 context
'if destroyed?' do
51 it
'returns :delete' do
53 expect(subject
.verb
).to be
:delete
57 context
'unless destroyed?' do
58 context
'if reblog?' do
59 it
'returns :share' do
60 subject
.reblog
= other
61 expect(subject
.verb
).to be
:share
65 context
'unless reblog?' do
68 expect(subject
.verb
).to be
:post
74 describe
'#object_type' do
75 it
'is note when the status is self-contained' do
76 expect(subject
.object_type
).to be
:note
79 it
'is comment when the status replies to another' do
80 subject
.thread
= other
81 expect(subject
.object_type
).to be
:comment
86 # rubocop:disable Style/InterpolationCheck
88 let(:account) { subject
.account
}
90 context
'if destroyed?' do
91 it
'returns "#{account.acct} deleted status"' do
93 expect(subject
.title
).to eq
"#{account.acct} deleted status"
97 context
'unless destroyed?' do
98 context
'if reblog?' do
99 it
'returns "#{account.acct} shared a status by #{reblog.account.acct}"' do
100 reblog
= subject
.reblog
= other
101 expect(subject
.title
).to eq
"#{account.acct} shared a status by #{reblog.account.acct}"
105 context
'unless reblog?' do
106 it
'returns "New status by #{account.acct}"' do
108 expect(subject
.title
).to eq
"New status by #{account.acct}"
114 describe
'#hidden?' do
115 context
'if private_visibility?' do
117 subject
.visibility
= :private
118 expect(subject
.hidden
?).to be
true
122 context
'if direct_visibility?' do
124 subject
.visibility
= :direct
125 expect(subject
.hidden
?).to be
true
129 context
'if public_visibility?' do
130 it
'returns false' do
131 subject
.visibility
= :public
132 expect(subject
.hidden
?).to be
false
136 context
'if unlisted_visibility?' do
137 it
'returns false' do
138 subject
.visibility
= :unlisted
139 expect(subject
.hidden
?).to be
false
144 describe
'#content' do
145 it
'returns the text of the status if it is not a reblog' do
146 expect(subject
.content
).to eql subject
.text
149 it
'returns the text of the reblogged status' do
150 subject
.reblog
= other
151 expect(subject
.content
).to eql other
.text
155 describe
'#target' do
156 it
'returns nil if the status is self-contained' do
157 expect(subject
.target
).to be_nil
160 it
'returns nil if the status is a reply' do
161 subject
.thread
= other
162 expect(subject
.target
).to be_nil
165 it
'returns the reblogged status' do
166 subject
.reblog
= other
167 expect(subject
.target
).to eq other
171 describe
'#reblogs_count' do
172 it
'is the number of reblogs' do
173 Fabricate(:status, account
: bob
, reblog
: subject
)
174 Fabricate(:status, account
: alice
, reblog
: subject
)
176 expect(subject
.reblogs_count
).to eq
2
179 it
'is decremented when reblog is removed' do
180 reblog
= Fabricate(:status, account
: bob
, reblog
: subject
)
181 expect(subject
.reblogs_count
).to eq
1
183 expect(subject
.reblogs_count
).to eq
0
186 it
'does not fail when original is deleted before reblog' do
187 reblog
= Fabricate(:status, account
: bob
, reblog
: subject
)
188 expect(subject
.reblogs_count
).to eq
1
189 expect
{ subject
.destroy
}.to_not raise_error
190 expect(Status
.find_by(id
: reblog
.id
)).to be_nil
194 describe
'#replies_count' do
195 it
'is the number of replies' do
196 reply
= Fabricate(:status, account
: bob
, thread
: subject
)
197 expect(subject
.replies_count
).to eq
1
200 it
'is decremented when reply is removed' do
201 reply
= Fabricate(:status, account
: bob
, thread
: subject
)
202 expect(subject
.replies_count
).to eq
1
204 expect(subject
.replies_count
).to eq
0
208 describe
'#favourites_count' do
209 it
'is the number of favorites' do
210 Fabricate(:favourite, account
: bob
, status
: subject
)
211 Fabricate(:favourite, account
: alice
, status
: subject
)
213 expect(subject
.favourites_count
).to eq
2
216 it
'is decremented when favourite is removed' do
217 favourite
= Fabricate(:favourite, account
: bob
, status
: subject
)
218 expect(subject
.favourites_count
).to eq
1
220 expect(subject
.favourites_count
).to eq
0
224 describe
'#proper' do
225 it
'is itself for original statuses' do
226 expect(subject
.proper
).to eq subject
229 it
'is the source status for reblogs' do
230 subject
.reblog
= other
231 expect(subject
.proper
).to eq other
235 describe
'.mutes_map' do
236 let(:status) { Fabricate(:status) }
237 let(:account) { Fabricate(:account) }
239 subject
{ Status
.mutes_map([status
.conversation
.id
], account
) }
241 it
'returns a hash' do
242 expect(subject
).to be_a Hash
245 it
'contains true value' do
246 account
.mute_conversation!
(status
.conversation
)
247 expect(subject
[status
.conversation
.id
]).to be
true
251 describe
'.favourites_map' do
252 let(:status) { Fabricate(:status) }
253 let(:account) { Fabricate(:account) }
255 subject
{ Status
.favourites_map([status
], account
) }
257 it
'returns a hash' do
258 expect(subject
).to be_a Hash
261 it
'contains true value' do
262 Fabricate(:favourite, status
: status
, account
: account
)
263 expect(subject
[status
.id
]).to be
true
267 describe
'.reblogs_map' do
268 let(:status) { Fabricate(:status) }
269 let(:account) { Fabricate(:account) }
271 subject
{ Status
.reblogs_map([status
], account
) }
273 it
'returns a hash' do
274 expect(subject
).to be_a Hash
277 it
'contains true value' do
278 Fabricate(:status, account
: account
, reblog
: status
)
279 expect(subject
[status
.id
]).to be
true
283 describe
'.in_chosen_languages' do
284 context
'for accounts with language filters' do
285 let(:user) { Fabricate(:user, chosen_languages
: ['en']) }
287 it
'does not include statuses in not in chosen languages' do
288 status
= Fabricate(:status, language
: 'de')
289 expect(Status
.in_chosen_languages(user
.account
)).not_to
include status
292 it
'includes status with unknown language' do
293 status
= Fabricate(:status, language
: nil)
294 expect(Status
.in_chosen_languages(user
.account
)).to
include status
299 describe
'.as_home_timeline' do
300 let(:account) { Fabricate(:account) }
301 let(:followed) { Fabricate(:account) }
302 let(:not_followed) { Fabricate(:account) }
305 Fabricate(:follow, account
: account
, target_account
: followed
)
307 @self_status = Fabricate(:status, account
: account
, visibility
: :public)
308 @self_direct_status = Fabricate(:status, account
: account
, visibility
: :direct)
309 @followed_status = Fabricate(:status, account
: followed
, visibility
: :public)
310 @followed_direct_status = Fabricate(:status, account
: followed
, visibility
: :direct)
311 @not_followed_status = Fabricate(:status, account
: not_followed
, visibility
: :public)
313 @results = Status
.as_home_timeline(account
)
316 it
'includes statuses from self' do
317 expect(@results).to
include(@self_status)
320 it
'does not include direct statuses from self' do
321 expect(@results).to_not
include(@self_direct_status)
324 it
'includes statuses from followed' do
325 expect(@results).to
include(@followed_status)
328 it
'does not include direct statuses mentioning recipient from followed' do
329 Fabricate(:mention, account
: account
, status
: @followed_direct_status)
330 expect(@results).to_not
include(@followed_direct_status)
333 it
'does not include direct statuses not mentioning recipient from followed' do
334 expect(@results).not_to
include(@followed_direct_status)
337 it
'does not include statuses from non-followed' do
338 expect(@results).not_to
include(@not_followed_status)
342 describe
'.as_direct_timeline' do
343 let(:account) { Fabricate(:account) }
344 let(:followed) { Fabricate(:account) }
345 let(:not_followed) { Fabricate(:account) }
348 Fabricate(:follow, account
: account
, target_account
: followed
)
350 @self_public_status = Fabricate(:status, account
: account
, visibility
: :public)
351 @self_direct_status = Fabricate(:status, account
: account
, visibility
: :direct)
352 @followed_public_status = Fabricate(:status, account
: followed
, visibility
: :public)
353 @followed_direct_status = Fabricate(:status, account
: followed
, visibility
: :direct)
354 @not_followed_direct_status = Fabricate(:status, account
: not_followed
, visibility
: :direct)
356 @results = Status
.as_direct_timeline(account
)
359 it
'does not include public statuses from self' do
360 expect(@results).to_not
include(@self_public_status)
363 it
'includes direct statuses from self' do
364 expect(@results).to
include(@self_direct_status)
367 it
'does not include public statuses from followed' do
368 expect(@results).to_not
include(@followed_public_status)
371 it
'does not include direct statuses not mentioning recipient from followed' do
372 expect(@results).to_not
include(@followed_direct_status)
375 it
'does not include direct statuses not mentioning recipient from non-followed' do
376 expect(@results).to_not
include(@not_followed_direct_status)
379 it
'includes direct statuses mentioning recipient from followed' do
380 Fabricate(:mention, account
: account
, status
: @followed_direct_status)
381 results2
= Status
.as_direct_timeline(account
)
382 expect(results2
).to
include(@followed_direct_status)
385 it
'includes direct statuses mentioning recipient from non-followed' do
386 Fabricate(:mention, account
: account
, status
: @not_followed_direct_status)
387 results2
= Status
.as_direct_timeline(account
)
388 expect(results2
).to
include(@not_followed_direct_status)
392 describe
'.as_public_timeline' do
393 it
'only includes statuses with public visibility' do
394 public_status
= Fabricate(:status, visibility
: :public)
395 private_status
= Fabricate(:status, visibility
: :private)
397 results
= Status
.as_public_timeline
398 expect(results
).to
include(public_status
)
399 expect(results
).not_to
include(private_status
)
402 it
'does not include replies' do
403 status
= Fabricate(:status)
404 reply
= Fabricate(:status, in_reply_to_id
: status
.id
)
406 results
= Status
.as_public_timeline
407 expect(results
).to
include(status
)
408 expect(results
).not_to
include(reply
)
411 it
'does not include boosts' do
412 status
= Fabricate(:status)
413 boost
= Fabricate(:status, reblog_of_id
: status
.id
)
415 results
= Status
.as_public_timeline
416 expect(results
).to
include(status
)
417 expect(results
).not_to
include(boost
)
420 it
'filters out silenced accounts' do
421 account
= Fabricate(:account)
422 silenced_account
= Fabricate(:account, silenced
: true)
423 status
= Fabricate(:status, account
: account
)
424 silenced_status
= Fabricate(:status, account
: silenced_account
)
426 results
= Status
.as_public_timeline
427 expect(results
).to
include(status
)
428 expect(results
).not_to
include(silenced_status
)
431 context
'without local_only option' do
434 let!
(:local_account) { Fabricate(:account, domain
: nil) }
435 let!
(:remote_account) { Fabricate(:account, domain
: 'test.com') }
436 let!
(:local_status) { Fabricate(:status, account
: local_account
) }
437 let!
(:remote_status) { Fabricate(:status, account
: remote_account
) }
439 subject
{ Status
.as_public_timeline(viewer
, false) }
441 context
'without a viewer' do
444 it
'includes remote instances statuses' do
445 expect(subject
).to
include(remote_status
)
448 it
'includes local statuses' do
449 expect(subject
).to
include(local_status
)
453 context
'with a viewer' do
454 let(:viewer) { Fabricate(:account, username
: 'viewer') }
456 it
'includes remote instances statuses' do
457 expect(subject
).to
include(remote_status
)
460 it
'includes local statuses' do
461 expect(subject
).to
include(local_status
)
466 context
'with a local_only option set' do
467 let!
(:local_account) { Fabricate(:account, domain
: nil) }
468 let!
(:remote_account) { Fabricate(:account, domain
: 'test.com') }
469 let!
(:local_status) { Fabricate(:status, account
: local_account
) }
470 let!
(:remote_status) { Fabricate(:status, account
: remote_account
) }
472 subject
{ Status
.as_public_timeline(viewer
, true) }
474 context
'without a viewer' do
477 it
'does not include remote instances statuses' do
478 expect(subject
).to
include(local_status
)
479 expect(subject
).not_to
include(remote_status
)
483 context
'with a viewer' do
484 let(:viewer) { Fabricate(:account, username
: 'viewer') }
486 it
'does not include remote instances statuses' do
487 expect(subject
).to
include(local_status
)
488 expect(subject
).not_to
include(remote_status
)
491 it
'is not affected by personal domain blocks' do
492 viewer
.block_domain!
('test.com')
493 expect(subject
).to
include(local_status
)
494 expect(subject
).not_to
include(remote_status
)
499 describe
'with an account passed in' do
501 @account = Fabricate(:account)
504 it
'excludes statuses from accounts blocked by the account' do
505 blocked
= Fabricate(:account)
506 Fabricate(:block, account
: @account, target_account
: blocked
)
507 blocked_status
= Fabricate(:status, account
: blocked
)
509 results
= Status
.as_public_timeline(@account)
510 expect(results
).not_to
include(blocked_status
)
513 it
'excludes statuses from accounts who have blocked the account' do
514 blocked
= Fabricate(:account)
515 Fabricate(:block, account
: blocked
, target_account
: @account)
516 blocked_status
= Fabricate(:status, account
: blocked
)
518 results
= Status
.as_public_timeline(@account)
519 expect(results
).not_to
include(blocked_status
)
522 it
'excludes statuses from accounts muted by the account' do
523 muted
= Fabricate(:account)
524 Fabricate(:mute, account
: @account, target_account
: muted
)
525 muted_status
= Fabricate(:status, account
: muted
)
527 results
= Status
.as_public_timeline(@account)
528 expect(results
).not_to
include(muted_status
)
531 it
'excludes statuses from accounts from personally blocked domains' do
532 blocked
= Fabricate(:account, domain
: 'example.com')
533 @account.block_domain!
(blocked
.domain
)
534 blocked_status
= Fabricate(:status, account
: blocked
)
536 results
= Status
.as_public_timeline(@account)
537 expect(results
).not_to
include(blocked_status
)
540 context
'with language preferences' do
541 it
'excludes statuses in languages not allowed by the account user' do
542 user
= Fabricate(:user, chosen_languages
: [:en, :es])
543 @account.update(user
: user
)
544 en_status
= Fabricate(:status, language
: 'en')
545 es_status
= Fabricate(:status, language
: 'es')
546 fr_status
= Fabricate(:status, language
: 'fr')
548 results
= Status
.as_public_timeline(@account)
549 expect(results
).to
include(en_status
)
550 expect(results
).to
include(es_status
)
551 expect(results
).not_to
include(fr_status
)
554 it
'includes all languages when user does not have a setting' do
555 user
= Fabricate(:user, chosen_languages
: nil)
556 @account.update(user
: user
)
558 en_status
= Fabricate(:status, language
: 'en')
559 es_status
= Fabricate(:status, language
: 'es')
561 results
= Status
.as_public_timeline(@account)
562 expect(results
).to
include(en_status
)
563 expect(results
).to
include(es_status
)
566 it
'includes all languages when account does not have a user' do
567 expect(@account.user
).to be_nil
568 en_status
= Fabricate(:status, language
: 'en')
569 es_status
= Fabricate(:status, language
: 'es')
571 results
= Status
.as_public_timeline(@account)
572 expect(results
).to
include(en_status
)
573 expect(results
).to
include(es_status
)
579 describe
'.as_tag_timeline' do
580 it
'includes statuses with a tag' do
581 tag
= Fabricate(:tag)
582 status
= Fabricate(:status, tags
: [tag
])
583 other
= Fabricate(:status)
585 results
= Status
.as_tag_timeline(tag
)
586 expect(results
).to
include(status
)
587 expect(results
).not_to
include(other
)
590 it
'allows replies to be included' do
591 original
= Fabricate(:status)
592 tag
= Fabricate(:tag)
593 status
= Fabricate(:status, tags
: [tag
], in_reply_to_id
: original
.id
)
595 results
= Status
.as_tag_timeline(tag
)
596 expect(results
).to
include(status
)
600 describe
'.permitted_for' do
601 subject
{ described_class
.permitted_for(target_account
, account
).pluck(:visibility) }
603 let(:target_account) { alice
}
604 let(:account) { bob
}
605 let!
(:public_status) { Fabricate(:status, account
: target_account
, visibility
: 'public') }
606 let!
(:unlisted_status) { Fabricate(:status, account
: target_account
, visibility
: 'unlisted') }
607 let!
(:private_status) { Fabricate(:status, account
: target_account
, visibility
: 'private') }
609 let!
(:direct_status) do
610 Fabricate(:status, account
: target_account
, visibility
: 'direct').tap
do |status
|
611 Fabricate(:mention, status
: status
, account
: account
)
615 let!
(:other_direct_status) do
616 Fabricate(:status, account
: target_account
, visibility
: 'direct').tap
do |status
|
617 Fabricate(:mention, status
: status
)
621 context
'given nil' do
622 let(:account) { nil }
623 let(:direct_status) { nil }
624 it
{ is_expected
.to
eq(%w(unlisted public
)) }
627 context
'given blocked account' do
629 target_account
.block!
(account
)
632 it
{ is_expected
.to be_empty
}
635 context
'given same account' do
636 let(:account) { target_account
}
637 it
{ is_expected
.to
eq(%w(direct direct
private unlisted public
)) }
640 context
'given followed account' do
642 account
.follow!
(target_account
)
645 it
{ is_expected
.to
eq(%w(direct
private unlisted public
)) }
648 context
'given unfollowed account' do
649 it
{ is_expected
.to
eq(%w(direct unlisted public
)) }
653 describe
'before_validation' do
654 it
'sets account being replied to correctly over intermediary nodes' do
655 first_status
= Fabricate(:status, account
: bob
)
656 intermediary
= Fabricate(:status, thread
: first_status
, account
: alice
)
657 final
= Fabricate(:status, thread
: intermediary
, account
: alice
)
659 expect(final
.in_reply_to_account_id
).to eq bob
.id
662 it
'creates new conversation for stand-alone status' do
663 expect(Status
.create(account
: alice
, text
: 'First').conversation_id
).to_not be_nil
666 it
'keeps conversation of parent node' do
667 parent
= Fabricate(:status, text
: 'First')
668 expect(Status
.create(account
: alice
, thread
: parent
, text
: 'Response').conversation_id
).to eq parent
.conversation_id
671 it
'sets `local` to true for status by local account' do
672 expect(Status
.create(account
: alice
, text
: 'foo').local
).to be
true
675 it
'sets `local` to false for status by remote account' do
676 alice
.update(domain
: 'example.com')
677 expect(Status
.create(account
: alice
, text
: 'foo').local
).to be
false
681 describe
'validation' do
682 it
'disallow empty uri for remote status' do
683 alice
.update(domain
: 'example.com')
684 status
= Fabricate
.build(:status, uri
: '', account
: alice
)
685 expect(status
).to
model_have_error_on_field(:uri)
689 describe
'after_create' do
690 it
'saves ActivityPub uri as uri for local status' do
691 status
= Status
.create(account
: alice
, text
: 'foo')
693 expect(status
.uri
).to
start_with('https://')
This page took 0.330463 seconds and 4 git commands to generate.