uploaded_file_spec.rb 3.35 KB
Newer Older
1 2 3
require 'spec_helper'

describe UploadedFile do
4 5
  let(:temp_dir) { Dir.tmpdir }
  let(:temp_file) { Tempfile.new("test", temp_dir) }
6

7 8 9
  before do
    FileUtils.touch(temp_file)
  end
10

11 12 13 14 15 16
  after do
    FileUtils.rm_f(temp_file)
  end

  describe ".from_params" do
    let(:upload_path) { nil }
17 18 19 20 21

    after do
      FileUtils.rm_r(upload_path) if upload_path
    end

22 23 24 25
    subject do
      described_class.from_params(params, :file, upload_path)
    end

26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
    context 'when valid file is specified' do
      context 'only local path is specified' do
        let(:params) do
          { 'file.path' => temp_file.path }
        end

        it "succeeds" do
          is_expected.not_to be_nil
        end

        it "generates filename from path" do
          expect(subject.original_filename).to eq(::File.basename(temp_file.path))
        end
      end

      context 'all parameters are specified' do
        let(:params) do
          { 'file.path' => temp_file.path,
44
            'file.name' => 'dir/my file&.txt',
45 46 47 48 49 50 51 52 53 54
            'file.type' => 'my/type',
            'file.sha256' => 'sha256',
            'file.remote_id' => 'remote_id' }
        end

        it "succeeds" do
          is_expected.not_to be_nil
        end

        it "generates filename from path" do
55
          expect(subject.original_filename).to eq('my_file_.txt')
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
          expect(subject.content_type).to eq('my/type')
          expect(subject.sha256).to eq('sha256')
          expect(subject.remote_id).to eq('remote_id')
        end
      end
    end

    context 'when no params are specified' do
      let(:params) do
        {}
      end

      it "does not return an object" do
        is_expected.to be_nil
      end
    end

    context 'when only remote id is specified' do
      let(:params) do
        { 'file.remote_id' => 'remote_id' }
      end

      it "raises an error" do
        expect { subject }.to raise_error(UploadedFile::InvalidPathError, /file is invalid/)
      end
    end

    context 'when verifying allowed paths' do
      let(:params) do
        { 'file.path' => temp_file.path }
      end

      context 'when file is stored in system temporary folder' do
        let(:temp_dir) { Dir.tmpdir }

        it "succeeds" do
          is_expected.not_to be_nil
        end
      end

      context 'when file is stored in user provided upload path' do
        let(:upload_path) { Dir.mktmpdir }
        let(:temp_dir) { upload_path }

        it "succeeds" do
          is_expected.not_to be_nil
        end
      end

      context 'when file is stored outside of user provided upload path' do
        let!(:generated_dir) { Dir.mktmpdir }
        let!(:temp_dir) { Dir.mktmpdir }

        before do
          # We overwrite default temporary path
          allow(Dir).to receive(:tmpdir).and_return(generated_dir)
        end

        it "raises an error" do
          expect { subject }.to raise_error(UploadedFile::InvalidPathError, /insecure path used/)
        end
      end
    end
  end
120 121 122 123 124 125 126

  describe '#sanitize_filename' do
    it { expect(described_class.new(temp_file.path).sanitize_filename('spaced name')).to eq('spaced_name') }
    it { expect(described_class.new(temp_file.path).sanitize_filename('#$%^&')).to eq('_____') }
    it { expect(described_class.new(temp_file.path).sanitize_filename('..')).to eq('_..') }
    it { expect(described_class.new(temp_file.path).sanitize_filename('')).to eq('unnamed') }
  end
127
end