software_update_check_service_spec.rb 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. RSpec.describe SoftwareUpdateCheckService do
  4. subject { described_class.new }
  5. shared_examples 'when the feature is enabled' do
  6. let(:full_update_check_url) { "#{update_check_url}?version=#{Mastodon::Version.to_s.split('+')[0]}" }
  7. let(:devops_role) { Fabricate(:user_role, name: 'DevOps', permissions: UserRole::FLAGS[:view_devops]) }
  8. let(:owner_user) { Fabricate(:user, role: UserRole.find_by(name: 'Owner')) }
  9. let(:old_devops_user) { Fabricate(:user) }
  10. let(:none_user) { Fabricate(:user, role: devops_role) }
  11. let(:patch_user) { Fabricate(:user, role: devops_role) }
  12. let(:critical_user) { Fabricate(:user, role: devops_role) }
  13. around do |example|
  14. queue_adapter = ActiveJob::Base.queue_adapter
  15. ActiveJob::Base.queue_adapter = :test
  16. example.run
  17. ActiveJob::Base.queue_adapter = queue_adapter
  18. end
  19. before do
  20. Fabricate(:software_update, version: '3.5.0', type: 'major', urgent: false)
  21. Fabricate(:software_update, version: '42.13.12', type: 'major', urgent: false)
  22. Fabricate(:software_update, version: 'Malformed', type: 'major', urgent: false)
  23. owner_user.settings.update('notification_emails.software_updates': 'all')
  24. owner_user.save!
  25. old_devops_user.settings.update('notification_emails.software_updates': 'all')
  26. old_devops_user.save!
  27. none_user.settings.update('notification_emails.software_updates': 'none')
  28. none_user.save!
  29. patch_user.settings.update('notification_emails.software_updates': 'patch')
  30. patch_user.save!
  31. critical_user.settings.update('notification_emails.software_updates': 'critical')
  32. critical_user.save!
  33. end
  34. context 'when the update server errors out' do
  35. before do
  36. stub_request(:get, full_update_check_url).to_return(status: 404)
  37. end
  38. it 'deletes outdated update records but keeps valid update records' do
  39. expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12', 'Malformed']).to(['42.13.12'])
  40. end
  41. end
  42. context 'when the server returns new versions' do
  43. let(:server_json) do
  44. {
  45. updatesAvailable: [
  46. {
  47. version: '4.2.1',
  48. urgent: false,
  49. type: 'patch',
  50. releaseNotes: 'https://github.com/mastodon/mastodon/releases/v4.2.1',
  51. },
  52. {
  53. version: '4.3.0',
  54. urgent: false,
  55. type: 'minor',
  56. releaseNotes: 'https://github.com/mastodon/mastodon/releases/v4.3.0',
  57. },
  58. {
  59. version: '5.0.0',
  60. urgent: false,
  61. type: 'minor',
  62. releaseNotes: 'https://github.com/mastodon/mastodon/releases/v5.0.0',
  63. },
  64. ],
  65. }
  66. end
  67. before do
  68. stub_request(:get, full_update_check_url).to_return(body: Oj.dump(server_json))
  69. end
  70. it 'updates the list of known updates' do
  71. expect { subject.call }.to change { SoftwareUpdate.pluck(:version).sort }.from(['3.5.0', '42.13.12', 'Malformed']).to(['4.2.1', '4.3.0', '5.0.0'])
  72. end
  73. context 'when no update is urgent' do
  74. it 'sends e-mail notifications according to settings', :aggregate_failures do
  75. expect { subject.call }.to have_enqueued_mail(AdminMailer, :new_software_updates)
  76. .with(hash_including(params: { recipient: owner_user.account })).once
  77. .and(have_enqueued_mail(AdminMailer, :new_software_updates).with(hash_including(params: { recipient: patch_user.account })).once)
  78. .and(have_enqueued_mail.at_most(2))
  79. end
  80. end
  81. context 'when an update is urgent' do
  82. let(:server_json) do
  83. {
  84. updatesAvailable: [
  85. {
  86. version: '5.0.0',
  87. urgent: true,
  88. type: 'minor',
  89. releaseNotes: 'https://github.com/mastodon/mastodon/releases/v5.0.0',
  90. },
  91. ],
  92. }
  93. end
  94. it 'sends e-mail notifications according to settings', :aggregate_failures do
  95. expect { subject.call }.to have_enqueued_mail(AdminMailer, :new_critical_software_updates)
  96. .with(hash_including(params: { recipient: owner_user.account })).once
  97. .and(have_enqueued_mail(AdminMailer, :new_critical_software_updates).with(hash_including(params: { recipient: patch_user.account })).once)
  98. .and(have_enqueued_mail(AdminMailer, :new_critical_software_updates).with(hash_including(params: { recipient: critical_user.account })).once)
  99. .and(have_enqueued_mail.at_most(3))
  100. end
  101. end
  102. end
  103. end
  104. context 'when update checking is disabled' do
  105. around do |example|
  106. original = Rails.configuration.x.mastodon.software_update_url
  107. Rails.configuration.x.mastodon.software_update_url = ''
  108. example.run
  109. Rails.configuration.x.mastodon.software_update_url = original
  110. end
  111. before do
  112. Fabricate(:software_update, version: '3.5.0', type: 'major', urgent: false)
  113. end
  114. it 'deletes outdated update records' do
  115. expect { subject.call }.to change(SoftwareUpdate, :count).from(1).to(0)
  116. end
  117. end
  118. context 'when using the default update checking API' do
  119. let(:update_check_url) { 'https://api.joinmastodon.org/update-check' }
  120. it_behaves_like 'when the feature is enabled'
  121. end
  122. context 'when using a custom update check URL' do
  123. let(:update_check_url) { 'https://api.example.com/update_check' }
  124. around do |example|
  125. original = Rails.configuration.x.mastodon.software_update_url
  126. Rails.configuration.x.mastodon.software_update_url = 'https://api.example.com/update_check'
  127. example.run
  128. Rails.configuration.x.mastodon.software_update_url = original
  129. end
  130. it_behaves_like 'when the feature is enabled'
  131. end
  132. end