about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/lib/status_cache_hydrator.rb22
-rw-r--r--spec/lib/status_cache_hydrator_spec.rb111
2 files changed, 101 insertions, 32 deletions
diff --git a/app/lib/status_cache_hydrator.rb b/app/lib/status_cache_hydrator.rb
index 01e92b385..552419fff 100644
--- a/app/lib/status_cache_hydrator.rb
+++ b/app/lib/status_cache_hydrator.rb
@@ -16,23 +16,35 @@ class StatusCacheHydrator
     # We take advantage of the fact that some relationships can only occur with an original status, not
     # the reblog that wraps it, so we can assume that some values are always false
     if payload[:reblog]
-      payload[:favourited] = false
-      payload[:reblogged]  = false
       payload[:muted]      = false
       payload[:bookmarked] = false
-      payload[:pinned]     = false
+      payload[:pinned]     = false if @status.account_id == account_id
       payload[:filtered]   = CustomFilter.apply_cached_filters(CustomFilter.cached_filters_for(@status.reblog_of_id), @status.reblog).map { |filter| ActiveModelSerializers::SerializableResource.new(filter, serializer: REST::FilterResultSerializer).as_json }
 
       # If the reblogged status is being delivered to the author who disabled the display of the application
       # used to create the status, we need to hydrate it here too
-      payload[:reblog][:application] = ActiveModelSerializers::SerializableResource.new(@status.reblog.application, serializer: REST::StatusSerializer::ApplicationSerializer).as_json if payload[:reblog][:application].nil? && @status.reblog.account_id == account_id
+      payload[:reblog][:application] = ActiveModelSerializers::SerializableResource.new(@status.reblog.application, serializer: REST::StatusSerializer::ApplicationSerializer).as_json if payload[:reblog][:application].nil? && @status.reblog.account_id == account_id && @status.reblog.application_id.present?
 
       payload[:reblog][:favourited] = Favourite.where(account_id: account_id, status_id: @status.reblog_of_id).exists?
       payload[:reblog][:reblogged]  = Status.where(account_id: account_id, reblog_of_id: @status.reblog_of_id).exists?
       payload[:reblog][:muted]      = ConversationMute.where(account_id: account_id, conversation_id: @status.reblog.conversation_id).exists?
       payload[:reblog][:bookmarked] = Bookmark.where(account_id: account_id, status_id: @status.reblog_of_id).exists?
-      payload[:reblog][:pinned]     = StatusPin.where(account_id: account_id, status_id: @status.reblog_of_id).exists?
+      payload[:reblog][:pinned]     = StatusPin.where(account_id: account_id, status_id: @status.reblog_of_id).exists? if @status.reblog.account_id == account_id
       payload[:reblog][:filtered]   = payload[:filtered]
+
+      if payload[:reblog][:poll]
+        if @status.reblog.account_id == account_id
+          payload[:reblog][:poll][:voted] = true
+          payload[:reblog][:poll][:own_votes] = []
+        else
+          own_votes = @status.reblog.poll.votes.where(account_id: account_id).pluck(:choice)
+          payload[:reblog][:poll][:voted] = !own_votes.empty?
+          payload[:reblog][:poll][:own_votes] = own_votes
+        end
+      end
+
+      payload[:favourited] = payload[:reblog][:favourited]
+      payload[:reblogged]  = payload[:reblog][:reblogged]
     else
       payload[:favourited] = Favourite.where(account_id: account_id, status_id: @status.id).exists?
       payload[:reblogged]  = Status.where(account_id: account_id, reblog_of_id: @status.id).exists?
diff --git a/spec/lib/status_cache_hydrator_spec.rb b/spec/lib/status_cache_hydrator_spec.rb
index ad9940a85..873d58464 100644
--- a/spec/lib/status_cache_hydrator_spec.rb
+++ b/spec/lib/status_cache_hydrator_spec.rb
@@ -7,48 +7,105 @@ describe StatusCacheHydrator do
   let(:account) { Fabricate(:account) }
 
   describe '#hydrate' do
-    subject { described_class.new(status).hydrate(account.id) }
-
     let(:compare_to_hash) { InlineRenderer.render(status, account, :status) }
 
-    context 'when cache is warm' do
-      before do
-        Rails.cache.write("fan-out/#{status.id}", InlineRenderer.render(status, nil, :status))
+    shared_examples 'shared behavior' do
+      context 'when handling a new status' do
+        it 'renders the same attributes as a full render' do
+          expect(subject).to include(compare_to_hash)
+        end
       end
 
-      it 'renders the same attributes as a full render' do
-        expect(subject).to include(compare_to_hash)
-      end
-    end
+      context 'when handling a reblog' do
+        let(:reblog) { Fabricate(:status) }
+        let(:status) { Fabricate(:status, reblog: reblog) }
 
-    context 'when cache is cold' do
-      before do
-        Rails.cache.delete("fan-out/#{status.id}")
-      end
+        context 'that has been favourited' do
+          before do
+            FavouriteService.new.call(account, reblog)
+          end
+
+          it 'renders the same attributes as a full render' do
+            expect(subject).to include(compare_to_hash)
+          end
+        end
+
+        context 'that has been reblogged' do
+          before do
+            ReblogService.new.call(account, reblog)
+          end
+
+          it 'renders the same attributes as a full render' do
+            expect(subject).to include(compare_to_hash)
+          end
+        end
+
+        context 'that has been pinned' do
+          let(:reblog) { Fabricate(:status, account: account) }
+
+          before do
+            StatusPin.create!(account: account, status: reblog)
+          end
+
+          it 'renders the same attributes as a full render' do
+            expect(subject).to include(compare_to_hash)
+          end
+        end
 
-      it 'renders the same attributes as a full render' do
-        expect(subject).to include(compare_to_hash)
+        context 'that has been followed tags' do
+          let(:followed_tag) { Fabricate(:tag) }
+
+          before do
+            reblog.tags << Fabricate(:tag)
+            reblog.tags << followed_tag
+            TagFollow.create!(tag: followed_tag, account: account, rate_limit: false)
+          end
+
+          it 'renders the same attributes as a full render' do
+            expect(subject).to include(compare_to_hash)
+          end
+        end
+
+        context 'that has a poll authored by the user' do
+          let(:poll) { Fabricate(:poll, account: account) }
+          let(:reblog) { Fabricate(:status, poll: poll, account: account) }
+
+          it 'renders the same attributes as a full render' do
+            expect(subject).to include(compare_to_hash)
+          end
+        end
+
+        context 'that has been voted in' do
+          let(:poll) { Fabricate(:poll, options: %w(Yellow Blue)) }
+          let(:reblog) { Fabricate(:status, poll: poll) }
+
+          before do
+            VoteService.new.call(account, poll, [0])
+          end
+
+          it 'renders the same attributes as a full render' do
+            expect(subject).to include(compare_to_hash)
+          end
+        end
       end
     end
 
-    context 'when account has favourited status' do
-      before do
-        FavouriteService.new.call(account, status)
+    context 'when cache is warm' do
+      subject do
+        Rails.cache.write("fan-out/#{status.id}", InlineRenderer.render(status, nil, :status))
+        described_class.new(status).hydrate(account.id)
       end
 
-      it 'renders the same attributes as a full render' do
-        expect(subject).to include(compare_to_hash)
-      end
+      it_behaves_like 'shared behavior'
     end
 
-    context 'when account has reblogged status' do
-      before do
-        ReblogService.new.call(account, status)
+    context 'when cache is cold' do
+      subject do
+        Rails.cache.delete("fan-out/#{status.id}")
+        described_class.new(status).hydrate(account.id)
       end
 
-      it 'renders the same attributes as a full render' do
-        expect(subject).to include(compare_to_hash)
-      end
+      it_behaves_like 'shared behavior'
     end
   end
 end