The code powering m.abunchtell.com https://m.abunchtell.com
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.
 
 
 
 

596 lines
16 KiB

  1. require 'rails_helper'
  2. RSpec.describe ActivityPub::Activity::Create do
  3. let(:sender) { Fabricate(:account, followers_url: 'http://example.com/followers', domain: 'example.com', uri: 'https://example.com/actor') }
  4. let(:json) do
  5. {
  6. '@context': 'https://www.w3.org/ns/activitystreams',
  7. id: [ActivityPub::TagManager.instance.uri_for(sender), '#foo'].join,
  8. type: 'Create',
  9. actor: ActivityPub::TagManager.instance.uri_for(sender),
  10. object: object_json,
  11. }.with_indifferent_access
  12. end
  13. before do
  14. sender.update(uri: ActivityPub::TagManager.instance.uri_for(sender))
  15. stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
  16. stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png'))
  17. end
  18. describe '#perform' do
  19. context 'when fetching' do
  20. subject { described_class.new(json, sender) }
  21. before do
  22. subject.perform
  23. end
  24. context 'standalone' do
  25. let(:object_json) do
  26. {
  27. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  28. type: 'Note',
  29. content: 'Lorem ipsum',
  30. }
  31. end
  32. it 'creates status' do
  33. status = sender.statuses.first
  34. expect(status).to_not be_nil
  35. expect(status.text).to eq 'Lorem ipsum'
  36. end
  37. it 'missing to/cc defaults to direct privacy' do
  38. status = sender.statuses.first
  39. expect(status).to_not be_nil
  40. expect(status.visibility).to eq 'direct'
  41. end
  42. end
  43. context 'public' do
  44. let(:object_json) do
  45. {
  46. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  47. type: 'Note',
  48. content: 'Lorem ipsum',
  49. to: 'https://www.w3.org/ns/activitystreams#Public',
  50. }
  51. end
  52. it 'creates status' do
  53. status = sender.statuses.first
  54. expect(status).to_not be_nil
  55. expect(status.visibility).to eq 'public'
  56. end
  57. end
  58. context 'unlisted' do
  59. let(:object_json) do
  60. {
  61. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  62. type: 'Note',
  63. content: 'Lorem ipsum',
  64. cc: 'https://www.w3.org/ns/activitystreams#Public',
  65. }
  66. end
  67. it 'creates status' do
  68. status = sender.statuses.first
  69. expect(status).to_not be_nil
  70. expect(status.visibility).to eq 'unlisted'
  71. end
  72. end
  73. context 'private' do
  74. let(:object_json) do
  75. {
  76. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  77. type: 'Note',
  78. content: 'Lorem ipsum',
  79. to: 'http://example.com/followers',
  80. }
  81. end
  82. it 'creates status' do
  83. status = sender.statuses.first
  84. expect(status).to_not be_nil
  85. expect(status.visibility).to eq 'private'
  86. end
  87. end
  88. context 'limited' do
  89. let(:recipient) { Fabricate(:account) }
  90. let(:object_json) do
  91. {
  92. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  93. type: 'Note',
  94. content: 'Lorem ipsum',
  95. to: ActivityPub::TagManager.instance.uri_for(recipient),
  96. }
  97. end
  98. it 'creates status' do
  99. status = sender.statuses.first
  100. expect(status).to_not be_nil
  101. expect(status.visibility).to eq 'limited'
  102. end
  103. it 'creates silent mention' do
  104. status = sender.statuses.first
  105. expect(status.mentions.first).to be_silent
  106. end
  107. end
  108. context 'direct' do
  109. let(:recipient) { Fabricate(:account) }
  110. let(:object_json) do
  111. {
  112. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  113. type: 'Note',
  114. content: 'Lorem ipsum',
  115. to: ActivityPub::TagManager.instance.uri_for(recipient),
  116. tag: {
  117. type: 'Mention',
  118. href: ActivityPub::TagManager.instance.uri_for(recipient),
  119. },
  120. }
  121. end
  122. it 'creates status' do
  123. status = sender.statuses.first
  124. expect(status).to_not be_nil
  125. expect(status.visibility).to eq 'direct'
  126. end
  127. end
  128. context 'as a reply' do
  129. let(:original_status) { Fabricate(:status) }
  130. let(:object_json) do
  131. {
  132. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  133. type: 'Note',
  134. content: 'Lorem ipsum',
  135. inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
  136. }
  137. end
  138. it 'creates status' do
  139. status = sender.statuses.first
  140. expect(status).to_not be_nil
  141. expect(status.thread).to eq original_status
  142. expect(status.reply?).to be true
  143. expect(status.in_reply_to_account).to eq original_status.account
  144. expect(status.conversation).to eq original_status.conversation
  145. end
  146. end
  147. context 'with mentions' do
  148. let(:recipient) { Fabricate(:account) }
  149. let(:object_json) do
  150. {
  151. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  152. type: 'Note',
  153. content: 'Lorem ipsum',
  154. tag: [
  155. {
  156. type: 'Mention',
  157. href: ActivityPub::TagManager.instance.uri_for(recipient),
  158. },
  159. ],
  160. }
  161. end
  162. it 'creates status' do
  163. status = sender.statuses.first
  164. expect(status).to_not be_nil
  165. expect(status.mentions.map(&:account)).to include(recipient)
  166. end
  167. end
  168. context 'with mentions missing href' do
  169. let(:object_json) do
  170. {
  171. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  172. type: 'Note',
  173. content: 'Lorem ipsum',
  174. tag: [
  175. {
  176. type: 'Mention',
  177. },
  178. ],
  179. }
  180. end
  181. it 'creates status' do
  182. status = sender.statuses.first
  183. expect(status).to_not be_nil
  184. end
  185. end
  186. context 'with media attachments' do
  187. let(:object_json) do
  188. {
  189. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  190. type: 'Note',
  191. content: 'Lorem ipsum',
  192. attachment: [
  193. {
  194. type: 'Document',
  195. mediaType: 'image/png',
  196. url: 'http://example.com/attachment.png',
  197. },
  198. ],
  199. }
  200. end
  201. it 'creates status' do
  202. status = sender.statuses.first
  203. expect(status).to_not be_nil
  204. expect(status.media_attachments.map(&:remote_url)).to include('http://example.com/attachment.png')
  205. end
  206. end
  207. context 'with media attachments with focal points' do
  208. let(:object_json) do
  209. {
  210. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  211. type: 'Note',
  212. content: 'Lorem ipsum',
  213. attachment: [
  214. {
  215. type: 'Document',
  216. mediaType: 'image/png',
  217. url: 'http://example.com/attachment.png',
  218. focalPoint: [0.5, -0.7],
  219. },
  220. ],
  221. }
  222. end
  223. it 'creates status' do
  224. status = sender.statuses.first
  225. expect(status).to_not be_nil
  226. expect(status.media_attachments.map(&:focus)).to include('0.5,-0.7')
  227. end
  228. end
  229. context 'with media attachments missing url' do
  230. let(:object_json) do
  231. {
  232. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  233. type: 'Note',
  234. content: 'Lorem ipsum',
  235. attachment: [
  236. {
  237. type: 'Document',
  238. mediaType: 'image/png',
  239. },
  240. ],
  241. }
  242. end
  243. it 'creates status' do
  244. status = sender.statuses.first
  245. expect(status).to_not be_nil
  246. end
  247. end
  248. context 'with hashtags' do
  249. let(:object_json) do
  250. {
  251. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  252. type: 'Note',
  253. content: 'Lorem ipsum',
  254. tag: [
  255. {
  256. type: 'Hashtag',
  257. href: 'http://example.com/blah',
  258. name: '#test',
  259. },
  260. ],
  261. }
  262. end
  263. it 'creates status' do
  264. status = sender.statuses.first
  265. expect(status).to_not be_nil
  266. expect(status.tags.map(&:name)).to include('test')
  267. end
  268. end
  269. context 'with hashtags missing name' do
  270. let(:object_json) do
  271. {
  272. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  273. type: 'Note',
  274. content: 'Lorem ipsum',
  275. tag: [
  276. {
  277. type: 'Hashtag',
  278. href: 'http://example.com/blah',
  279. },
  280. ],
  281. }
  282. end
  283. it 'creates status' do
  284. status = sender.statuses.first
  285. expect(status).to_not be_nil
  286. end
  287. end
  288. context 'with emojis' do
  289. let(:object_json) do
  290. {
  291. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  292. type: 'Note',
  293. content: 'Lorem ipsum :tinking:',
  294. tag: [
  295. {
  296. type: 'Emoji',
  297. icon: {
  298. url: 'http://example.com/emoji.png',
  299. },
  300. name: 'tinking',
  301. },
  302. ],
  303. }
  304. end
  305. it 'creates status' do
  306. status = sender.statuses.first
  307. expect(status).to_not be_nil
  308. expect(status.emojis.map(&:shortcode)).to include('tinking')
  309. end
  310. end
  311. context 'with emojis missing name' do
  312. let(:object_json) do
  313. {
  314. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  315. type: 'Note',
  316. content: 'Lorem ipsum :tinking:',
  317. tag: [
  318. {
  319. type: 'Emoji',
  320. icon: {
  321. url: 'http://example.com/emoji.png',
  322. },
  323. },
  324. ],
  325. }
  326. end
  327. it 'creates status' do
  328. status = sender.statuses.first
  329. expect(status).to_not be_nil
  330. end
  331. end
  332. context 'with emojis missing icon' do
  333. let(:object_json) do
  334. {
  335. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  336. type: 'Note',
  337. content: 'Lorem ipsum :tinking:',
  338. tag: [
  339. {
  340. type: 'Emoji',
  341. name: 'tinking',
  342. },
  343. ],
  344. }
  345. end
  346. it 'creates status' do
  347. status = sender.statuses.first
  348. expect(status).to_not be_nil
  349. end
  350. end
  351. context 'with poll' do
  352. let(:object_json) do
  353. {
  354. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  355. type: 'Question',
  356. content: 'Which color was the submarine?',
  357. oneOf: [
  358. {
  359. name: 'Yellow',
  360. replies: {
  361. type: 'Collection',
  362. totalItems: 10,
  363. },
  364. },
  365. {
  366. name: 'Blue',
  367. replies: {
  368. type: 'Collection',
  369. totalItems: 3,
  370. }
  371. },
  372. ],
  373. }
  374. end
  375. it 'creates status' do
  376. status = sender.statuses.first
  377. expect(status).to_not be_nil
  378. expect(status.poll).to_not be_nil
  379. end
  380. it 'creates a poll' do
  381. poll = sender.polls.first
  382. expect(poll).to_not be_nil
  383. expect(poll.status).to_not be_nil
  384. expect(poll.options).to eq %w(Yellow Blue)
  385. expect(poll.cached_tallies).to eq [10, 3]
  386. end
  387. end
  388. context 'when a vote to a local poll' do
  389. let(:poll) { Fabricate(:poll, options: %w(Yellow Blue)) }
  390. let!(:local_status) { Fabricate(:status, owned_poll: poll) }
  391. let(:object_json) do
  392. {
  393. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  394. type: 'Note',
  395. name: 'Yellow',
  396. inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status)
  397. }
  398. end
  399. it 'adds a vote to the poll with correct uri' do
  400. vote = poll.votes.first
  401. expect(vote).to_not be_nil
  402. expect(vote.uri).to eq object_json[:id]
  403. expect(poll.reload.cached_tallies).to eq [1, 0]
  404. end
  405. end
  406. end
  407. context 'when sender is followed by local users' do
  408. subject { described_class.new(json, sender, delivery: true) }
  409. before do
  410. Fabricate(:account).follow!(sender)
  411. subject.perform
  412. end
  413. let(:object_json) do
  414. {
  415. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  416. type: 'Note',
  417. content: 'Lorem ipsum',
  418. }
  419. end
  420. it 'creates status' do
  421. status = sender.statuses.first
  422. expect(status).to_not be_nil
  423. expect(status.text).to eq 'Lorem ipsum'
  424. end
  425. end
  426. context 'when sender replies to local status' do
  427. let!(:local_status) { Fabricate(:status) }
  428. subject { described_class.new(json, sender, delivery: true) }
  429. before do
  430. subject.perform
  431. end
  432. let(:object_json) do
  433. {
  434. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  435. type: 'Note',
  436. content: 'Lorem ipsum',
  437. inReplyTo: ActivityPub::TagManager.instance.uri_for(local_status),
  438. }
  439. end
  440. it 'creates status' do
  441. status = sender.statuses.first
  442. expect(status).to_not be_nil
  443. expect(status.text).to eq 'Lorem ipsum'
  444. end
  445. end
  446. context 'when sender targets a local user' do
  447. let!(:local_account) { Fabricate(:account) }
  448. subject { described_class.new(json, sender, delivery: true) }
  449. before do
  450. subject.perform
  451. end
  452. let(:object_json) do
  453. {
  454. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  455. type: 'Note',
  456. content: 'Lorem ipsum',
  457. to: ActivityPub::TagManager.instance.uri_for(local_account),
  458. }
  459. end
  460. it 'creates status' do
  461. status = sender.statuses.first
  462. expect(status).to_not be_nil
  463. expect(status.text).to eq 'Lorem ipsum'
  464. end
  465. end
  466. context 'when sender cc\'s a local user' do
  467. let!(:local_account) { Fabricate(:account) }
  468. subject { described_class.new(json, sender, delivery: true) }
  469. before do
  470. subject.perform
  471. end
  472. let(:object_json) do
  473. {
  474. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  475. type: 'Note',
  476. content: 'Lorem ipsum',
  477. cc: ActivityPub::TagManager.instance.uri_for(local_account),
  478. }
  479. end
  480. it 'creates status' do
  481. status = sender.statuses.first
  482. expect(status).to_not be_nil
  483. expect(status.text).to eq 'Lorem ipsum'
  484. end
  485. end
  486. context 'when the sender has no relevance to local activity' do
  487. subject { described_class.new(json, sender, delivery: true) }
  488. before do
  489. subject.perform
  490. end
  491. let(:object_json) do
  492. {
  493. id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
  494. type: 'Note',
  495. content: 'Lorem ipsum',
  496. }
  497. end
  498. it 'does not create anything' do
  499. expect(sender.statuses.count).to eq 0
  500. end
  501. end
  502. end
  503. end