summaryrefslogtreecommitdiff
path: root/spec/uploaders/records_uploads_spec.rb
blob: c1f5f962d771a7d902995ff9715892895182dc61 (plain)
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
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
120
121
122
123
124
125
126
127
128
129
130
131
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe RecordsUploads do
  let!(:uploader) do
    stub_const('RecordsUploadsExampleUploader', Class.new(GitlabUploader))

    RecordsUploadsExampleUploader.class_eval do
      include RecordsUploads::Concern

      storage :file

      def dynamic_segment
        'co/fe/ee'
      end
    end

    RecordsUploadsExampleUploader.new(build_stubbed(:user))
  end

  def upload_fixture(filename)
    fixture_file_upload(File.join('spec', 'fixtures', filename))
  end

  describe 'callbacks' do
    let(:upload) { create(:upload) }

    before do
      uploader.upload = upload
    end

    it '#record_upload after `store`' do
      expect(uploader).to receive(:record_upload).once

      uploader.store!(upload_fixture('doc_sample.txt'))
    end

    it '#destroy_upload after `remove`' do
      uploader.store!(upload_fixture('doc_sample.txt'))

      expect(uploader).to receive(:destroy_upload).once
      uploader.remove!
    end
  end

  describe '#record_upload callback' do
    it 'creates an Upload record after store' do
      expect { uploader.store!(upload_fixture('rails_sample.jpg')) }.to change { Upload.count }.by(1)
    end

    it 'creates a new record and assigns size, path, model, and uploader' do
      uploader.store!(upload_fixture('rails_sample.jpg'))

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

    it "does not create an Upload record when the file doesn't exist" do
      allow(uploader).to receive(:file).and_return(double(exists?: false))

      expect { uploader.store!(upload_fixture('rails_sample.jpg')) }.not_to change { Upload.count }
    end

    it 'does not create an Upload record if model is missing' do
      allow_any_instance_of(RecordsUploadsExampleUploader).to receive(:model).and_return(nil)

      expect { uploader.store!(upload_fixture('rails_sample.jpg')) }.not_to change { Upload.count }
    end

    it 'destroys Upload records at the same path before recording' do
      existing = Upload.create!(
        path: File.join('uploads', 'rails_sample.jpg'),
        size: 512.kilobytes,
        model: build_stubbed(:user),
        uploader: uploader.class.to_s
      )

      uploader.upload = existing
      uploader.store!(upload_fixture('rails_sample.jpg'))

      expect { existing.reload }.to raise_error(ActiveRecord::RecordNotFound)
      expect(Upload.count).to eq(1)
    end

    it 'does not affect other uploads with different model but the same path' do
      project = create(:project)
      other_project = create(:project)

      uploader = RecordsUploadsExampleUploader.new(other_project)

      upload_for_project = Upload.create!(
        path: File.join('uploads', 'rails_sample.jpg'),
        size: 512.kilobytes,
        model: project,
        uploader: uploader.class.to_s
      )

      uploader.store!(upload_fixture('rails_sample.jpg'))

      upload_for_project_fresh = Upload.find(upload_for_project.id)

      expect(upload_for_project).to eq(upload_for_project_fresh)
      expect(Upload.count).to eq(2)
    end
  end

  describe '#destroy_upload callback' do
    it 'destroys Upload records at the same path after removal' do
      uploader.store!(upload_fixture('rails_sample.jpg'))

      expect { uploader.remove! }.to change { Upload.count }.from(1).to(0)
    end
  end

  describe '#filename' do
    it 'gets the filename from the path recorded in the database, not CarrierWave' do
      uploader.store!(upload_fixture('rails_sample.jpg'))
      expect_any_instance_of(GitlabUploader).not_to receive(:filename)

      expect(uploader.filename).to eq('rails_sample.jpg')
    end
  end
end