translate_status_service_spec.rb 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. RSpec.describe TranslateStatusService, type: :service do
  4. subject(:service) { described_class.new }
  5. let(:status) { Fabricate(:status, text: text, spoiler_text: spoiler_text, language: 'en', preloadable_poll: poll, media_attachments: media_attachments) }
  6. let(:text) { 'Hello' }
  7. let(:spoiler_text) { '' }
  8. let(:poll) { nil }
  9. let(:media_attachments) { [] }
  10. before do
  11. Fabricate(:custom_emoji, shortcode: 'highfive')
  12. end
  13. describe '#call' do
  14. before do
  15. translation_service = TranslationService.new
  16. allow(translation_service).to receive(:languages).and_return({ 'en' => ['es'] })
  17. allow(translation_service).to receive(:translate) do |texts|
  18. texts.map do |text|
  19. TranslationService::Translation.new(
  20. text: text.gsub('Hello', 'Hola').gsub('higfive', 'cincoaltos'),
  21. detected_source_language: 'en',
  22. provider: 'Dummy'
  23. )
  24. end
  25. end
  26. allow(TranslationService).to receive_messages(configured?: true, configured: translation_service)
  27. end
  28. it 'returns translated status content' do
  29. expect(service.call(status, 'es').content).to eq '<p>Hola</p>'
  30. end
  31. it 'returns source language' do
  32. expect(service.call(status, 'es').detected_source_language).to eq 'en'
  33. end
  34. it 'returns translation provider' do
  35. expect(service.call(status, 'es').provider).to eq 'Dummy'
  36. end
  37. it 'returns original status' do
  38. expect(service.call(status, 'es').status).to eq status
  39. end
  40. describe 'status has content with custom emoji' do
  41. let(:text) { 'Hello & :highfive:' }
  42. it 'does not translate shortcode' do
  43. expect(service.call(status, 'es').content).to eq '<p>Hola &amp; :highfive:</p>'
  44. end
  45. end
  46. describe 'status has no spoiler_text' do
  47. it 'returns an empty string' do
  48. expect(service.call(status, 'es').spoiler_text).to eq ''
  49. end
  50. end
  51. describe 'status has spoiler_text' do
  52. let(:spoiler_text) { 'Hello & Hello!' }
  53. it 'translates the spoiler text' do
  54. expect(service.call(status, 'es').spoiler_text).to eq 'Hola & Hola!'
  55. end
  56. end
  57. describe 'status has spoiler_text with custom emoji' do
  58. let(:spoiler_text) { 'Hello :highfive:' }
  59. it 'does not translate shortcode' do
  60. expect(service.call(status, 'es').spoiler_text).to eq 'Hola :highfive:'
  61. end
  62. end
  63. describe 'status has spoiler_text with unmatched custom emoji' do
  64. let(:spoiler_text) { 'Hello :Hello:' }
  65. it 'translates the invalid shortcode' do
  66. expect(service.call(status, 'es').spoiler_text).to eq 'Hola :Hola:'
  67. end
  68. end
  69. describe 'status has poll' do
  70. let(:poll) { Fabricate(:poll, options: ['Hello 1', 'Hello 2']) }
  71. it 'translates the poll option title' do
  72. status_translation = service.call(status, 'es')
  73. expect(status_translation.poll_options.size).to eq 2
  74. expect(status_translation.poll_options.first.title).to eq 'Hola 1'
  75. end
  76. end
  77. describe 'status has media attachment' do
  78. let(:media_attachments) { [Fabricate(:media_attachment, description: 'Hello & :highfive:')] }
  79. it 'translates the media attachment description' do
  80. status_translation = service.call(status, 'es')
  81. media_attachment = status_translation.media_attachments.first
  82. expect(media_attachment.id).to eq media_attachments.first.id
  83. expect(media_attachment.description).to eq 'Hola & :highfive:'
  84. end
  85. end
  86. end
  87. describe '#source_texts' do
  88. before do
  89. service.instance_variable_set(:@status, status)
  90. end
  91. describe 'status only has content' do
  92. it 'returns formatted content' do
  93. expect(service.send(:source_texts)).to eq({ content: '<p>Hello</p>' })
  94. end
  95. end
  96. describe 'status content contains custom emoji' do
  97. let(:status) { Fabricate(:status, text: 'Hello :highfive:') }
  98. it 'returns formatted content' do
  99. source_texts = service.send(:source_texts)
  100. expect(source_texts[:content]).to eq '<p>Hello <span translate="no">:highfive:</span></p>'
  101. end
  102. end
  103. describe 'status content contains tags' do
  104. let(:status) { Fabricate(:status, text: 'Hello #hola') }
  105. it 'returns formatted content' do
  106. source_texts = service.send(:source_texts)
  107. expect(source_texts[:content]).to include '<p>Hello <a'
  108. expect(source_texts[:content]).to include '/tags/hola'
  109. end
  110. end
  111. describe 'status has spoiler text' do
  112. let(:status) { Fabricate(:status, spoiler_text: 'Hello :highfive:') }
  113. it 'returns formatted spoiler text' do
  114. source_texts = service.send(:source_texts)
  115. expect(source_texts[:spoiler_text]).to eq 'Hello <span translate="no">:highfive:</span>'
  116. end
  117. end
  118. describe 'status has poll' do
  119. let(:poll) { Fabricate(:poll, options: %w(Blue Green)) }
  120. context 'with source texts from the service' do
  121. let!(:source_texts) { service.send(:source_texts) }
  122. it 'returns formatted poll options' do
  123. expect(source_texts.size).to eq 3
  124. expect(source_texts.values).to eq %w(<p>Hello</p> Blue Green)
  125. end
  126. it 'has a first key with content' do
  127. expect(source_texts.keys.first).to eq :content
  128. end
  129. it 'has the first option in the second key with correct options' do
  130. option1 = source_texts.keys.second
  131. expect(option1).to be_a Poll::Option
  132. expect(option1.id).to eq '0'
  133. expect(option1.title).to eq 'Blue'
  134. end
  135. it 'has the second option in the third key with correct options' do
  136. option2 = source_texts.keys.third
  137. expect(option2).to be_a Poll::Option
  138. expect(option2.id).to eq '1'
  139. expect(option2.title).to eq 'Green'
  140. end
  141. end
  142. end
  143. describe 'status has poll with custom emoji' do
  144. let(:poll) { Fabricate(:poll, options: ['Blue', 'Green :highfive:']) }
  145. it 'returns formatted poll options' do
  146. html = service.send(:source_texts).values.last
  147. expect(html).to eq 'Green <span translate="no">:highfive:</span>'
  148. end
  149. end
  150. describe 'status has media attachments' do
  151. let(:text) { '' }
  152. let(:media_attachments) { [Fabricate(:media_attachment, description: 'Hello :highfive:')] }
  153. it 'returns media attachments without custom emoji rendering' do
  154. source_texts = service.send(:source_texts)
  155. expect(source_texts.size).to eq 1
  156. key, text = source_texts.first
  157. expect(key).to eq media_attachments.first
  158. expect(text).to eq 'Hello :highfive:'
  159. end
  160. end
  161. end
  162. describe '#wrap_emoji_shortcodes' do
  163. before do
  164. service.instance_variable_set(:@status, status)
  165. end
  166. describe 'string contains custom emoji' do
  167. let(:text) { ':highfive:' }
  168. it 'renders the emoji' do
  169. html = service.send(:wrap_emoji_shortcodes, 'Hello :highfive:'.html_safe)
  170. expect(html).to eq 'Hello <span translate="no">:highfive:</span>'
  171. end
  172. end
  173. end
  174. describe '#unwrap_emoji_shortcodes' do
  175. describe 'string contains custom emoji' do
  176. it 'inserts the shortcode' do
  177. fragment = service.send(:unwrap_emoji_shortcodes, '<p>Hello <span translate="no">:highfive:</span>!</p>')
  178. expect(fragment.to_html).to eq '<p>Hello :highfive:!</p>'
  179. end
  180. it 'preserves other attributes than translate=no' do
  181. fragment = service.send(:unwrap_emoji_shortcodes, '<p>Hello <span translate="no" class="foo">:highfive:</span>!</p>')
  182. expect(fragment.to_html).to eq '<p>Hello <span class="foo">:highfive:</span>!</p>'
  183. end
  184. end
  185. end
  186. end