# typed: false # frozen_string_literal: true require "rails_helper" require "fileutils" require "securerandom" RSpec.describe LoadedMedia do let(:gif_fixture_path) do Rails.root.join("test/fixtures/files/images/e621-5418755-animated.gif").to_s end let(:jpeg_fixture_path) do Rails .root .join("test/fixtures/files/images/thumb-ac63d9d7-low-quality.jpeg") .to_s end let(:webm_fixture_path) do Rails .root .join("test/fixtures/files/images/e621-5421402-animated.webm") .to_s end let(:mp4_fixture_path) do Rails.root.join("test/fixtures/files/images/bsky-3l6tnjkcgw72y.mp4").to_s end let(:bmp_fixture_path) do Rails .root .join( "test/fixtures/files/images/1404612500.nickthefur775_streaminglive.bmp", ) .to_s end let(:thumbnail_options) do LoadedMedia::ThumbnailOptions.new( width: 100, height: 100, quality: 95, size: :down, interlace: true, for_frames: [0], ) end describe ".from_file" do context "with a gif file" do it "creates a LoadedMedia::Gif instance" do media = LoadedMedia.from_file("image/gif", gif_fixture_path) expect(media).to be_a(LoadedMedia::Gif) expect(media.num_frames).to eq(37) end end context "with a jpeg file" do it "creates a LoadedMedia::StaticImage instance" do media = LoadedMedia.from_file("image/jpeg", jpeg_fixture_path) expect(media).to be_a(LoadedMedia::StaticImage) expect(media.num_frames).to eq(1) end end context "with a webm file" do it "creates a LoadedMedia::WebmOrMp4 instance" do media = LoadedMedia.from_file("video/webm", webm_fixture_path) expect(media).to be_a(LoadedMedia::WebmOrMp4) expect(media.num_frames).to eq(908) end end context "with an mp4 file" do it "creates a LoadedMedia::WebmOrMp4 instance" do media = LoadedMedia.from_file("video/mp4", mp4_fixture_path) expect(media).to be_a(LoadedMedia::WebmOrMp4) expect(media.num_frames).to eq(22) end end context "with an unsupported file type" do it "returns nil" do media = LoadedMedia.from_file("application/pdf", jpeg_fixture_path) expect(media).to be_nil end end end describe "#write_frame_thumbnail" do let(:output_dir) do File.join(BlobFile::TMP_DIR, "loaded_media_spec-#{SecureRandom.uuid}") end before { FileUtils.mkdir_p(output_dir) } after { FileUtils.rm_rf(output_dir) } def make_output_path(frame) File.join(output_dir, "thumbnail-#{frame}-#{SecureRandom.uuid}.jpg") end context "with a gif file" do it "can extract and save a thumbnail" do media = LoadedMedia.from_file("image/gif", gif_fixture_path) output_path = make_output_path(0) media.write_frame_thumbnail(0, output_path, thumbnail_options) expect(File.exist?(output_path)).to be true expect(File.size(output_path)).to be > 0 end end context "with a jpeg file" do it "can create and save a thumbnail" do media = LoadedMedia.from_file("image/jpeg", jpeg_fixture_path) output_path = make_output_path(0) media.write_frame_thumbnail(0, output_path, thumbnail_options) expect(File.exist?(output_path)).to be true expect(File.size(output_path)).to be > 0 end end context "with a webm file" do it "can extract a frame and save a thumbnail" do media = LoadedMedia.from_file("video/webm", webm_fixture_path) output_path = make_output_path(0) media.write_frame_thumbnail(0, output_path, thumbnail_options) expect(File.exist?(output_path)).to be true expect(File.size(output_path)).to be > 0 end it "creates different frames" do media = LoadedMedia.from_file("video/webm", webm_fixture_path) paths = [0, 453, media.num_frames - 1].map do |frame| output_path = make_output_path(frame) media.write_frame_thumbnail(frame, output_path, thumbnail_options) output_path end expect(paths.uniq.length).to eq(3) expect(FileUtils.compare_file(paths[0], paths[1])).to be false expect(FileUtils.compare_file(paths[0], paths[2])).to be false expect(FileUtils.compare_file(paths[1], paths[2])).to be false end it "works with files that have a strange last frame" do media = LoadedMedia.from_file( "video/webm", Rails .root .join("test/fixtures/files/images/last-frame-weird-ts.webm") .to_s, ) paths = [0, 50, media.num_frames - 1].map do |frame| output_path = make_output_path(frame) media.write_frame_thumbnail(frame, output_path, thumbnail_options) output_path end expect(paths.uniq.length).to eq(3) expect(FileUtils.compare_file(paths[0], paths[1])).to be false expect(FileUtils.compare_file(paths[0], paths[2])).to be false expect(FileUtils.compare_file(paths[1], paths[2])).to be false end end context "with an mp4 file" do it "can extract a frame and save a thumbnail" do media = LoadedMedia.from_file("video/mp4", mp4_fixture_path) output_path = make_output_path(0) media.write_frame_thumbnail(0, output_path, thumbnail_options) end it "creates different frames" do media = LoadedMedia.from_file("video/mp4", mp4_fixture_path) paths = [0, 10, media.num_frames - 1].map do |frame| output_path = make_output_path(frame) media.write_frame_thumbnail(frame, output_path, thumbnail_options) output_path end expect(paths.uniq.length).to eq(3) expect(FileUtils.compare_file(paths[0], paths[1])).to be false expect(FileUtils.compare_file(paths[0], paths[2])).to be false expect(FileUtils.compare_file(paths[1], paths[2])).to be false end end context "with a bmp file" do it "can extract a frame and save a thumbnail" do media = LoadedMedia.from_file("image/bmp", bmp_fixture_path) output_path = make_output_path(0) media.write_frame_thumbnail(0, output_path, thumbnail_options) expect(File.exist?(output_path)).to be true expect(File.size(output_path)).to be > 0 end end end end