json_ld_helper_spec.rb 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. describe JsonLdHelper do
  4. describe '#equals_or_includes?' do
  5. it 'returns true when value equals' do
  6. expect(helper.equals_or_includes?('foo', 'foo')).to be true
  7. end
  8. it 'returns false when value does not equal' do
  9. expect(helper.equals_or_includes?('foo', 'bar')).to be false
  10. end
  11. it 'returns true when value is included' do
  12. expect(helper.equals_or_includes?(%w(foo baz), 'foo')).to be true
  13. end
  14. it 'returns false when value is not included' do
  15. expect(helper.equals_or_includes?(%w(foo baz), 'bar')).to be false
  16. end
  17. end
  18. describe '#first_of_value' do
  19. context 'when value.is_a?(Array)' do
  20. it 'returns value.first' do
  21. value = ['a']
  22. expect(helper.first_of_value(value)).to be 'a'
  23. end
  24. end
  25. context 'with !value.is_a?(Array)' do
  26. it 'returns value' do
  27. value = 'a'
  28. expect(helper.first_of_value(value)).to be 'a'
  29. end
  30. end
  31. end
  32. describe '#supported_context?' do
  33. context 'when json is present and in an activitypub tagmanager context' do
  34. it 'returns true' do
  35. json = { '@context' => ActivityPub::TagManager::CONTEXT }.as_json
  36. expect(helper.supported_context?(json)).to be true
  37. end
  38. end
  39. context 'when not in activitypub tagmanager context' do
  40. it 'returns false' do
  41. json = nil
  42. expect(helper.supported_context?(json)).to be false
  43. end
  44. end
  45. end
  46. describe '#fetch_resource' do
  47. context 'when the second argument is false' do
  48. it 'returns resource even if the retrieved ID and the given URI does not match' do
  49. stub_request(:get, 'https://bob.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
  50. stub_request(:get, 'https://alice.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
  51. expect(fetch_resource('https://bob.test/', false)).to eq({ 'id' => 'https://alice.test/' })
  52. end
  53. it 'returns nil if the object identified by the given URI and the object identified by the retrieved ID does not match' do
  54. stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://marvin.test/"}', headers: { 'Content-Type': 'application/activity+json' })
  55. stub_request(:get, 'https://marvin.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
  56. expect(fetch_resource('https://mallory.test/', false)).to be_nil
  57. end
  58. end
  59. context 'when the second argument is true' do
  60. it 'returns nil if the retrieved ID and the given URI does not match' do
  61. stub_request(:get, 'https://mallory.test/').to_return(body: '{"id": "https://alice.test/"}', headers: { 'Content-Type': 'application/activity+json' })
  62. expect(fetch_resource('https://mallory.test/', true)).to be_nil
  63. end
  64. end
  65. end
  66. describe '#fetch_resource_without_id_validation' do
  67. it 'returns nil if the status code is not 200' do
  68. stub_request(:get, 'https://host.test/').to_return(status: 400, body: '{}', headers: { 'Content-Type': 'application/activity+json' })
  69. expect(fetch_resource_without_id_validation('https://host.test/')).to be_nil
  70. end
  71. it 'returns hash' do
  72. stub_request(:get, 'https://host.test/').to_return(status: 200, body: '{}', headers: { 'Content-Type': 'application/activity+json' })
  73. expect(fetch_resource_without_id_validation('https://host.test/')).to eq({})
  74. end
  75. end
  76. context 'with compaction and forwarding' do
  77. let(:json) do
  78. {
  79. '@context' => [
  80. 'https://www.w3.org/ns/activitystreams',
  81. 'https://w3id.org/security/v1',
  82. {
  83. 'obsolete' => 'http://ostatus.org#',
  84. 'convo' => 'obsolete:conversation',
  85. 'new' => 'https://obscure-unreleased-test.joinmastodon.org/#',
  86. },
  87. ],
  88. 'type' => 'Create',
  89. 'to' => ['https://www.w3.org/ns/activitystreams#Public'],
  90. 'object' => {
  91. 'id' => 'https://example.com/status',
  92. 'type' => 'Note',
  93. 'inReplyTo' => nil,
  94. 'convo' => 'https://example.com/conversation',
  95. 'tag' => [
  96. {
  97. 'type' => 'Mention',
  98. 'href' => ['foo'],
  99. },
  100. ],
  101. },
  102. 'signature' => {
  103. 'type' => 'RsaSignature2017',
  104. 'created' => '2022-02-02T12:00:00Z',
  105. 'creator' => 'https://example.com/actor#main-key',
  106. 'signatureValue' => 'some-sig',
  107. },
  108. }
  109. end
  110. describe '#compact' do
  111. it 'properly compacts JSON-LD with alternative context definitions' do
  112. expect(compact(json).dig('object', 'conversation')).to eq 'https://example.com/conversation'
  113. end
  114. it 'compacts single-item arrays' do
  115. expect(compact(json).dig('object', 'tag', 'href')).to eq 'foo'
  116. end
  117. it 'compacts the activitystreams Public collection' do
  118. expect(compact(json)['to']).to eq 'as:Public'
  119. end
  120. it 'properly copies signature' do
  121. expect(compact(json)['signature']).to eq json['signature']
  122. end
  123. end
  124. describe 'patch_for_forwarding!' do
  125. it 'properly patches incompatibilities' do
  126. json['object'].delete('convo')
  127. compacted = compact(json)
  128. patch_for_forwarding!(json, compacted)
  129. expect(compacted['to']).to eq ['https://www.w3.org/ns/activitystreams#Public']
  130. expect(compacted.dig('object', 'tag', 0, 'href')).to eq ['foo']
  131. expect(safe_for_forwarding?(json, compacted)).to be true
  132. end
  133. end
  134. describe 'safe_for_forwarding?' do
  135. it 'deems a safe compacting as such' do
  136. json['object'].delete('convo')
  137. compacted = compact(json)
  138. patch_for_forwarding!(json, compacted)
  139. expect(compacted['to']).to eq ['https://www.w3.org/ns/activitystreams#Public']
  140. expect(safe_for_forwarding?(json, compacted)).to be true
  141. end
  142. it 'deems an unsafe compacting as such' do
  143. compacted = compact(json)
  144. patch_for_forwarding!(json, compacted)
  145. expect(compacted['to']).to eq ['https://www.w3.org/ns/activitystreams#Public']
  146. expect(safe_for_forwarding?(json, compacted)).to be false
  147. end
  148. end
  149. end
  150. end