translate_status_service_spec.rb 7.7 KB

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