Remove unused ActivityPub @context values depending on response (#10378)
				
					
				
			Fix #8078
This commit is contained in:
		| @@ -1,30 +1,23 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base | ||||
|   CONTEXT = { | ||||
|     '@context': [ | ||||
|       'https://www.w3.org/ns/activitystreams', | ||||
|       'https://w3id.org/security/v1', | ||||
|   NAMED_CONTEXT_MAP = { | ||||
|     activitystreams: 'https://www.w3.org/ns/activitystreams', | ||||
|     security: 'https://w3id.org/security/v1', | ||||
|   }.freeze | ||||
|  | ||||
|       { | ||||
|         'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', | ||||
|         'sensitive'                 => 'as:sensitive', | ||||
|         'movedTo'                   => { '@id' => 'as:movedTo', '@type' => '@id' }, | ||||
|         'alsoKnownAs'               => { '@id' => 'as:alsoKnownAs', '@type' => '@id' }, | ||||
|         'Hashtag'                   => 'as:Hashtag', | ||||
|         'ostatus'                   => 'http://ostatus.org#', | ||||
|         'atomUri'                   => 'ostatus:atomUri', | ||||
|         'inReplyToAtomUri'          => 'ostatus:inReplyToAtomUri', | ||||
|         'conversation'              => 'ostatus:conversation', | ||||
|         'toot'                      => 'http://joinmastodon.org/ns#', | ||||
|         'Emoji'                     => 'toot:Emoji', | ||||
|         'focalPoint'                => { '@container' => '@list', '@id' => 'toot:focalPoint' }, | ||||
|         'featured'                  => { '@id' => 'toot:featured', '@type' => '@id' }, | ||||
|         'schema'                    => 'http://schema.org#', | ||||
|         'PropertyValue'             => 'schema:PropertyValue', | ||||
|         'value'                     => 'schema:value', | ||||
|       }, | ||||
|     ], | ||||
|   CONTEXT_EXTENSION_MAP = { | ||||
|     manually_approves_followers: { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers' }, | ||||
|     sensitive: { 'sensitive' => 'as:sensitive' }, | ||||
|     hashtag: { 'Hashtag' => 'as:Hashtag' }, | ||||
|     moved_to: { 'movedTo' => { '@id' => 'as:movedTo', '@type' => '@id' } }, | ||||
|     also_known_as: { 'alsoKnownAs' => { '@id' => 'as:alsoKnownAs', '@type' => '@id' } }, | ||||
|     emoji: { 'toot' => 'http://joinmastodon.org/ns#', 'Emoji' => 'toot:Emoji' }, | ||||
|     featured: { 'toot' => 'http://joinmastodon.org/ns#', 'featured' => { '@id' => 'toot:featured', '@type' => '@id' } }, | ||||
|     property_value: { 'schema' => 'http://schema.org#', 'PropertyValue' => 'schema:PropertyValue', 'value' => 'schema:value' }, | ||||
|     atom_uri: { 'ostatus' => 'http://ostatus.org#', 'atomUri' => 'ostatus:atomUri' }, | ||||
|     conversation: { 'ostatus' => 'http://ostatus.org#', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', 'conversation' => 'ostatus:conversation' }, | ||||
|     focal_point: { 'toot' => 'http://joinmastodon.org/ns#', 'focalPoint' => { '@container' => '@list', '@id' => 'toot:focalPoint' } }, | ||||
|   }.freeze | ||||
|  | ||||
|   def self.default_key_transform | ||||
| @@ -37,7 +30,35 @@ class ActivityPub::Adapter < ActiveModelSerializers::Adapter::Base | ||||
|  | ||||
|   def serializable_hash(options = nil) | ||||
|     options         = serialization_options(options) | ||||
|     serialized_hash = ActiveModelSerializers::Adapter::Attributes.new(serializer, instance_options).serializable_hash(options) | ||||
|     CONTEXT.merge(self.class.transform_key_casing!(serialized_hash, instance_options)) | ||||
|     serialized_hash = serializer.serializable_hash(options) | ||||
|     serialized_hash = self.class.transform_key_casing!(serialized_hash, instance_options) | ||||
|  | ||||
|     { '@context' => serialized_context }.merge(serialized_hash) | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def serialized_context | ||||
|     context_array = [] | ||||
|  | ||||
|     serializer_options = serializer.send(:instance_options) || {} | ||||
|     named_contexts     = [:activitystreams] + serializer._named_contexts.keys + serializer_options.fetch(:named_contexts, {}).keys | ||||
|     context_extensions = serializer._context_extensions.keys + serializer_options.fetch(:context_extensions, {}).keys | ||||
|  | ||||
|     named_contexts.each do |key| | ||||
|       context_array << NAMED_CONTEXT_MAP[key] | ||||
|     end | ||||
|  | ||||
|     extensions = context_extensions.each_with_object({}) do |key, h| | ||||
|       h.merge!(CONTEXT_EXTENSION_MAP[key]) | ||||
|     end | ||||
|  | ||||
|     context_array << extensions unless extensions.empty? | ||||
|  | ||||
|     if context_array.size == 1 | ||||
|       context_array.first | ||||
|     else | ||||
|       context_array | ||||
|     end | ||||
|   end | ||||
| end | ||||
|   | ||||
							
								
								
									
										30
									
								
								app/lib/activitypub/serializer.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/lib/activitypub/serializer.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::Serializer < ActiveModel::Serializer | ||||
|   with_options instance_writer: false, instance_reader: true do |serializer| | ||||
|     serializer.class_attribute :_named_contexts | ||||
|     serializer.class_attribute :_context_extensions | ||||
|  | ||||
|     self._named_contexts     ||= {} | ||||
|     self._context_extensions ||= {} | ||||
|   end | ||||
|  | ||||
|   def self.inherited(base) | ||||
|     super | ||||
|  | ||||
|     base._named_contexts     = _named_contexts.dup | ||||
|     base._context_extensions = _context_extensions.dup | ||||
|   end | ||||
|  | ||||
|   def self.context(*named_contexts) | ||||
|     named_contexts.each do |context| | ||||
|       _named_contexts[context] = true | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def self.context_extensions(*extension_names) | ||||
|     extension_names.each do |extension_name| | ||||
|       _context_extensions[extension_name] = true | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::AcceptFollowSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::AcceptFollowSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::FollowSerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::ActivitySerializer < ActiveModel::Serializer | ||||
| class ActivityPub::ActivitySerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor, :published, :to, :cc | ||||
|  | ||||
|   has_one :proper, key: :object, serializer: ActivityPub::NoteSerializer, if: :serialize_object? | ||||
|   | ||||
| @@ -1,8 +1,13 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::ActorSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::ActorSerializer < ActivityPub::Serializer | ||||
|   include RoutingHelper | ||||
|  | ||||
|   context :security | ||||
|  | ||||
|   context_extensions :manually_approves_followers, :featured, :also_known_as, | ||||
|                      :moved_to, :property_value, :hashtag, :emoji | ||||
|  | ||||
|   attributes :id, :type, :following, :followers, | ||||
|              :inbox, :outbox, :featured, | ||||
|              :preferred_username, :name, :summary, | ||||
| @@ -16,7 +21,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer | ||||
|   attribute :moved_to, if: :moved? | ||||
|   attribute :also_known_as, if: :also_known_as? | ||||
|  | ||||
|   class EndpointsSerializer < ActiveModel::Serializer | ||||
|   class EndpointsSerializer < ActivityPub::Serializer | ||||
|     include RoutingHelper | ||||
|  | ||||
|     attributes :shared_inbox | ||||
| @@ -124,7 +129,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer | ||||
|   class CustomEmojiSerializer < ActivityPub::EmojiSerializer | ||||
|   end | ||||
|  | ||||
|   class TagSerializer < ActiveModel::Serializer | ||||
|   class TagSerializer < ActivityPub::Serializer | ||||
|     include RoutingHelper | ||||
|  | ||||
|     attributes :type, :href, :name | ||||
| @@ -142,7 +147,7 @@ class ActivityPub::ActorSerializer < ActiveModel::Serializer | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   class Account::FieldSerializer < ActiveModel::Serializer | ||||
|   class Account::FieldSerializer < ActivityPub::Serializer | ||||
|     attributes :type, :name, :value | ||||
|  | ||||
|     def type | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::AddSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::AddSerializer < ActivityPub::Serializer | ||||
|   include RoutingHelper | ||||
|  | ||||
|   attributes :type, :actor, :target | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::BlockSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::BlockSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|   attribute :virtual_object, key: :object | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::CollectionSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::CollectionSerializer < ActivityPub::Serializer | ||||
|   def self.serializer_for(model, options) | ||||
|     return ActivityPub::NoteSerializer if model.class.name == 'Status' | ||||
|     return ActivityPub::CollectionSerializer if model.class.name == 'ActivityPub::CollectionPresenter' | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::DeleteActorSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::DeleteActorSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor, :to | ||||
|   attribute :virtual_object, key: :object | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::DeleteSerializer < ActiveModel::Serializer | ||||
|   class TombstoneSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::DeleteSerializer < ActivityPub::Serializer | ||||
|   class TombstoneSerializer < ActivityPub::Serializer | ||||
|     context_extensions :atom_uri | ||||
|  | ||||
|     attributes :id, :type, :atom_uri | ||||
|  | ||||
|     def id | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::EmojiSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::EmojiSerializer < ActivityPub::Serializer | ||||
|   include RoutingHelper | ||||
|  | ||||
|   context_extensions :emoji | ||||
|  | ||||
|   attributes :id, :type, :name, :updated | ||||
|  | ||||
|   has_one :icon, serializer: ActivityPub::ImageSerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::FlagSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::FlagSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor, :content | ||||
|   attribute :virtual_object, key: :object | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::FollowSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::FollowSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|   attribute :virtual_object, key: :object | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::ImageSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::ImageSerializer < ActivityPub::Serializer | ||||
|   include RoutingHelper | ||||
|  | ||||
|   context_extensions :focal_point | ||||
|  | ||||
|   attributes :type, :media_type, :url | ||||
|   attribute :focal_point, if: :focal_point? | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::LikeSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::LikeSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|   attribute :virtual_object, key: :object | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::NoteSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::NoteSerializer < ActivityPub::Serializer | ||||
|   context_extensions :atom_uri, :conversation, :sensitive, | ||||
|                      :hashtag, :emoji, :focal_point | ||||
|  | ||||
|   attributes :id, :type, :summary, | ||||
|              :in_reply_to, :published, :url, | ||||
|              :attributed_to, :to, :cc, :sensitive, | ||||
| @@ -147,7 +150,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer | ||||
|     object.poll&.expired? | ||||
|   end | ||||
|  | ||||
|   class MediaAttachmentSerializer < ActiveModel::Serializer | ||||
|   class MediaAttachmentSerializer < ActivityPub::Serializer | ||||
|     include RoutingHelper | ||||
|  | ||||
|     attributes :type, :media_type, :url, :name | ||||
| @@ -178,7 +181,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   class MentionSerializer < ActiveModel::Serializer | ||||
|   class MentionSerializer < ActivityPub::Serializer | ||||
|     attributes :type, :href, :name | ||||
|  | ||||
|     def type | ||||
| @@ -194,7 +197,7 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   class TagSerializer < ActiveModel::Serializer | ||||
|   class TagSerializer < ActivityPub::Serializer | ||||
|     include RoutingHelper | ||||
|  | ||||
|     attributes :type, :href, :name | ||||
| @@ -215,8 +218,8 @@ class ActivityPub::NoteSerializer < ActiveModel::Serializer | ||||
|   class CustomEmojiSerializer < ActivityPub::EmojiSerializer | ||||
|   end | ||||
|  | ||||
|   class OptionSerializer < ActiveModel::Serializer | ||||
|     class RepliesSerializer < ActiveModel::Serializer | ||||
|   class OptionSerializer < ActivityPub::Serializer | ||||
|     class RepliesSerializer < ActivityPub::Serializer | ||||
|       attributes :type, :total_items | ||||
|  | ||||
|       def type | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::PublicKeySerializer < ActiveModel::Serializer | ||||
| class ActivityPub::PublicKeySerializer < ActivityPub::Serializer | ||||
|   context :security | ||||
|  | ||||
|   attributes :id, :owner, :public_key_pem | ||||
|  | ||||
|   def id | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::RejectFollowSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::RejectFollowSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::FollowSerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::RemoveSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::RemoveSerializer < ActivityPub::Serializer | ||||
|   include RoutingHelper | ||||
|  | ||||
|   attributes :type, :actor, :target | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::UndoAnnounceSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::UndoAnnounceSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor, :to | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::ActivitySerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::UndoBlockSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::UndoBlockSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::BlockSerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::UndoFollowSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::UndoFollowSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::FollowSerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::UndoLikeSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::UndoLikeSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::LikeSerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::UpdatePollSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::UpdatePollSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor, :to | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::NoteSerializer | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::UpdateSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::UpdateSerializer < ActivityPub::Serializer | ||||
|   attributes :id, :type, :actor, :to | ||||
|  | ||||
|   has_one :object, serializer: ActivityPub::ActorSerializer | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| # frozen_string_literal: true | ||||
|  | ||||
| class ActivityPub::VoteSerializer < ActiveModel::Serializer | ||||
|   class NoteSerializer < ActiveModel::Serializer | ||||
| class ActivityPub::VoteSerializer < ActivityPub::Serializer | ||||
|   class NoteSerializer < ActivityPub::Serializer | ||||
|     attributes :id, :type, :name, :attributed_to, | ||||
|                :in_reply_to, :to | ||||
|  | ||||
|   | ||||
| @@ -3,3 +3,22 @@ ActiveModelSerializers.config.tap do |config| | ||||
| end | ||||
|  | ||||
| ActiveSupport::Notifications.unsubscribe(ActiveModelSerializers::Logging::RENDER_EVENT) | ||||
|  | ||||
| class ActiveModel::Serializer::Reflection | ||||
|   # We monkey-patch this method so that when we include associations in a serializer, | ||||
|   # the nested serializers can send information about used contexts upwards back to | ||||
|   # the root. We do this via instance_options because the nesting can be dynamic. | ||||
|   def build_association(parent_serializer, parent_serializer_options, include_slice = {}) | ||||
|     serializer = options[:serializer] | ||||
|  | ||||
|     parent_serializer_options.merge!(named_contexts: serializer._named_contexts, context_extensions: serializer._context_extensions) if serializer.respond_to?(:_named_contexts) | ||||
|  | ||||
|     association_options = { | ||||
|       parent_serializer: parent_serializer, | ||||
|       parent_serializer_options: parent_serializer_options, | ||||
|       include_slice: include_slice, | ||||
|     } | ||||
|  | ||||
|     ActiveModel::Serializer::Association.new(self, association_options) | ||||
|   end | ||||
| end | ||||
|   | ||||
							
								
								
									
										88
									
								
								spec/lib/activitypub/adapter_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								spec/lib/activitypub/adapter_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| require 'rails_helper' | ||||
|  | ||||
| RSpec.describe ActivityPub::Adapter do | ||||
|   class TestObject < ActiveModelSerializers::Model | ||||
|     attributes :foo | ||||
|   end | ||||
|  | ||||
|   class TestWithBasicContextSerializer < ActivityPub::Serializer | ||||
|     attributes :foo | ||||
|   end | ||||
|  | ||||
|   class TestWithNamedContextSerializer < ActivityPub::Serializer | ||||
|     context :security | ||||
|     attributes :foo | ||||
|   end | ||||
|  | ||||
|   class TestWithNestedNamedContextSerializer < ActivityPub::Serializer | ||||
|     attributes :foo | ||||
|  | ||||
|     has_one :virtual_object, key: :baz, serializer: TestWithNamedContextSerializer | ||||
|  | ||||
|     def virtual_object | ||||
|       object | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   class TestWithContextExtensionSerializer < ActivityPub::Serializer | ||||
|     context_extensions :sensitive | ||||
|     attributes :foo | ||||
|   end | ||||
|  | ||||
|   class TestWithNestedContextExtensionSerializer < ActivityPub::Serializer | ||||
|     context_extensions :manually_approves_followers | ||||
|     attributes :foo | ||||
|  | ||||
|     has_one :virtual_object, key: :baz, serializer: TestWithContextExtensionSerializer | ||||
|  | ||||
|     def virtual_object | ||||
|       object | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   describe '#serializable_hash' do | ||||
|     let(:serializer_class) {} | ||||
|  | ||||
|     subject { ActiveModelSerializers::SerializableResource.new(TestObject.new(foo: 'bar'), serializer: serializer_class, adapter: described_class).as_json } | ||||
|  | ||||
|     context 'when serializer defines no context' do | ||||
|       let(:serializer_class) { TestWithBasicContextSerializer } | ||||
|  | ||||
|       it 'renders a basic @context' do | ||||
|         expect(subject).to include({ '@context' => 'https://www.w3.org/ns/activitystreams' }) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     context 'when serializer defines a named context' do | ||||
|       let(:serializer_class) { TestWithNamedContextSerializer } | ||||
|  | ||||
|       it 'renders a @context with both items' do | ||||
|         expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     context 'when serializer has children that define a named context' do | ||||
|       let(:serializer_class) { TestWithNestedNamedContextSerializer } | ||||
|  | ||||
|       it 'renders a @context with both items' do | ||||
|         expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1'] }) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     context 'when serializer defines context extensions' do | ||||
|       let(:serializer_class) { TestWithContextExtensionSerializer } | ||||
|  | ||||
|       it 'renders a @context with the extension' do | ||||
|         expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', { 'sensitive' => 'as:sensitive' }] }) | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     context 'when serializer has children that define context extensions' do | ||||
|       let(:serializer_class) { TestWithNestedContextExtensionSerializer } | ||||
|  | ||||
|       it 'renders a @context with both extensions' do | ||||
|         expect(subject).to include({ '@context' => ['https://www.w3.org/ns/activitystreams', { 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'sensitive' => 'as:sensitive' }] }) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| end | ||||
		Reference in New Issue
	
	Block a user