account_interactions_spec.rb 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. describe AccountInteractions do
  4. let(:account) { Fabricate(:account, username: 'account') }
  5. let(:account_id) { account.id }
  6. let(:account_ids) { [account_id] }
  7. let(:target_account) { Fabricate(:account, username: 'target') }
  8. let(:target_account_id) { target_account.id }
  9. let(:target_account_ids) { [target_account_id] }
  10. describe '.following_map' do
  11. subject { Account.following_map(target_account_ids, account_id) }
  12. context 'when Account with Follow' do
  13. it 'returns { target_account_id => true }' do
  14. Fabricate(:follow, account: account, target_account: target_account)
  15. expect(subject).to eq(target_account_id => { reblogs: true, notify: false, languages: nil })
  16. end
  17. end
  18. context 'when Account without Follow' do
  19. it 'returns {}' do
  20. expect(subject).to eq({})
  21. end
  22. end
  23. end
  24. describe '.followed_by_map' do
  25. subject { Account.followed_by_map(target_account_ids, account_id) }
  26. context 'when Account with Follow' do
  27. it 'returns { target_account_id => true }' do
  28. Fabricate(:follow, account: target_account, target_account: account)
  29. expect(subject).to eq(target_account_id => true)
  30. end
  31. end
  32. context 'when Account without Follow' do
  33. it 'returns {}' do
  34. expect(subject).to eq({})
  35. end
  36. end
  37. end
  38. describe '.blocking_map' do
  39. subject { Account.blocking_map(target_account_ids, account_id) }
  40. context 'when Account with Block' do
  41. it 'returns { target_account_id => true }' do
  42. Fabricate(:block, account: account, target_account: target_account)
  43. expect(subject).to eq(target_account_id => true)
  44. end
  45. end
  46. context 'when Account without Block' do
  47. it 'returns {}' do
  48. expect(subject).to eq({})
  49. end
  50. end
  51. end
  52. describe '.muting_map' do
  53. subject { Account.muting_map(target_account_ids, account_id) }
  54. context 'when Account with Mute' do
  55. before do
  56. Fabricate(:mute, target_account: target_account, account: account, hide_notifications: hide)
  57. end
  58. context 'when Mute#hide_notifications?' do
  59. let(:hide) { true }
  60. it 'returns { target_account_id => { notifications: true } }' do
  61. expect(subject).to eq(target_account_id => { notifications: true })
  62. end
  63. end
  64. context 'when not Mute#hide_notifications?' do
  65. let(:hide) { false }
  66. it 'returns { target_account_id => { notifications: false } }' do
  67. expect(subject).to eq(target_account_id => { notifications: false })
  68. end
  69. end
  70. end
  71. context 'when Account without Mute' do
  72. it 'returns {}' do
  73. expect(subject).to eq({})
  74. end
  75. end
  76. end
  77. describe '#follow!' do
  78. it 'creates and returns Follow' do
  79. expect do
  80. expect(account.follow!(target_account)).to be_a Follow
  81. end.to change { account.following.count }.by 1
  82. end
  83. end
  84. describe '#block' do
  85. it 'creates and returns Block' do
  86. expect do
  87. expect(account.block!(target_account)).to be_a Block
  88. end.to change { account.block_relationships.count }.by 1
  89. end
  90. end
  91. describe '#mute!' do
  92. subject { account.mute!(target_account, notifications: arg_notifications) }
  93. context 'when Mute does not exist yet' do
  94. context 'when arg :notifications is nil' do
  95. let(:arg_notifications) { nil }
  96. it 'creates Mute, and returns Mute' do
  97. expect do
  98. expect(subject).to be_a Mute
  99. end.to change { account.mute_relationships.count }.by 1
  100. end
  101. end
  102. context 'when arg :notifications is false' do
  103. let(:arg_notifications) { false }
  104. it 'creates Mute, and returns Mute' do
  105. expect do
  106. expect(subject).to be_a Mute
  107. end.to change { account.mute_relationships.count }.by 1
  108. end
  109. end
  110. context 'when arg :notifications is true' do
  111. let(:arg_notifications) { true }
  112. it 'creates Mute, and returns Mute' do
  113. expect do
  114. expect(subject).to be_a Mute
  115. end.to change { account.mute_relationships.count }.by 1
  116. end
  117. end
  118. end
  119. context 'when Mute already exists' do
  120. before do
  121. account.mute_relationships << mute
  122. end
  123. let(:mute) do
  124. Fabricate(:mute,
  125. account: account,
  126. target_account: target_account,
  127. hide_notifications: hide_notifications)
  128. end
  129. context 'when mute.hide_notifications is true' do
  130. let(:hide_notifications) { true }
  131. context 'when arg :notifications is nil' do
  132. let(:arg_notifications) { nil }
  133. it 'returns Mute without updating mute.hide_notifications' do
  134. expect do
  135. expect(subject).to be_a Mute
  136. end.to_not change { mute.reload.hide_notifications? }.from(true)
  137. end
  138. end
  139. context 'when arg :notifications is false' do
  140. let(:arg_notifications) { false }
  141. it 'returns Mute, and updates mute.hide_notifications false' do
  142. expect do
  143. expect(subject).to be_a Mute
  144. end.to change { mute.reload.hide_notifications? }.from(true).to(false)
  145. end
  146. end
  147. context 'when arg :notifications is true' do
  148. let(:arg_notifications) { true }
  149. it 'returns Mute without updating mute.hide_notifications' do
  150. expect do
  151. expect(subject).to be_a Mute
  152. end.to_not change { mute.reload.hide_notifications? }.from(true)
  153. end
  154. end
  155. end
  156. context 'when mute.hide_notifications is false' do
  157. let(:hide_notifications) { false }
  158. context 'when arg :notifications is nil' do
  159. let(:arg_notifications) { nil }
  160. it 'returns Mute, and updates mute.hide_notifications true' do
  161. expect do
  162. expect(subject).to be_a Mute
  163. end.to change { mute.reload.hide_notifications? }.from(false).to(true)
  164. end
  165. end
  166. context 'when arg :notifications is false' do
  167. let(:arg_notifications) { false }
  168. it 'returns Mute without updating mute.hide_notifications' do
  169. expect do
  170. expect(subject).to be_a Mute
  171. end.to_not change { mute.reload.hide_notifications? }.from(false)
  172. end
  173. end
  174. context 'when arg :notifications is true' do
  175. let(:arg_notifications) { true }
  176. it 'returns Mute, and updates mute.hide_notifications true' do
  177. expect do
  178. expect(subject).to be_a Mute
  179. end.to change { mute.reload.hide_notifications? }.from(false).to(true)
  180. end
  181. end
  182. end
  183. end
  184. end
  185. describe '#mute_conversation!' do
  186. subject { account.mute_conversation!(conversation) }
  187. let(:conversation) { Fabricate(:conversation) }
  188. it 'creates and returns ConversationMute' do
  189. expect do
  190. expect(subject).to be_a ConversationMute
  191. end.to change { account.conversation_mutes.count }.by 1
  192. end
  193. end
  194. describe '#block_domain!' do
  195. subject { account.block_domain!(domain) }
  196. let(:domain) { 'example.com' }
  197. it 'creates and returns AccountDomainBlock' do
  198. expect do
  199. expect(subject).to be_a AccountDomainBlock
  200. end.to change { account.domain_blocks.count }.by 1
  201. end
  202. end
  203. describe '#unfollow!' do
  204. subject { account.unfollow!(target_account) }
  205. context 'when following target_account' do
  206. it 'returns destroyed Follow' do
  207. account.active_relationships.create(target_account: target_account)
  208. expect(subject).to be_a Follow
  209. expect(subject).to be_destroyed
  210. end
  211. end
  212. context 'when not following target_account' do
  213. it 'returns nil' do
  214. expect(subject).to be_nil
  215. end
  216. end
  217. end
  218. describe '#unblock!' do
  219. subject { account.unblock!(target_account) }
  220. context 'when blocking target_account' do
  221. it 'returns destroyed Block' do
  222. account.block_relationships.create(target_account: target_account)
  223. expect(subject).to be_a Block
  224. expect(subject).to be_destroyed
  225. end
  226. end
  227. context 'when not blocking target_account' do
  228. it 'returns nil' do
  229. expect(subject).to be_nil
  230. end
  231. end
  232. end
  233. describe '#unmute!' do
  234. subject { account.unmute!(target_account) }
  235. context 'when muting target_account' do
  236. it 'returns destroyed Mute' do
  237. account.mute_relationships.create(target_account: target_account)
  238. expect(subject).to be_a Mute
  239. expect(subject).to be_destroyed
  240. end
  241. end
  242. context 'when not muting target_account' do
  243. it 'returns nil' do
  244. expect(subject).to be_nil
  245. end
  246. end
  247. end
  248. describe '#unmute_conversation!' do
  249. subject { account.unmute_conversation!(conversation) }
  250. let(:conversation) { Fabricate(:conversation) }
  251. context 'when muting the conversation' do
  252. it 'returns destroyed ConversationMute' do
  253. account.conversation_mutes.create(conversation: conversation)
  254. expect(subject).to be_a ConversationMute
  255. expect(subject).to be_destroyed
  256. end
  257. end
  258. context 'when not muting the conversation' do
  259. it 'returns nil' do
  260. expect(subject).to be_nil
  261. end
  262. end
  263. end
  264. describe '#unblock_domain!' do
  265. subject { account.unblock_domain!(domain) }
  266. let(:domain) { 'example.com' }
  267. context 'when blocking the domain' do
  268. it 'returns destroyed AccountDomainBlock' do
  269. account_domain_block = Fabricate(:account_domain_block, domain: domain)
  270. account.domain_blocks << account_domain_block
  271. expect(subject).to be_a AccountDomainBlock
  272. expect(subject).to be_destroyed
  273. end
  274. end
  275. context 'when unblocking the domain' do
  276. it 'returns nil' do
  277. expect(subject).to be_nil
  278. end
  279. end
  280. end
  281. describe '#following?' do
  282. subject { account.following?(target_account) }
  283. context 'when following target_account' do
  284. it 'returns true' do
  285. account.active_relationships.create(target_account: target_account)
  286. expect(subject).to be true
  287. end
  288. end
  289. context 'when not following target_account' do
  290. it 'returns false' do
  291. expect(subject).to be false
  292. end
  293. end
  294. end
  295. describe '#followed_by?' do
  296. subject { account.followed_by?(target_account) }
  297. context 'when followed by target_account' do
  298. it 'returns true' do
  299. account.passive_relationships.create(account: target_account)
  300. expect(subject).to be true
  301. end
  302. end
  303. context 'when not followed by target_account' do
  304. it 'returns false' do
  305. expect(subject).to be false
  306. end
  307. end
  308. end
  309. describe '#blocking?' do
  310. subject { account.blocking?(target_account) }
  311. context 'when blocking target_account' do
  312. it 'returns true' do
  313. account.block_relationships.create(target_account: target_account)
  314. expect(subject).to be true
  315. end
  316. end
  317. context 'when not blocking target_account' do
  318. it 'returns false' do
  319. expect(subject).to be false
  320. end
  321. end
  322. end
  323. describe '#domain_blocking?' do
  324. subject { account.domain_blocking?(domain) }
  325. let(:domain) { 'example.com' }
  326. context 'when blocking the domain' do
  327. it 'returns true' do
  328. account_domain_block = Fabricate(:account_domain_block, domain: domain)
  329. account.domain_blocks << account_domain_block
  330. expect(subject).to be true
  331. end
  332. end
  333. context 'when not blocking the domain' do
  334. it 'returns false' do
  335. expect(subject).to be false
  336. end
  337. end
  338. end
  339. describe '#muting?' do
  340. subject { account.muting?(target_account) }
  341. context 'when muting target_account' do
  342. it 'returns true' do
  343. mute = Fabricate(:mute, account: account, target_account: target_account)
  344. account.mute_relationships << mute
  345. expect(subject).to be true
  346. end
  347. end
  348. context 'when not muting target_account' do
  349. it 'returns false' do
  350. expect(subject).to be false
  351. end
  352. end
  353. end
  354. describe '#muting_conversation?' do
  355. subject { account.muting_conversation?(conversation) }
  356. let(:conversation) { Fabricate(:conversation) }
  357. context 'when muting the conversation' do
  358. it 'returns true' do
  359. account.conversation_mutes.create(conversation: conversation)
  360. expect(subject).to be true
  361. end
  362. end
  363. context 'when not muting the conversation' do
  364. it 'returns false' do
  365. expect(subject).to be false
  366. end
  367. end
  368. end
  369. describe '#muting_notifications?' do
  370. subject { account.muting_notifications?(target_account) }
  371. before do
  372. mute = Fabricate(:mute, target_account: target_account, account: account, hide_notifications: hide)
  373. account.mute_relationships << mute
  374. end
  375. context 'when muting notifications of target_account' do
  376. let(:hide) { true }
  377. it 'returns true' do
  378. expect(subject).to be true
  379. end
  380. end
  381. context 'when not muting notifications of target_account' do
  382. let(:hide) { false }
  383. it 'returns false' do
  384. expect(subject).to be false
  385. end
  386. end
  387. end
  388. describe '#requested?' do
  389. subject { account.requested?(target_account) }
  390. context 'with requested by target_account' do
  391. it 'returns true' do
  392. Fabricate(:follow_request, account: account, target_account: target_account)
  393. expect(subject).to be true
  394. end
  395. end
  396. context 'when not requested by target_account' do
  397. it 'returns false' do
  398. expect(subject).to be false
  399. end
  400. end
  401. end
  402. describe '#favourited?' do
  403. subject { account.favourited?(status) }
  404. let(:status) { Fabricate(:status, account: account, favourites: favourites) }
  405. context 'when favorited' do
  406. let(:favourites) { [Fabricate(:favourite, account: account)] }
  407. it 'returns true' do
  408. expect(subject).to be true
  409. end
  410. end
  411. context 'when not favorited' do
  412. let(:favourites) { [] }
  413. it 'returns false' do
  414. expect(subject).to be false
  415. end
  416. end
  417. end
  418. describe '#reblogged?' do
  419. subject { account.reblogged?(status) }
  420. let(:status) { Fabricate(:status, account: account, reblogs: reblogs) }
  421. context 'with reblogged' do
  422. let(:reblogs) { [Fabricate(:status, account: account)] }
  423. it 'returns true' do
  424. expect(subject).to be true
  425. end
  426. end
  427. context 'when not reblogged' do
  428. let(:reblogs) { [] }
  429. it 'returns false' do
  430. expect(subject).to be false
  431. end
  432. end
  433. end
  434. describe '#pinned?' do
  435. subject { account.pinned?(status) }
  436. let(:status) { Fabricate(:status, account: account) }
  437. context 'when pinned' do
  438. it 'returns true' do
  439. Fabricate(:status_pin, account: account, status: status)
  440. expect(subject).to be true
  441. end
  442. end
  443. context 'when not pinned' do
  444. it 'returns false' do
  445. expect(subject).to be false
  446. end
  447. end
  448. end
  449. describe '#remote_followers_hash' do
  450. let(:me) { Fabricate(:account, username: 'Me') }
  451. let(:remote_alice) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') }
  452. let(:remote_bob) { Fabricate(:account, username: 'bob', domain: 'example.org', uri: 'https://example.org/users/bob') }
  453. let(:remote_instance_actor) { Fabricate(:account, username: 'instance-actor', domain: 'example.org', uri: 'https://example.org') }
  454. let(:remote_eve) { Fabricate(:account, username: 'eve', domain: 'foo.org', uri: 'https://foo.org/users/eve') }
  455. before do
  456. remote_alice.follow!(me)
  457. remote_bob.follow!(me)
  458. remote_instance_actor.follow!(me)
  459. remote_eve.follow!(me)
  460. me.follow!(remote_alice)
  461. end
  462. it 'returns correct hash for remote domains' do
  463. expect(me.remote_followers_hash('https://example.org/')).to eq '20aecbe774b3d61c25094370baf370012b9271c5b172ecedb05caff8d79ef0c7'
  464. expect(me.remote_followers_hash('https://foo.org/')).to eq 'ccb9c18a67134cfff9d62c7f7e7eb88e6b803446c244b84265565f4eba29df0e'
  465. expect(me.remote_followers_hash('https://foo.org.evil.com/')).to eq '0000000000000000000000000000000000000000000000000000000000000000'
  466. expect(me.remote_followers_hash('https://foo')).to eq '0000000000000000000000000000000000000000000000000000000000000000'
  467. end
  468. it 'invalidates cache as needed when removing or adding followers' do
  469. expect(me.remote_followers_hash('https://example.org/')).to eq '20aecbe774b3d61c25094370baf370012b9271c5b172ecedb05caff8d79ef0c7'
  470. remote_instance_actor.unfollow!(me)
  471. expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
  472. remote_alice.unfollow!(me)
  473. expect(me.remote_followers_hash('https://example.org/')).to eq '241b00794ce9b46aa864f3220afadef128318da2659782985bac5ed5bd436bff'
  474. remote_alice.follow!(me)
  475. expect(me.remote_followers_hash('https://example.org/')).to eq '707962e297b7bd94468a21bc8e506a1bcea607a9142cd64e27c9b106b2a5f6ec'
  476. end
  477. end
  478. describe '#local_followers_hash' do
  479. let(:me) { Fabricate(:account, username: 'Me') }
  480. let(:remote_alice) { Fabricate(:account, username: 'alice', domain: 'example.org', uri: 'https://example.org/users/alice') }
  481. before do
  482. me.follow!(remote_alice)
  483. end
  484. it 'returns correct hash for local users' do
  485. expect(remote_alice.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
  486. end
  487. it 'invalidates cache as needed when removing or adding followers' do
  488. expect(remote_alice.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
  489. me.unfollow!(remote_alice)
  490. expect(remote_alice.local_followers_hash).to eq '0000000000000000000000000000000000000000000000000000000000000000'
  491. me.follow!(remote_alice)
  492. expect(remote_alice.local_followers_hash).to eq Digest::SHA256.hexdigest(ActivityPub::TagManager.instance.uri_for(me))
  493. end
  494. end
  495. describe 'muting an account' do
  496. let(:me) { Fabricate(:account, username: 'Me') }
  497. let(:you) { Fabricate(:account, username: 'You') }
  498. context 'with the notifications option unspecified' do
  499. before do
  500. me.mute!(you)
  501. end
  502. it 'defaults to muting notifications' do
  503. expect(me.muting_notifications?(you)).to be true
  504. end
  505. end
  506. context 'with the notifications option set to false' do
  507. before do
  508. me.mute!(you, notifications: false)
  509. end
  510. it 'does not mute notifications' do
  511. expect(me.muting_notifications?(you)).to be false
  512. end
  513. end
  514. context 'with the notifications option set to true' do
  515. before do
  516. me.mute!(you, notifications: true)
  517. end
  518. it 'does mute notifications' do
  519. expect(me.muting_notifications?(you)).to be true
  520. end
  521. end
  522. end
  523. describe 'ignoring reblogs from an account' do
  524. before do
  525. @me = Fabricate(:account, username: 'Me')
  526. @you = Fabricate(:account, username: 'You')
  527. end
  528. context 'with the reblogs option unspecified' do
  529. before do
  530. @me.follow!(@you)
  531. end
  532. it 'defaults to showing reblogs' do
  533. expect(@me.muting_reblogs?(@you)).to be(false)
  534. end
  535. end
  536. context 'with the reblogs option set to false' do
  537. before do
  538. @me.follow!(@you, reblogs: false)
  539. end
  540. it 'does mute reblogs' do
  541. expect(@me.muting_reblogs?(@you)).to be(true)
  542. end
  543. end
  544. context 'with the reblogs option set to true' do
  545. before do
  546. @me.follow!(@you, reblogs: true)
  547. end
  548. it 'does not mute reblogs' do
  549. expect(@me.muting_reblogs?(@you)).to be(false)
  550. end
  551. end
  552. end
  553. describe '#lists_for_local_distribution' do
  554. let(:account) { Fabricate(:user, current_sign_in_at: Time.now.utc).account }
  555. let!(:inactive_follower_user) { Fabricate(:user, current_sign_in_at: 5.years.ago) }
  556. let!(:follower_user) { Fabricate(:user, current_sign_in_at: Time.now.utc) }
  557. let!(:follow_request_user) { Fabricate(:user, current_sign_in_at: Time.now.utc) }
  558. let!(:inactive_follower_list) { Fabricate(:list, account: inactive_follower_user.account) }
  559. let!(:follower_list) { Fabricate(:list, account: follower_user.account) }
  560. let!(:follow_request_list) { Fabricate(:list, account: follow_request_user.account) }
  561. let!(:self_list) { Fabricate(:list, account: account) }
  562. before do
  563. inactive_follower_user.account.follow!(account)
  564. follower_user.account.follow!(account)
  565. follow_request_user.account.follow_requests.create!(target_account: account)
  566. inactive_follower_list.accounts << account
  567. follower_list.accounts << account
  568. follow_request_list.accounts << account
  569. self_list.accounts << account
  570. end
  571. it 'includes only the list from the active follower and from oneself' do
  572. expect(account.lists_for_local_distribution.to_a).to contain_exactly(follower_list, self_list)
  573. end
  574. end
  575. end