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.

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