You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
11 KiB

8 years ago
8 years ago
  1. require 'rails_helper'
  2. RSpec.describe Account, type: :model do
  3. subject { Fabricate(:account, username: 'alice') }
  4. context do
  5. let(:bob) { Fabricate(:account, username: 'bob') }
  6. describe '#follow!' do
  7. it 'creates a follow' do
  8. follow = subject.follow!(bob)
  9. expect(follow).to be_instance_of Follow
  10. expect(follow.account).to eq subject
  11. expect(follow.target_account).to eq bob
  12. end
  13. end
  14. describe '#unfollow!' do
  15. before do
  16. subject.follow!(bob)
  17. end
  18. it 'destroys a follow' do
  19. unfollow = subject.unfollow!(bob)
  20. expect(unfollow).to be_instance_of Follow
  21. expect(unfollow.account).to eq subject
  22. expect(unfollow.target_account).to eq bob
  23. expect(unfollow.destroyed?).to be true
  24. end
  25. end
  26. describe '#following?' do
  27. it 'returns true when the target is followed' do
  28. subject.follow!(bob)
  29. expect(subject.following?(bob)).to be true
  30. end
  31. it 'returns false if the target is not followed' do
  32. expect(subject.following?(bob)).to be false
  33. end
  34. end
  35. end
  36. describe '#local?' do
  37. it 'returns true when the account is local' do
  38. expect(subject.local?).to be true
  39. end
  40. it 'returns false when the account is on a different domain' do
  41. subject.domain = 'foreign.tld'
  42. expect(subject.local?).to be false
  43. end
  44. end
  45. describe '#acct' do
  46. it 'returns username for local users' do
  47. expect(subject.acct).to eql 'alice'
  48. end
  49. it 'returns username@domain for foreign users' do
  50. subject.domain = 'foreign.tld'
  51. expect(subject.acct).to eql 'alice@foreign.tld'
  52. end
  53. end
  54. describe '#subscribed?' do
  55. it 'returns false when no subscription expiration information is present' do
  56. expect(subject.subscribed?).to be false
  57. end
  58. it 'returns true when subscription expiration has been set' do
  59. subject.subscription_expires_at = 30.days.from_now
  60. expect(subject.subscribed?).to be true
  61. end
  62. end
  63. describe '#keypair' do
  64. it 'returns an RSA key pair' do
  65. expect(subject.keypair).to be_instance_of OpenSSL::PKey::RSA
  66. end
  67. end
  68. describe '#subscription' do
  69. it 'returns an OStatus subscription' do
  70. expect(subject.subscription('')).to be_instance_of OStatus2::Subscription
  71. end
  72. end
  73. describe '#object_type' do
  74. it 'is always a person' do
  75. expect(subject.object_type).to be :person
  76. end
  77. end
  78. describe '#ping!' do
  79. pending
  80. end
  81. describe '#favourited?' do
  82. let(:original_status) do
  83. author = Fabricate(:account, username: 'original')
  84. Fabricate(:status, account: author)
  85. end
  86. context 'when the status is a reblog of another status' do
  87. let(:original_reblog) do
  88. author = Fabricate(:account, username: 'original_reblogger')
  89. Fabricate(:status, reblog: original_status, account: author)
  90. end
  91. it 'is is true when this account has favourited it' do
  92. Fabricate(:favourite, status: original_reblog, account: subject)
  93. expect(subject.favourited?(original_status)).to eq true
  94. end
  95. it 'is false when this account has not favourited it' do
  96. expect(subject.favourited?(original_status)).to eq false
  97. end
  98. end
  99. context 'when the status is an original status' do
  100. it 'is is true when this account has favourited it' do
  101. Fabricate(:favourite, status: original_status, account: subject)
  102. expect(subject.favourited?(original_status)).to eq true
  103. end
  104. it 'is false when this account has not favourited it' do
  105. expect(subject.favourited?(original_status)).to eq false
  106. end
  107. end
  108. end
  109. describe '#reblogged?' do
  110. let(:original_status) do
  111. author = Fabricate(:account, username: 'original')
  112. Fabricate(:status, account: author)
  113. end
  114. context 'when the status is a reblog of another status'do
  115. let(:original_reblog) do
  116. author = Fabricate(:account, username: 'original_reblogger')
  117. Fabricate(:status, reblog: original_status, account: author)
  118. end
  119. it 'is true when this account has reblogged it' do
  120. Fabricate(:status, reblog: original_reblog, account: subject)
  121. expect(subject.reblogged?(original_reblog)).to eq true
  122. end
  123. it 'is false when this account has not reblogged it' do
  124. expect(subject.reblogged?(original_reblog)).to eq false
  125. end
  126. end
  127. context 'when the status is an original status' do
  128. it 'is true when this account has reblogged it' do
  129. Fabricate(:status, reblog: original_status, account: subject)
  130. expect(subject.reblogged?(original_status)).to eq true
  131. end
  132. it 'is false when this account has not reblogged it' do
  133. expect(subject.reblogged?(original_status)).to eq false
  134. end
  135. end
  136. end
  137. describe '.search_for' do
  138. before do
  139. @match = Fabricate(
  140. :account,
  141. display_name: "Display Name",
  142. username: "username",
  143. domain: "example.com"
  144. )
  145. _missing = Fabricate(
  146. :account,
  147. display_name: "Missing",
  148. username: "missing",
  149. domain: "missing.com"
  150. )
  151. end
  152. it 'finds accounts with matching display_name' do
  153. results = Account.search_for("display")
  154. expect(results).to eq [@match]
  155. end
  156. it 'finds accounts with matching username' do
  157. results = Account.search_for("username")
  158. expect(results).to eq [@match]
  159. end
  160. it 'finds accounts with matching domain' do
  161. results = Account.search_for("example")
  162. expect(results).to eq [@match]
  163. end
  164. it 'ranks multiple matches higher' do
  165. account = Fabricate(
  166. :account,
  167. username: "username",
  168. display_name: "username"
  169. )
  170. results = Account.search_for("username")
  171. expect(results).to eq [account, @match]
  172. end
  173. end
  174. describe '.advanced_search_for' do
  175. it 'ranks followed accounts higher' do
  176. account = Fabricate(:account)
  177. match = Fabricate(:account, username: "Matching")
  178. followed_match = Fabricate(:account, username: "Matcher")
  179. Fabricate(:follow, account: account, target_account: followed_match)
  180. results = Account.advanced_search_for("match", account)
  181. expect(results).to eq [followed_match, match]
  182. expect(results.first.rank).to be > results.last.rank
  183. end
  184. end
  185. describe '.find_local' do
  186. before do
  187. Fabricate(:account, username: 'Alice')
  188. end
  189. it 'returns Alice for alice' do
  190. expect(Account.find_local('alice')).to_not be_nil
  191. end
  192. it 'returns Alice for Alice' do
  193. expect(Account.find_local('Alice')).to_not be_nil
  194. end
  195. it 'does not return anything for a_ice' do
  196. expect(Account.find_local('a_ice')).to be_nil
  197. end
  198. it 'does not return anything for al%' do
  199. expect(Account.find_local('al%')).to be_nil
  200. end
  201. end
  202. describe '.find_remote' do
  203. before do
  204. Fabricate(:account, username: 'Alice', domain: 'mastodon.social')
  205. end
  206. it 'returns Alice for alice@mastodon.social' do
  207. expect(Account.find_remote('alice', 'mastodon.social')).to_not be_nil
  208. end
  209. it 'returns Alice for ALICE@MASTODON.SOCIAL' do
  210. expect(Account.find_remote('ALICE', 'MASTODON.SOCIAL')).to_not be_nil
  211. end
  212. it 'does not return anything for a_ice@mastodon.social' do
  213. expect(Account.find_remote('a_ice', 'mastodon.social')).to be_nil
  214. end
  215. it 'does not return anything for alice@m_stodon.social' do
  216. expect(Account.find_remote('alice', 'm_stodon.social')).to be_nil
  217. end
  218. it 'does not return anything for alice@m%' do
  219. expect(Account.find_remote('alice', 'm%')).to be_nil
  220. end
  221. end
  222. describe '.following_map' do
  223. it 'returns an hash' do
  224. expect(Account.following_map([], 1)).to be_a Hash
  225. end
  226. end
  227. describe '.followed_by_map' do
  228. it 'returns an hash' do
  229. expect(Account.followed_by_map([], 1)).to be_a Hash
  230. end
  231. end
  232. describe '.blocking_map' do
  233. it 'returns an hash' do
  234. expect(Account.blocking_map([], 1)).to be_a Hash
  235. end
  236. end
  237. describe '.requested_map' do
  238. it 'returns an hash' do
  239. expect(Account.requested_map([], 1)).to be_a Hash
  240. end
  241. end
  242. describe 'MENTION_RE' do
  243. subject { Account::MENTION_RE }
  244. it 'matches usernames in the middle of a sentence' do
  245. expect(subject.match('Hello to @alice from me')[1]).to eq 'alice'
  246. end
  247. it 'matches usernames in the beginning of status' do
  248. expect(subject.match('@alice Hey how are you?')[1]).to eq 'alice'
  249. end
  250. it 'matches full usernames' do
  251. expect(subject.match('@alice@example.com')[1]).to eq 'alice@example.com'
  252. end
  253. it 'matches full usernames with a dot at the end' do
  254. expect(subject.match('Hello @alice@example.com.')[1]).to eq 'alice@example.com'
  255. end
  256. it 'matches dot-prepended usernames' do
  257. expect(subject.match('.@alice I want everybody to see this')[1]).to eq 'alice'
  258. end
  259. it 'does not match e-mails' do
  260. expect(subject.match('Drop me an e-mail at alice@example.com')).to be_nil
  261. end
  262. it 'does not match URLs' do
  263. expect(subject.match('Check this out https://medium.com/@alice/some-article#.abcdef123')).to be_nil
  264. end
  265. end
  266. describe 'validations' do
  267. it 'has a valid fabricator' do
  268. account = Fabricate.build(:account)
  269. account.valid?
  270. expect(account).to be_valid
  271. end
  272. it 'is invalid without a username' do
  273. account = Fabricate.build(:account, username: nil)
  274. account.valid?
  275. expect(account).to model_have_error_on_field(:username)
  276. end
  277. it 'is invalid if the username already exists' do
  278. account_1 = Fabricate(:account, username: 'the_doctor')
  279. account_2 = Fabricate.build(:account, username: 'the_doctor')
  280. account_2.valid?
  281. expect(account_2).to model_have_error_on_field(:username)
  282. end
  283. context 'when is local' do
  284. it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do
  285. account = Fabricate.build(:account, username: 'the-doctor')
  286. account.valid?
  287. expect(account).to model_have_error_on_field(:username)
  288. end
  289. it 'is invalid if the username is longer then 30 characters' do
  290. account = Fabricate.build(:account, username: Faker::Lorem.characters(31))
  291. account.valid?
  292. expect(account).to model_have_error_on_field(:username)
  293. end
  294. end
  295. end
  296. describe 'scopes' do
  297. describe 'remote' do
  298. it 'returns an array of accounts who have a domain' do
  299. account_1 = Fabricate(:account, domain: nil)
  300. account_2 = Fabricate(:account, domain: 'example.com')
  301. expect(Account.remote).to match_array([account_2])
  302. end
  303. end
  304. describe 'local' do
  305. it 'returns an array of accounts who do not have a domain' do
  306. account_1 = Fabricate(:account, domain: nil)
  307. account_2 = Fabricate(:account, domain: 'example.com')
  308. expect(Account.local).to match_array([account_1])
  309. end
  310. end
  311. describe 'silenced' do
  312. it 'returns an array of accounts who are silenced' do
  313. account_1 = Fabricate(:account, silenced: true)
  314. account_2 = Fabricate(:account, silenced: false)
  315. expect(Account.silenced).to match_array([account_1])
  316. end
  317. end
  318. describe 'suspended' do
  319. it 'returns an array of accounts who are suspended' do
  320. account_1 = Fabricate(:account, suspended: true)
  321. account_2 = Fabricate(:account, suspended: false)
  322. expect(Account.suspended).to match_array([account_1])
  323. end
  324. end
  325. end
  326. end