spam_check_spec.rb 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. require 'rails_helper'
  2. RSpec.describe SpamCheck do
  3. let!(:sender) { Fabricate(:account) }
  4. let!(:alice) { Fabricate(:account, username: 'alice') }
  5. let!(:bob) { Fabricate(:account, username: 'bob') }
  6. def status_with_html(text, options = {})
  7. status = PostStatusService.new.call(sender, { text: text }.merge(options))
  8. status.update_columns(text: Formatter.instance.format(status), local: false)
  9. status
  10. end
  11. describe '#hashable_text' do
  12. it 'removes mentions from HTML for remote statuses' do
  13. status = status_with_html('@alice Hello')
  14. expect(described_class.new(status).hashable_text).to eq 'hello'
  15. end
  16. it 'removes mentions from text for local statuses' do
  17. status = PostStatusService.new.call(alice, text: "Hey @#{sender.username}, how are you?")
  18. expect(described_class.new(status).hashable_text).to eq 'hey , how are you?'
  19. end
  20. end
  21. describe '#insufficient_data?' do
  22. it 'returns true when there is no text' do
  23. status = status_with_html('@alice')
  24. expect(described_class.new(status).insufficient_data?).to be true
  25. end
  26. it 'returns false when there is text' do
  27. status = status_with_html('@alice h')
  28. expect(described_class.new(status).insufficient_data?).to be false
  29. end
  30. end
  31. describe '#digest' do
  32. it 'returns a string' do
  33. status = status_with_html('@alice Hello world')
  34. expect(described_class.new(status).digest).to be_a String
  35. end
  36. end
  37. describe '#spam?' do
  38. it 'returns false for a unique status' do
  39. status = status_with_html('@alice Hello')
  40. expect(described_class.new(status).spam?).to be false
  41. end
  42. it 'returns false for different statuses to the same recipient' do
  43. status1 = status_with_html('@alice Hello')
  44. described_class.new(status1).remember!
  45. status2 = status_with_html('@alice Are you available to talk?')
  46. expect(described_class.new(status2).spam?).to be false
  47. end
  48. it 'returns false for statuses with different content warnings' do
  49. status1 = status_with_html('@alice Are you available to talk?')
  50. described_class.new(status1).remember!
  51. status2 = status_with_html('@alice Are you available to talk?', spoiler_text: 'This is a completely different matter than what I was talking about previously, I swear!')
  52. expect(described_class.new(status2).spam?).to be false
  53. end
  54. it 'returns false for different statuses to different recipients' do
  55. status1 = status_with_html('@alice How is it going?')
  56. described_class.new(status1).remember!
  57. status2 = status_with_html('@bob Are you okay?')
  58. expect(described_class.new(status2).spam?).to be false
  59. end
  60. it 'returns false for very short different statuses to different recipients' do
  61. status1 = status_with_html('@alice 🙄')
  62. described_class.new(status1).remember!
  63. status2 = status_with_html('@bob Huh?')
  64. expect(described_class.new(status2).spam?).to be false
  65. end
  66. it 'returns false for statuses with no text' do
  67. status1 = status_with_html('@alice')
  68. described_class.new(status1).remember!
  69. status2 = status_with_html('@bob')
  70. expect(described_class.new(status2).spam?).to be false
  71. end
  72. it 'returns true for duplicate statuses to the same recipient' do
  73. status1 = status_with_html('@alice Hello')
  74. described_class.new(status1).remember!
  75. status2 = status_with_html('@alice Hello')
  76. expect(described_class.new(status2).spam?).to be true
  77. end
  78. it 'returns true for duplicate statuses to different recipients' do
  79. status1 = status_with_html('@alice Hello')
  80. described_class.new(status1).remember!
  81. status2 = status_with_html('@bob Hello')
  82. expect(described_class.new(status2).spam?).to be true
  83. end
  84. it 'returns true for nearly identical statuses with random numbers' do
  85. source_text = 'Sodium, atomic number 11, was first isolated by Humphry Davy in 1807. A chemical component of salt, he named it Na in honor of the saltiest region on earth, North America.'
  86. status1 = status_with_html('@alice ' + source_text + ' 1234')
  87. described_class.new(status1).remember!
  88. status2 = status_with_html('@bob ' + source_text + ' 9568')
  89. expect(described_class.new(status2).spam?).to be true
  90. end
  91. end
  92. describe '#skip?' do
  93. it 'returns true when the sender is already silenced' do
  94. status = status_with_html('@alice Hello')
  95. sender.silence!
  96. expect(described_class.new(status).skip?).to be true
  97. end
  98. it 'returns true when the mentioned person follows the sender' do
  99. status = status_with_html('@alice Hello')
  100. alice.follow!(sender)
  101. expect(described_class.new(status).skip?).to be true
  102. end
  103. it 'returns false when even one mentioned person doesn\'t follow the sender' do
  104. status = status_with_html('@alice @bob Hello')
  105. alice.follow!(sender)
  106. expect(described_class.new(status).skip?).to be false
  107. end
  108. it 'returns true when the sender is replying to a status that mentions the sender' do
  109. parent = PostStatusService.new.call(alice, text: "Hey @#{sender.username}, how are you?")
  110. status = status_with_html('@alice @bob Hello', thread: parent)
  111. expect(described_class.new(status).skip?).to be true
  112. end
  113. end
  114. describe '#remember!' do
  115. pending
  116. end
  117. describe '#flag!' do
  118. let!(:status1) { status_with_html('@alice General Kenobi you are a bold one') }
  119. let!(:status2) { status_with_html('@alice @bob General Kenobi, you are a bold one') }
  120. before do
  121. described_class.new(status1).remember!
  122. described_class.new(status2).flag!
  123. end
  124. it 'silences the account' do
  125. expect(sender.silenced?).to be true
  126. end
  127. it 'creates a report about the account' do
  128. expect(sender.targeted_reports.unresolved.count).to eq 1
  129. end
  130. it 'attaches both matching statuses to the report' do
  131. expect(sender.targeted_reports.first.status_ids).to include(status1.id, status2.id)
  132. end
  133. end
  134. end