BigW Consortium Gitlab

upload_spec.rb 4.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
require 'rails_helper'

describe Upload, type: :model do
  describe 'assocations' do
    it { is_expected.to belong_to(:model) }
  end

  describe 'validations' do
    it { is_expected.to validate_presence_of(:size) }
    it { is_expected.to validate_presence_of(:path) }
    it { is_expected.to validate_presence_of(:model) }
    it { is_expected.to validate_presence_of(:uploader) }
  end

  describe 'callbacks' do
    context 'for a file above the checksum threshold' do
      it 'schedules checksum calculation' do
        stub_const('UploadChecksumWorker', spy)

        upload = described_class.create(
          path: __FILE__,
          size: described_class::CHECKSUM_THRESHOLD + 1.kilobyte,
          model: build_stubbed(:user),
          uploader: double('ExampleUploader')
        )

        expect(UploadChecksumWorker)
          .to have_received(:perform_async).with(upload.id)
      end
    end

    context 'for a file at or below the checksum threshold' do
      it 'calculates checksum immediately before save' do
        upload = described_class.new(
          path: __FILE__,
          size: described_class::CHECKSUM_THRESHOLD,
          model: build_stubbed(:user),
          uploader: double('ExampleUploader')
        )

        expect { upload.save }
          .to change { upload.checksum }.from(nil)
          .to(a_string_matching(/\A\h{64}\z/))
      end
    end
  end

  describe '.remove_path' do
    it 'removes all records at the given path' do
      described_class.create!(
        size: File.size(__FILE__),
        path: __FILE__,
        model: build_stubbed(:user),
        uploader: 'AvatarUploader'
      )

57 58
      expect { described_class.remove_path(__FILE__) }
        .to change { described_class.count }.from(1).to(0)
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    end
  end

  describe '.record' do
    let(:fake_uploader) do
      double(
        file: double(size: 12_345),
        relative_path: 'foo/bar.jpg',
        model: build_stubbed(:user),
        class: 'AvatarUploader'
      )
    end

    it 'removes existing paths before creation' do
      expect(described_class).to receive(:remove_path)
        .with(fake_uploader.relative_path)

      described_class.record(fake_uploader)
    end

    it 'creates a new record and assigns size, path, model, and uploader' do
      upload = described_class.record(fake_uploader)

      aggregate_failures do
        expect(upload).to be_persisted
        expect(upload.size).to eq fake_uploader.file.size
        expect(upload.path).to eq fake_uploader.relative_path
        expect(upload.model_id).to eq fake_uploader.model.id
        expect(upload.model_type).to eq fake_uploader.model.class.to_s
        expect(upload.uploader).to eq fake_uploader.class
      end
    end
  end

  describe '#absolute_path' do
    it 'returns the path directly when already absolute' do
      path = '/path/to/namespace/project/secret/file.jpg'
      upload = described_class.new(path: path)

      expect(upload).not_to receive(:uploader_class)

      expect(upload.absolute_path).to eq path
    end

    it "delegates to the uploader's absolute_path method" do
      uploader = spy('FakeUploader')
      upload = described_class.new(path: 'secret/file.jpg')
      expect(upload).to receive(:uploader_class).and_return(uploader)

      upload.absolute_path

      expect(uploader).to have_received(:absolute_path).with(upload)
    end
  end

  describe '#calculate_checksum' do
    it 'calculates the SHA256 sum' do
      upload = described_class.new(
        path: __FILE__,
        size: described_class::CHECKSUM_THRESHOLD - 1.megabyte
      )
      expected = Digest::SHA256.file(__FILE__).hexdigest

      expect { upload.calculate_checksum }
        .to change { upload.checksum }.from(nil).to(expected)
    end

    it 'returns nil for a non-existant file' do
      upload = described_class.new(
        path: __FILE__,
        size: described_class::CHECKSUM_THRESHOLD - 1.megabyte
      )

      expect(upload).to receive(:exist?).and_return(false)

      expect(upload.calculate_checksum).to be_nil
    end
  end

  describe '#exist?' do
    it 'returns true when the file exists' do
      upload = described_class.new(path: __FILE__)

      expect(upload).to exist
    end

    it 'returns false when the file does not exist' do
      upload = described_class.new(path: "#{__FILE__}-nope")

      expect(upload).not_to exist
    end
  end
end