summaryrefslogtreecommitdiff
path: root/spec/support/shared_examples/controllers/repository_lfs_file_load_examples.rb
blob: 982e0317f7ffe22c5d6155498d9d2f0578632c95 (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
# frozen_string_literal: true

# Shared examples for controllers that load and send files from the git repository
# (like Projects::RawController or Projects::AvatarsController)

# These examples requires the following variables:
# - `project`
# - `filename`: filename of the file
# - `filepath`: path of the file (contains filename)
# - `subject`: the request to be made to the controller. Example:
# subject { get :show, namespace_id: project.namespace, project_id: project }
shared_examples 'repository lfs file load' do
  context 'when file is stored in lfs' do
    let(:lfs_oid) { '91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897' }
    let(:lfs_size) { '1575078' }
    let!(:lfs_object) { create(:lfs_object, oid: lfs_oid, size: lfs_size) }

    context 'when lfs is enabled' do
      before do
        allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(true)
      end

      context 'when project has access' do
        before do
          project.lfs_objects << lfs_object
          allow_any_instance_of(LfsObjectUploader).to receive(:exists?).and_return(true)
          allow(controller).to receive(:send_file) { controller.head :ok }
        end

        it 'serves the file' do
          # Notice the filename= is omitted from the disposition; this is because
          # Rails 5 will append this header in send_file
          expect(controller).to receive(:send_file)
                            .with(
                              "#{LfsObjectUploader.root}/91/ef/f75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897",
                              filename: filename,
                              disposition: %Q(attachment; filename*=UTF-8''#{filename}))

          subject

          expect(response).to have_gitlab_http_status(200)
        end

        context 'and lfs uses object storage' do
          let(:lfs_object) { create(:lfs_object, :with_file, oid: lfs_oid, size: lfs_size) }

          before do
            stub_lfs_object_storage
            lfs_object.file.migrate!(LfsObjectUploader::Store::REMOTE)
          end

          it 'responds with redirect to file' do
            subject

            expect(response).to have_gitlab_http_status(302)
            expect(response.location).to include(lfs_object.reload.file.path)
          end

          it 'sets content disposition' do
            subject

            file_uri = URI.parse(response.location)
            params = CGI.parse(file_uri.query)

            expect(params["response-content-disposition"].first).to eq(%q(attachment; filename="lfs_object.iso"; filename*=UTF-8''lfs_object.iso))
          end
        end
      end

      context 'when project does not have access' do
        it 'does not serve the file' do
          subject

          expect(response).to have_gitlab_http_status(404)
        end
      end
    end

    context 'when lfs is not enabled' do
      before do
        allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(false)
      end

      it 'delivers ASCII file' do
        subject

        expect(response).to have_gitlab_http_status(200)
        expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
        expect(response.header['Content-Disposition'])
            .to eq('inline')
        expect(response.header[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with('git-blob:')
      end
    end
  end
end