Add ActivityPub inbox (#4216)
* Add ActivityPub inbox * Handle ActivityPub deletes * Handle ActivityPub creates * Handle ActivityPub announces * Stubs for handling all activities that need to be handled * Add ActivityPub actor resolving * Handle conversation URI passing in ActivityPub * Handle content language in ActivityPub * Send accept header when fetching actor, handle JSON parse errors * Test for ActivityPub::FetchRemoteAccountService * Handle public key and icon/image when embedded/as array/as resolvable URI * Implement ActivityPub::FetchRemoteStatusService * Add stubs for more interactions * Undo activities implemented * Handle out of order activities * Hook up ActivityPub to ResolveRemoteAccountService, handle Update Account activities * Add fragment IDs to all transient activity serializers * Add tests and fixes * Add stubs for missing tests * Add more tests * Add more tests
This commit is contained in:
		
							
								
								
									
										29
									
								
								spec/lib/activitypub/activity/announce_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								spec/lib/activitypub/activity/announce_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Announce do
 | 
			
		||||
  let(:sender)    { Fabricate(:account) }
 | 
			
		||||
  let(:recipient) { Fabricate(:account) }
 | 
			
		||||
  let(:status)    { Fabricate(:status, account: recipient) }
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Announce',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: ActivityPub::TagManager.instance.uri_for(status),
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      subject.perform
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'creates a reblog by sender of status' do
 | 
			
		||||
      expect(sender.reblogged?(status)).to be true
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										28
									
								
								spec/lib/activitypub/activity/block_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								spec/lib/activitypub/activity/block_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Block do
 | 
			
		||||
  let(:sender)    { Fabricate(:account) }
 | 
			
		||||
  let(:recipient) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Block',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: ActivityPub::TagManager.instance.uri_for(recipient),
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      subject.perform
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'creates a block from sender to recipient' do
 | 
			
		||||
      expect(sender.blocking?(recipient)).to be true
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										221
									
								
								spec/lib/activitypub/activity/create_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								spec/lib/activitypub/activity/create_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,221 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Create do
 | 
			
		||||
  let(:sender) { Fabricate(:account, followers_url: 'http://example.com/followers') }
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Create',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: object_json,
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
  before do
 | 
			
		||||
    stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    before do
 | 
			
		||||
      subject.perform
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'standalone' do
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.text).to eq 'Lorem ipsum'
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'missing to/cc defaults to direct privacy' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.visibility).to eq 'direct'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'public' do
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          to: 'https://www.w3.org/ns/activitystreams#Public',
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.visibility).to eq 'public'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'unlisted' do
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          cc: 'https://www.w3.org/ns/activitystreams#Public',
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.visibility).to eq 'unlisted'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'private' do
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          to: 'http://example.com/followers',
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.visibility).to eq 'private'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'direct' do
 | 
			
		||||
      let(:recipient) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          to: ActivityPub::TagManager.instance.uri_for(recipient),
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.visibility).to eq 'direct'
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'as a reply' do
 | 
			
		||||
      let(:original_status) { Fabricate(:status) }
 | 
			
		||||
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          inReplyTo: ActivityPub::TagManager.instance.uri_for(original_status),
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.thread).to eq original_status
 | 
			
		||||
        expect(status.reply?).to be true
 | 
			
		||||
        expect(status.in_reply_to_account).to eq original_status.account
 | 
			
		||||
        expect(status.conversation).to eq original_status.conversation
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with mentions' do
 | 
			
		||||
      let(:recipient) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          tag: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'Mention',
 | 
			
		||||
              href: ActivityPub::TagManager.instance.uri_for(recipient),
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.mentions.map(&:account)).to include(recipient)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with media attachments' do
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          attachment: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'Document',
 | 
			
		||||
              mime_type: 'image/png',
 | 
			
		||||
              url: 'http://example.com/attachment.png',
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.media_attachments.map(&:remote_url)).to include('http://example.com/attachment.png')
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with hashtags' do
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Note',
 | 
			
		||||
          content: 'Lorem ipsum',
 | 
			
		||||
          tag: [
 | 
			
		||||
            {
 | 
			
		||||
              type: 'Hashtag',
 | 
			
		||||
              href: 'http://example.com/blah',
 | 
			
		||||
              name: '#test',
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'creates status' do
 | 
			
		||||
        status = sender.statuses.first
 | 
			
		||||
 | 
			
		||||
        expect(status).to_not be_nil
 | 
			
		||||
        expect(status.tags.map(&:name)).to include('test')
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										28
									
								
								spec/lib/activitypub/activity/delete_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								spec/lib/activitypub/activity/delete_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Delete do
 | 
			
		||||
  let(:sender)    { Fabricate(:account) }
 | 
			
		||||
  let(:status)    { Fabricate(:status, account: sender, uri: 'foobar') }
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Delete',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: ActivityPub::TagManager.instance.uri_for(status),
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      subject.perform
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'deletes sender\'s status' do
 | 
			
		||||
      expect(Status.find_by(id: status.id)).to be_nil
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										28
									
								
								spec/lib/activitypub/activity/follow_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								spec/lib/activitypub/activity/follow_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Follow do
 | 
			
		||||
  let(:sender)    { Fabricate(:account) }
 | 
			
		||||
  let(:recipient) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Follow',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: ActivityPub::TagManager.instance.uri_for(recipient),
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      subject.perform
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'creates a follow from sender to recipient' do
 | 
			
		||||
      expect(sender.following?(recipient)).to be true
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										29
									
								
								spec/lib/activitypub/activity/like_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								spec/lib/activitypub/activity/like_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Like do
 | 
			
		||||
  let(:sender)    { Fabricate(:account) }
 | 
			
		||||
  let(:recipient) { Fabricate(:account) }
 | 
			
		||||
  let(:status)    { Fabricate(:status, account: recipient) }
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Like',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: ActivityPub::TagManager.instance.uri_for(status),
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      subject.perform
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'creates a favourite from sender to status' do
 | 
			
		||||
      expect(sender.favourited?(status)).to be true
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										107
									
								
								spec/lib/activitypub/activity/undo_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								spec/lib/activitypub/activity/undo_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Undo do
 | 
			
		||||
  let(:sender) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Undo',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: object_json,
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    context 'with Announce' do
 | 
			
		||||
      let(:status) { Fabricate(:status) }
 | 
			
		||||
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Announce',
 | 
			
		||||
          actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
          object: ActivityPub::TagManager.instance.uri_for(status),
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        Fabricate(:status, reblog: status, account: sender, uri: 'bar')
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'deletes the reblog' do
 | 
			
		||||
        subject.perform
 | 
			
		||||
        expect(sender.reblogged?(status)).to be false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with Block' do
 | 
			
		||||
      let(:recipient) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Block',
 | 
			
		||||
          actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
          object: ActivityPub::TagManager.instance.uri_for(recipient),
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        sender.block!(recipient)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'deletes block from sender to recipient' do
 | 
			
		||||
        subject.perform
 | 
			
		||||
        expect(sender.blocking?(recipient)).to be false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with Follow' do
 | 
			
		||||
      let(:recipient) { Fabricate(:account) }
 | 
			
		||||
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Follow',
 | 
			
		||||
          actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
          object: ActivityPub::TagManager.instance.uri_for(recipient),
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        sender.follow!(recipient)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'deletes follow from sender to recipient' do
 | 
			
		||||
        subject.perform
 | 
			
		||||
        expect(sender.following?(recipient)).to be false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with Like' do
 | 
			
		||||
      let(:status) { Fabricate(:status) }
 | 
			
		||||
 | 
			
		||||
      let(:object_json) do
 | 
			
		||||
        {
 | 
			
		||||
          id: 'bar',
 | 
			
		||||
          type: 'Like',
 | 
			
		||||
          actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
          object: ActivityPub::TagManager.instance.uri_for(status),
 | 
			
		||||
        }
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      before do
 | 
			
		||||
        Fabricate(:favourite, account: sender, status: status)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      it 'deletes favourite from sender to status' do
 | 
			
		||||
        subject.perform
 | 
			
		||||
        expect(sender.favourited?(status)).to be false
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										41
									
								
								spec/lib/activitypub/activity/update_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								spec/lib/activitypub/activity/update_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
require 'rails_helper'
 | 
			
		||||
 | 
			
		||||
RSpec.describe ActivityPub::Activity::Update do
 | 
			
		||||
  let!(:sender) { Fabricate(:account) }
 | 
			
		||||
  
 | 
			
		||||
  before do
 | 
			
		||||
    sender.update!(uri: ActivityPub::TagManager.instance.uri_for(sender))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  let(:modified_sender) do 
 | 
			
		||||
    sender.dup.tap do |modified_sender|
 | 
			
		||||
      modified_sender.display_name = 'Totally modified now'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  let(:actor_json) do
 | 
			
		||||
    ActiveModelSerializers::SerializableResource.new(modified_sender, serializer: ActivityPub::ActorSerializer, key_transform: :camel_lower).as_json
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  let(:json) do
 | 
			
		||||
    {
 | 
			
		||||
      '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
      id: 'foo',
 | 
			
		||||
      type: 'Update',
 | 
			
		||||
      actor: ActivityPub::TagManager.instance.uri_for(sender),
 | 
			
		||||
      object: actor_json,
 | 
			
		||||
    }.with_indifferent_access
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  describe '#perform' do
 | 
			
		||||
    subject { described_class.new(json, sender) }
 | 
			
		||||
 | 
			
		||||
    before do
 | 
			
		||||
      subject.perform
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    it 'updates profile' do
 | 
			
		||||
      expect(sender.reload.display_name).to eq 'Totally modified now'
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Reference in New Issue
	
	Block a user