# frozen_string_literal: true require 'spec_helper' RSpec.describe Gitlab::FileTypeDetection do describe '.extension_match?' do let(:extensions) { %w[foo bar] } it 'returns false when filename is blank' do expect(described_class.extension_match?(nil, extensions)).to eq(false) expect(described_class.extension_match?('', extensions)).to eq(false) end it 'returns true when filename matches extensions' do expect(described_class.extension_match?('file.foo', extensions)).to eq(true) expect(described_class.extension_match?('file.bar', extensions)).to eq(true) end it 'returns false when filename does not match extensions' do expect(described_class.extension_match?('file.baz', extensions)).to eq(false) end it 'can match case insensitive filenames' do expect(described_class.extension_match?('file.FOO', extensions)).to eq(true) end it 'can match filenames with periods' do expect(described_class.extension_match?('my.file.foo', extensions)).to eq(true) end it 'can match filenames with directories' do expect(described_class.extension_match?('my/file.foo', extensions)).to eq(true) end end context 'when class is an uploader' do let(:uploader) do example_uploader = Class.new(CarrierWave::Uploader::Base) do include Gitlab::FileTypeDetection storage :file end example_uploader.new end def upload_fixture(filename) fixture_file_upload(File.join('spec', 'fixtures', filename)) end describe '#image?' do it 'returns true for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).to be_image end it 'returns false if filename has a dangerous image extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).to be_dangerous_image expect(uploader).not_to be_image end it 'returns false for a video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).not_to be_image end it 'returns false for an audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).not_to be_image end it 'returns false if filename is blank' do uploader.store!(upload_fixture('dk.png')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_image end end describe '#video?' do it 'returns true for a video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).to be_video end it 'returns false for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).not_to be_video end it 'returns false for an audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).not_to be_video end it 'returns false if file has a dangerous image extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).to be_dangerous_image expect(uploader).not_to be_video end it 'returns false if filename is blank' do uploader.store!(upload_fixture('video_sample.mp4')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_video end end describe '#audio?' do it 'returns true for an audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).to be_audio end it 'returns false for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).not_to be_audio end it 'returns false for a video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).not_to be_audio end it 'returns false if file has a dangerous image extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).to be_dangerous_image expect(uploader).not_to be_audio end it 'returns false if filename is blank' do uploader.store!(upload_fixture('audio_sample.wav')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_audio end end describe '#embeddable?' do it 'returns true for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).to be_embeddable end it 'returns true for a video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).to be_embeddable end it 'returns true for an audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).to be_embeddable end it 'returns false if not an embeddable file' do uploader.store!(upload_fixture('doc_sample.txt')) expect(uploader).not_to be_embeddable end it 'returns false if filename has a dangerous image extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).to be_dangerous_image expect(uploader).not_to be_embeddable end it 'returns false if filename is blank' do uploader.store!(upload_fixture('dk.png')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_embeddable end end describe '#image_safe_for_scaling?' do it 'returns true for allowed image formats' do uploader.store!(upload_fixture('rails_sample.jpg')) expect(uploader).to be_image_safe_for_scaling end it 'returns false for other files' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).not_to be_image_safe_for_scaling end end describe '#dangerous_image?' do it 'returns true if filename has a dangerous extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).to be_dangerous_image end it 'returns false for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).not_to be_dangerous_image end it 'returns false for a video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).not_to be_dangerous_image end it 'returns false for an audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).not_to be_dangerous_image end it 'returns false if filename is blank' do uploader.store!(upload_fixture('dk.png')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_dangerous_image end end describe '#dangerous_video?' do it 'returns false for a safe video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).not_to be_dangerous_video end it 'returns false if filename is a dangerous image extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).not_to be_dangerous_video end it 'returns false for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).not_to be_dangerous_video end it 'returns false for an audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).not_to be_dangerous_video end it 'returns false if filename is blank' do uploader.store!(upload_fixture('dk.png')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_dangerous_video end end describe '#dangerous_audio?' do it 'returns false for a safe audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).not_to be_dangerous_audio end it 'returns false if filename is a dangerous image extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).not_to be_dangerous_audio end it 'returns false for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).not_to be_dangerous_audio end it 'returns false for an video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).not_to be_dangerous_audio end it 'returns false if filename is blank' do uploader.store!(upload_fixture('dk.png')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_dangerous_audio end end describe '#dangerous_embeddable?' do it 'returns true if filename has a dangerous image extension' do uploader.store!(upload_fixture('unsanitized.svg')) expect(uploader).to be_dangerous_embeddable end it 'returns false for an image file' do uploader.store!(upload_fixture('dk.png')) expect(uploader).not_to be_dangerous_embeddable end it 'returns false for a video file' do uploader.store!(upload_fixture('video_sample.mp4')) expect(uploader).not_to be_dangerous_embeddable end it 'returns false for an audio file' do uploader.store!(upload_fixture('audio_sample.wav')) expect(uploader).not_to be_dangerous_embeddable end it 'returns false for a non-embeddable file' do uploader.store!(upload_fixture('doc_sample.txt')) expect(uploader).not_to be_dangerous_embeddable end it 'returns false if filename is blank' do uploader.store!(upload_fixture('dk.png')) allow(uploader).to receive(:filename).and_return(nil) expect(uploader).not_to be_dangerous_embeddable end end end context 'when class is a regular class' do let(:custom_class) do custom_class = Class.new do include Gitlab::FileTypeDetection end custom_class.new end describe '#image?' do it 'returns true for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).to be_image end it 'returns false if file has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).to be_dangerous_image expect(custom_class).not_to be_image end it 'returns false for a video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).not_to be_image end it 'returns false for an audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).not_to be_image end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_image end end describe '#image_safe_for_scaling?' do using RSpec::Parameterized::TableSyntax where(:filename, :expectation) do 'img.jpg' | true 'img.jpeg' | true 'img.png' | true 'img.svg' | false end with_them do it "returns expected result" do allow(custom_class).to receive(:filename).and_return(filename) expect(custom_class.image_safe_for_scaling?).to be(expectation) end end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_image_safe_for_scaling end end describe '#video?' do it 'returns true for a video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).to be_video end it 'returns false for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).not_to be_video end it 'returns false for an audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).not_to be_video end it 'returns false if file has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).to be_dangerous_image expect(custom_class).not_to be_video end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_video end end describe '#audio?' do it 'returns true for an audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).to be_audio end it 'returns false for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).not_to be_audio end it 'returns false for a video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).not_to be_audio end it 'returns false if file has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).to be_dangerous_image expect(custom_class).not_to be_audio end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_audio end end describe '#embeddable?' do it 'returns true for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).to be_embeddable end it 'returns true for a video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).to be_embeddable end it 'returns true for an audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).to be_embeddable end it 'returns false if not an embeddable file' do allow(custom_class).to receive(:filename).and_return('doc_sample.txt') expect(custom_class).not_to be_embeddable end it 'returns false if filename has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).to be_dangerous_image expect(custom_class).not_to be_embeddable end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_embeddable end end describe '#dangerous_image?' do it 'returns true if file has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).to be_dangerous_image end it 'returns false for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).not_to be_dangerous_image end it 'returns false for a video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).not_to be_dangerous_image end it 'returns false for an audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).not_to be_dangerous_image end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_dangerous_image end end describe '#dangerous_video?' do it 'returns false for a safe video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).not_to be_dangerous_video end it 'returns false for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).not_to be_dangerous_video end it 'returns false for an audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).not_to be_dangerous_video end it 'returns false if file has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).not_to be_dangerous_video end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_dangerous_video end end describe '#dangerous_audio?' do it 'returns false for a safe audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).not_to be_dangerous_audio end it 'returns false for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).not_to be_dangerous_audio end it 'returns false for a video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).not_to be_dangerous_audio end it 'returns false if file has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).not_to be_dangerous_audio end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_dangerous_audio end end describe '#dangerous_embeddable?' do it 'returns true if file has a dangerous image extension' do allow(custom_class).to receive(:filename).and_return('unsanitized.svg') expect(custom_class).to be_dangerous_embeddable end it 'returns false for an image file' do allow(custom_class).to receive(:filename).and_return('dk.png') expect(custom_class).not_to be_dangerous_embeddable end it 'returns false for a video file' do allow(custom_class).to receive(:filename).and_return('video_sample.mp4') expect(custom_class).not_to be_dangerous_embeddable end it 'returns false for an audio file' do allow(custom_class).to receive(:filename).and_return('audio_sample.wav') expect(custom_class).not_to be_dangerous_embeddable end it 'returns false for a non-embeddable file' do allow(custom_class).to receive(:filename).and_return('doc_sample.txt') expect(custom_class).not_to be_dangerous_embeddable end it 'returns false if filename is blank' do allow(custom_class).to receive(:filename).and_return(nil) expect(custom_class).not_to be_dangerous_embeddable end end end end