From 614a6f3939f1cd69f40779680b5f7324041d94de Mon Sep 17 00:00:00 2001 From: aidewoode Date: Wed, 25 Oct 2023 21:57:17 +0800 Subject: [PATCH] Remove web session authentication in API and share code relative to the stream controllers in concerns. --- app/controllers/albums_controller.rb | 2 +- app/controllers/api/v1/api_controller.rb | 8 +-- app/controllers/api/v1/stream_controller.rb | 40 +------------- .../api/v1/transcoded_stream_controller.rb | 45 +--------------- app/controllers/application_controller.rb | 20 +++++++ .../{playable.rb => playable_concern.rb} | 2 +- app/controllers/concerns/stream_concern.rb | 24 +++++++++ .../concerns/transcoded_stream_concern.rb | 53 +++++++++++++++++++ app/controllers/playlists/songs_controller.rb | 2 +- app/controllers/stream_controller.rb | 5 ++ .../transcoded_stream_controller.rb | 5 ++ app/helpers/song_helper.rb | 7 ++- app/views/api/v1/songs/_song.json.jbuilder | 2 +- config/routes.rb | 3 ++ .../controllers/api/v1/api_controller_test.rb | 6 +-- .../api/v1/stream_controller_test.rb | 38 ++++++------- .../v1/transcoded_stream_controller_test.rb | 23 ++++---- test/controllers/concerns/playable_test.rb | 4 +- test/controllers/stream_controller_test.rb | 17 ++++++ .../transcoded_stream_controller_test.rb | 22 ++++++++ test/system/album_test.rb | 3 +- test/system/songs_test.rb | 3 +- 22 files changed, 200 insertions(+), 134 deletions(-) rename app/controllers/concerns/{playable.rb => playable_concern.rb} (96%) create mode 100644 app/controllers/concerns/stream_concern.rb create mode 100644 app/controllers/concerns/transcoded_stream_concern.rb create mode 100644 app/controllers/stream_controller.rb create mode 100644 app/controllers/transcoded_stream_controller.rb create mode 100644 test/controllers/stream_controller_test.rb create mode 100644 test/controllers/transcoded_stream_controller_test.rb diff --git a/app/controllers/albums_controller.rb b/app/controllers/albums_controller.rb index bdd26bd3..93e73a95 100644 --- a/app/controllers/albums_controller.rb +++ b/app/controllers/albums_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class AlbumsController < ApplicationController - include Playable + include PlayableConcern before_action :require_admin, only: [:update] before_action :find_album, except: [:index] diff --git a/app/controllers/api/v1/api_controller.rb b/app/controllers/api/v1/api_controller.rb index b71d08e0..bd0f9967 100644 --- a/app/controllers/api/v1/api_controller.rb +++ b/app/controllers/api/v1/api_controller.rb @@ -7,14 +7,8 @@ class ApiController < ApplicationController private - # If user already has logged in then authenticate with current session, - # otherwise authenticate with api token. def find_current_user - Current.user = UserSession.find&.user - - return if logged_in? - - authenticate_with_http_token do |token, options| + authenticate_with_http_token do |token, _| user = User.find_by(api_token: token) return unless user.present? diff --git a/app/controllers/api/v1/stream_controller.rb b/app/controllers/api/v1/stream_controller.rb index e4dab5dd..7b3e222c 100644 --- a/app/controllers/api/v1/stream_controller.rb +++ b/app/controllers/api/v1/stream_controller.rb @@ -3,45 +3,7 @@ module Api module V1 class StreamController < ApiController - before_action :find_stream - - def new - send_local_file @stream.file_path - end - - private - - def set_nginx_header - # Let nginx can get value of media_path dynamically in the nginx config, - # when use X-Accel-Redirect header to send file. - response.headers["X-Media-Path"] = Setting.media_path - response.headers["X-Accel-Redirect"] = File.join("/private_media", @stream.file_path.sub(File.expand_path(Setting.media_path), "")) - end - - def find_stream - song = Song.find(params[:song_id]) - @stream = Stream.new(song) - end - - def send_local_file(file_path) - if BlackCandy::Config.nginx_sendfile? - set_nginx_header - - send_file file_path - return - end - - # Use Rack::File to support HTTP range without nginx. see https://github.com/rails/rails/issues/32193 - Rack::File.new(nil).serving(request, file_path).tap do |(status, headers, body)| - self.status = status - self.response_body = body - - headers.each { |name, value| response.headers[name] = value } - - response.headers["Content-Type"] = Mime[@stream.format] - response.headers["Content-Disposition"] = "attachment" - end - end + include StreamConcern end end end diff --git a/app/controllers/api/v1/transcoded_stream_controller.rb b/app/controllers/api/v1/transcoded_stream_controller.rb index f54bcab5..d35259ed 100644 --- a/app/controllers/api/v1/transcoded_stream_controller.rb +++ b/app/controllers/api/v1/transcoded_stream_controller.rb @@ -2,49 +2,8 @@ module Api module V1 - class TranscodedStreamController < StreamController - before_action :find_cache - - # Similar to send_file in rails, but let response_body to be a stream object. - # The instance of Stream can respond to each() method. So the download can be streamed, - # instead of read whole data into memory. - def new - # Because the module ActionController::Live contains methods that can block send file. - # So can't simply include ActionController::Live in class, otherwise include this module only on this method. - self.class.send(:include, ActionController::Live) - - response.headers["Content-Type"] = Mime[Stream::TRANSCODE_FORMAT] - - send_stream(filename: "#{@stream.name}.mp3") do |stream_response| - File.open(@stream.transcode_cache_file_path, "w") do |file| - @stream.each do |data| - stream_response.write data - file.write data - end - end - end - end - - private - - def set_nginx_header - response.headers["X-Accel-Redirect"] = File.join("/private_cache_media", @stream.transcode_cache_file_path.sub(Stream::TRANSCODE_CACHE_DIRECTORY.to_s, "")) - end - - def find_cache - return unless valid_cache? - send_local_file @stream.transcode_cache_file_path - end - - def valid_cache? - return unless File.exist?(@stream.transcode_cache_file_path) - - # Compare duration of cache file and original file to check integrity of cache file. - # Because the different format of the file, the duration will have a little difference, - # so the duration difference in two seconds are considered no problem. - cache_file_tag = WahWah.open(@stream.transcode_cache_file_path) - (@stream.duration - cache_file_tag.duration).abs <= 2 - end + class TranscodedStreamController < ApiController + include TranscodedStreamConcern end end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7d6d03ab..99ddc8e4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -116,4 +116,24 @@ def turbo_android? def render_json_error(error, status) render json: {type: error.type, message: error.message}, status: status end + + def send_local_file(file_path, format, nginx_headers: {}) + if BlackCandy::Config.nginx_sendfile? + nginx_headers.each { |name, value| response.headers[name] = value } + send_file file_path + + return + end + + # Use Rack::File to support HTTP range without nginx. see https://github.com/rails/rails/issues/32193 + Rack::File.new(nil).serving(request, file_path).tap do |(status, headers, body)| + self.status = status + self.response_body = body + + headers.each { |name, value| response.headers[name] = value } + + response.headers["Content-Type"] = Mime[format] + response.headers["Content-Disposition"] = "attachment" + end + end end diff --git a/app/controllers/concerns/playable.rb b/app/controllers/concerns/playable_concern.rb similarity index 96% rename from app/controllers/concerns/playable.rb rename to app/controllers/concerns/playable_concern.rb index 6a80a25e..897cf8ef 100644 --- a/app/controllers/concerns/playable.rb +++ b/app/controllers/concerns/playable_concern.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module Playable +module PlayableConcern extend ActiveSupport::Concern included do diff --git a/app/controllers/concerns/stream_concern.rb b/app/controllers/concerns/stream_concern.rb new file mode 100644 index 00000000..a7b7b08b --- /dev/null +++ b/app/controllers/concerns/stream_concern.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module StreamConcern + extend ActiveSupport::Concern + + included do + before_action :find_stream + end + + def new + send_local_file @stream.file_path, @stream.format, nginx_headers: { + # Let nginx can get value of media_path dynamically in the nginx config + # when use X-Accel-Redirect header to send file. + "X-Media-Path" => Setting.media_path, + "X-Accel-Redirect" => File.join("/private_media", @stream.file_path.sub(File.expand_path(Setting.media_path), "")) + } + end + + private + + def find_stream + @stream = Stream.new(Song.find(params[:song_id])) + end +end diff --git a/app/controllers/concerns/transcoded_stream_concern.rb b/app/controllers/concerns/transcoded_stream_concern.rb new file mode 100644 index 00000000..e95a9b9a --- /dev/null +++ b/app/controllers/concerns/transcoded_stream_concern.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module TranscodedStreamConcern + extend ActiveSupport::Concern + + included do + before_action :find_stream + before_action :find_cache + end + + # Similar to send_file in rails, but let response_body to be a stream object. + # The instance of Stream can respond to each() method. So the download can be streamed, + # instead of read whole data into memory. + def new + # Because the module ActionController::Live contains methods that can block send file. + # So can't simply include ActionController::Live in class, otherwise include this module only on this method. + self.class.send(:include, ActionController::Live) + + response.headers["Content-Type"] = Mime[Stream::TRANSCODE_FORMAT] + + send_stream(filename: "#{@stream.name}.mp3") do |stream_response| + File.open(@stream.transcode_cache_file_path, "w") do |file| + @stream.each do |data| + stream_response.write data + file.write data + end + end + end + end + + private + + def find_stream + @stream = Stream.new(Song.find(params[:song_id])) + end + + def find_cache + return unless valid_cache? + send_local_file @stream.transcode_cache_file_path, @stream.format, nginx_headers: { + "X-Accel-Redirect" => File.join("/private_cache_media", @stream.transcode_cache_file_path.sub(Stream::TRANSCODE_CACHE_DIRECTORY.to_s, "")) + } + end + + def valid_cache? + return unless File.exist?(@stream.transcode_cache_file_path) + + # Compare duration of cache file and original file to check integrity of cache file. + # Because the different format of the file, the duration will have a little difference, + # so the duration difference in two seconds are considered no problem. + cache_file_tag = WahWah.open(@stream.transcode_cache_file_path) + (@stream.duration - cache_file_tag.duration).abs <= 2 + end +end diff --git a/app/controllers/playlists/songs_controller.rb b/app/controllers/playlists/songs_controller.rb index 47669dfe..00901c71 100644 --- a/app/controllers/playlists/songs_controller.rb +++ b/app/controllers/playlists/songs_controller.rb @@ -4,7 +4,7 @@ class Playlists::SongsController < ApplicationController before_action :find_playlist before_action :find_song, only: [:create, :destroy] - include Playable + include PlayableConcern def show @pagy, @songs = pagy(@playlist.songs.includes(:artist)) diff --git a/app/controllers/stream_controller.rb b/app/controllers/stream_controller.rb new file mode 100644 index 00000000..a33bc103 --- /dev/null +++ b/app/controllers/stream_controller.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class StreamController < ApplicationController + include StreamConcern +end diff --git a/app/controllers/transcoded_stream_controller.rb b/app/controllers/transcoded_stream_controller.rb new file mode 100644 index 00000000..88616225 --- /dev/null +++ b/app/controllers/transcoded_stream_controller.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class TranscodedStreamController < ApplicationController + include TranscodedStreamConcern +end diff --git a/app/helpers/song_helper.rb b/app/helpers/song_helper.rb index 57347e9f..775b3ac4 100644 --- a/app/helpers/song_helper.rb +++ b/app/helpers/song_helper.rb @@ -1,10 +1,13 @@ # frozen_string_literal: true module SongHelper - def song_json_builder(song) + def song_json_builder(song, for_api: false) + stream_url = for_api ? new_api_v1_stream_url(song_id: song.id) : new_stream_url(song_id: song.id) + transcoded_stream_url = for_api ? new_api_v1_transcoded_stream_url(song_id: song.id) : new_transcoded_stream_url(song_id: song.id) + Jbuilder.new do |json| json.call(song, :id, :name, :duration) - json.url need_transcode?(song) ? new_api_v1_transcoded_stream_url(song_id: song.id) : new_api_v1_stream_url(song_id: song.id) + json.url need_transcode?(song) ? transcoded_stream_url : stream_url json.album_name song.album.title json.artist_name song.artist.title json.is_favorited song.is_favorited.nil? ? Current.user.favorited?(song) : song.is_favorited diff --git a/app/views/api/v1/songs/_song.json.jbuilder b/app/views/api/v1/songs/_song.json.jbuilder index 103bbf2e..504ca77b 100644 --- a/app/views/api/v1/songs/_song.json.jbuilder +++ b/app/views/api/v1/songs/_song.json.jbuilder @@ -1 +1 @@ -json.merge! song_json_builder(song) +json.merge! song_json_builder(song, for_api: true) diff --git a/config/routes.rb b/config/routes.rb index 49f7a597..e280a176 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -60,6 +60,9 @@ end end + resources :stream, only: [:new] + resources :transcoded_stream, only: [:new] + get "/403", to: "errors#forbidden", as: :forbidden get "/404", to: "errors#not_found", as: :not_found get "/422", to: "errors#unprocessable_entity", as: :unprocessable_entity diff --git a/test/controllers/api/v1/api_controller_test.rb b/test/controllers/api/v1/api_controller_test.rb index 480c5ea5..a47019fb 100644 --- a/test/controllers/api/v1/api_controller_test.rb +++ b/test/controllers/api/v1/api_controller_test.rb @@ -8,11 +8,11 @@ class Api::V1::ApiControllerTest < ActionDispatch::IntegrationTest @song = songs(:mp3_sample) end - test "should authenticate when have user session" do + test "should not authenticate when have user session" do login(@user) get api_v1_song_url(@song), as: :json - assert_response :success + assert_response :unauthorized end test "should authenticate when have api token" do @@ -21,7 +21,7 @@ class Api::V1::ApiControllerTest < ActionDispatch::IntegrationTest assert_response :success end - test "should not authenticate when do not have user seesion or api token" do + test "should not authenticate when do not have api token" do get api_v1_song_url(@song), as: :json assert_response :unauthorized diff --git a/test/controllers/api/v1/stream_controller_test.rb b/test/controllers/api/v1/stream_controller_test.rb index 4c1e112d..aa698f73 100644 --- a/test/controllers/api/v1/stream_controller_test.rb +++ b/test/controllers/api/v1/stream_controller_test.rb @@ -4,18 +4,18 @@ class Api::V1::StreamControllerTest < ActionDispatch::IntegrationTest setup do - login + @user = users(:visitor1) Setting.update(media_path: Rails.root.join("test/fixtures/files")) end test "should get new stream" do - get new_api_v1_stream_url(song_id: songs(:mp3_sample).id) + get new_api_v1_stream_url(song_id: songs(:mp3_sample).id), headers: api_token_header(@user) assert_response :success end test "should set header for nginx send file" do with_env("NGINX_SENDFILE" => "true") do - get new_api_v1_stream_url(song_id: songs(:mp3_sample).id) + get new_api_v1_stream_url(song_id: songs(:mp3_sample).id), headers: api_token_header(@user) assert_equal Setting.media_path, @response.get_header("X-Media-Path") assert_equal "/private_media/artist1_album2.mp3", @response.get_header("X-Accel-Redirect") @@ -23,61 +23,61 @@ class Api::V1::StreamControllerTest < ActionDispatch::IntegrationTest end test "should respond file data" do - get new_api_v1_stream_url(song_id: songs(:mp3_sample).id) + get new_api_v1_stream_url(song_id: songs(:mp3_sample).id), headers: api_token_header(@user) assert_equal binary_data(file_fixture("artist1_album2.mp3")), response.body end test "should respond file data when set nginx send file header" do with_env("NGINX_SENDFILE" => "true") do - get new_api_v1_stream_url(song_id: songs(:mp3_sample).id) + get new_api_v1_stream_url(song_id: songs(:mp3_sample).id), headers: api_token_header(@user) assert_equal binary_data(file_fixture("artist1_album2.mp3")), response.body end end test "should set correct content type header" do - get new_api_v1_stream_url(song_id: songs(:mp3_sample).id) + get new_api_v1_stream_url(song_id: songs(:mp3_sample).id), headers: api_token_header(@user) assert_equal "audio/mpeg", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_equal "audio/flac", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:ogg_sample).id) + get new_api_v1_stream_url(song_id: songs(:ogg_sample).id), headers: api_token_header(@user) assert_equal "audio/ogg", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:wav_sample).id) + get new_api_v1_stream_url(song_id: songs(:wav_sample).id), headers: api_token_header(@user) assert_equal "audio/wav", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:opus_sample).id) + get new_api_v1_stream_url(song_id: songs(:opus_sample).id), headers: api_token_header(@user) assert_equal "audio/ogg", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:m4a_sample).id) + get new_api_v1_stream_url(song_id: songs(:m4a_sample).id), headers: api_token_header(@user) assert_equal "audio/aac", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:oga_sample).id) + get new_api_v1_stream_url(song_id: songs(:oga_sample).id), headers: api_token_header(@user) assert_equal "audio/ogg", @response.get_header("Content-Type") end test "should set correct content type header when not set nginx send file header" do Rails.configuration.action_dispatch.stub(:x_sendfile_header, "") do - get new_api_v1_stream_url(song_id: songs(:mp3_sample).id) + get new_api_v1_stream_url(song_id: songs(:mp3_sample).id), headers: api_token_header(@user) assert_equal "audio/mpeg", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_equal "audio/flac", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:ogg_sample).id) + get new_api_v1_stream_url(song_id: songs(:ogg_sample).id), headers: api_token_header(@user) assert_equal "audio/ogg", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:wav_sample).id) + get new_api_v1_stream_url(song_id: songs(:wav_sample).id), headers: api_token_header(@user) assert_equal "audio/wav", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:opus_sample).id) + get new_api_v1_stream_url(song_id: songs(:opus_sample).id), headers: api_token_header(@user) assert_equal "audio/ogg", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:m4a_sample).id) + get new_api_v1_stream_url(song_id: songs(:m4a_sample).id), headers: api_token_header(@user) assert_equal "audio/aac", @response.get_header("Content-Type") - get new_api_v1_stream_url(song_id: songs(:oga_sample).id) + get new_api_v1_stream_url(song_id: songs(:oga_sample).id), headers: api_token_header(@user) assert_equal "audio/ogg", @response.get_header("Content-Type") end end diff --git a/test/controllers/api/v1/transcoded_stream_controller_test.rb b/test/controllers/api/v1/transcoded_stream_controller_test.rb index 29f6ec8d..3eabd263 100644 --- a/test/controllers/api/v1/transcoded_stream_controller_test.rb +++ b/test/controllers/api/v1/transcoded_stream_controller_test.rb @@ -4,23 +4,22 @@ class Api::V1::TranscodedStreamControllerTest < ActionDispatch::IntegrationTest setup do + @user = users(:visitor1) Setting.update(media_path: Rails.root.join("test/fixtures/files")) cache_directory = "#{Stream::TRANSCODE_CACHE_DIRECTORY}/#{songs(:flac_sample).id}" if Dir.exist?(cache_directory) FileUtils.remove_dir(cache_directory) end - - login end test "should get new stream for transcode format" do - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_response :success end test "should get transcoded data" do - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) create_tmp_file(format: "mp3") do |tmp_file_path| File.write(tmp_file_path, response.body) @@ -33,26 +32,26 @@ class Api::V1::TranscodedStreamControllerTest < ActionDispatch::IntegrationTest stream = Stream.new(songs(:flac_sample)) assert_not File.exist? stream.transcode_cache_file_path - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_response :success assert File.exist? stream.transcode_cache_file_path end test "should send cached transcoded stream file when found cache" do - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_response :success - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_equal binary_data(Stream.new(songs(:flac_sample)).transcode_cache_file_path), response.body end test "should send cached transcoded stream file when found cache and send file with nginx" do - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_response :success with_env("NGINX_SENDFILE" => "true") do - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_equal "/private_cache_media/2/ZmxhY19zYW1wbGVfbWQ1X2hhc2g=_128.mp3", @response.get_header("X-Accel-Redirect") assert_equal "audio/mpeg", @response.get_header("Content-Type") end @@ -61,7 +60,7 @@ class Api::V1::TranscodedStreamControllerTest < ActionDispatch::IntegrationTest test "should regenerate new cache when cache is invalid" do stream = Stream.new(songs(:flac_sample)) - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_response :success original_cache_file_mtime = File.mtime(stream.transcode_cache_file_path) @@ -70,14 +69,14 @@ class Api::V1::TranscodedStreamControllerTest < ActionDispatch::IntegrationTest # so that the cache will be treated as invalid songs(:flac_sample).update(duration: 12.0) - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_response :success assert_not_equal original_cache_file_mtime, File.mtime(stream.transcode_cache_file_path) end test "should set correct content type header" do - get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id) + get new_api_v1_transcoded_stream_url(song_id: songs(:flac_sample).id), headers: api_token_header(@user) assert_equal "audio/mpeg", @response.get_header("Content-Type") end end diff --git a/test/controllers/concerns/playable_test.rb b/test/controllers/concerns/playable_test.rb index 9b500653..238371b3 100644 --- a/test/controllers/concerns/playable_test.rb +++ b/test/controllers/concerns/playable_test.rb @@ -3,7 +3,7 @@ require "test_helper" class DummyPlayableController < ApplicationController - include Playable + include PlayableConcern private @@ -13,7 +13,7 @@ def find_all_song_ids end class NotImplementedDummyPlayableController < ApplicationController - include Playable + include PlayableConcern end class PlayableTest < ActionDispatch::IntegrationTest diff --git a/test/controllers/stream_controller_test.rb b/test/controllers/stream_controller_test.rb new file mode 100644 index 00000000..5b6440cc --- /dev/null +++ b/test/controllers/stream_controller_test.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require "test_helper" + +class StreamControllerTest < ActionDispatch::IntegrationTest + setup do + @user = users(:visitor1) + Setting.update(media_path: Rails.root.join("test/fixtures/files")) + + login(@user) + end + + test "should get new stream" do + get new_stream_url(song_id: songs(:mp3_sample).id) + assert_response :success + end +end diff --git a/test/controllers/transcoded_stream_controller_test.rb b/test/controllers/transcoded_stream_controller_test.rb new file mode 100644 index 00000000..df72b3f7 --- /dev/null +++ b/test/controllers/transcoded_stream_controller_test.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require "test_helper" + +class TranscodedStreamControllerTest < ActionDispatch::IntegrationTest + setup do + @user = users(:visitor1) + Setting.update(media_path: Rails.root.join("test/fixtures/files")) + + cache_directory = "#{Stream::TRANSCODE_CACHE_DIRECTORY}/#{songs(:flac_sample).id}" + if Dir.exist?(cache_directory) + FileUtils.remove_dir(cache_directory) + end + + login(@user) + end + + test "should get new stream for transcode format" do + get new_transcoded_stream_url(song_id: songs(:flac_sample).id) + assert_response :success + end +end diff --git a/test/system/album_test.rb b/test/system/album_test.rb index 735db984..7698a230 100644 --- a/test/system/album_test.rb +++ b/test/system/album_test.rb @@ -4,6 +4,7 @@ class AlbumSystemTest < ApplicationSystemTestCase setup do + Setting.update(media_path: Rails.root.join("test/fixtures/files")) @album = albums(:album1) end @@ -21,7 +22,6 @@ class AlbumSystemTest < ApplicationSystemTestCase test "play all songs on album" do login_as users(:visitor1) - Setting.update(media_path: Rails.root.join("test/fixtures/files")) visit album_url(@album) click_on "Play all" @@ -53,7 +53,6 @@ class AlbumSystemTest < ApplicationSystemTestCase end test "play song from album" do - Setting.update(media_path: Rails.root.join("test/fixtures/files")) login_as users(:visitor1) visit album_url(@album) diff --git a/test/system/songs_test.rb b/test/system/songs_test.rb index c8400f95..22442ec2 100644 --- a/test/system/songs_test.rb +++ b/test/system/songs_test.rb @@ -4,6 +4,8 @@ class SongsSystemTest < ApplicationSystemTestCase setup do + Setting.update(media_path: Rails.root.join("test/fixtures/files")) + # create many record to test infinite scroll (Pagy::DEFAULT[:items] * 2).times do |n| Song.create( @@ -33,7 +35,6 @@ class SongsSystemTest < ApplicationSystemTestCase end test "play song from songs list" do - Setting.update(media_path: Rails.root.join("test/fixtures/files")) visit songs_url first_song_name = first(:test_id, "song_name").text