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.

174 lines
5.9 KiB

  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 '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 '!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 "!json.nil? && equals_or_includes?(json['@context'], 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 'else' 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/"}'
  50. stub_request(:get, 'https://alice.test/').to_return body: '{"id": "https://alice.test/"}'
  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/"}'
  55. stub_request(:get, 'https://marvin.test/').to_return body: '{"id": "https://alice.test/"}'
  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/"}'
  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: '{}'
  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: '{}'
  73. expect(fetch_resource_without_id_validation('https://host.test/')).to eq({})
  74. end
  75. end
  76. context '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 activistreams 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. deemed_compatible = 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. deemed_compatible = 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