files_spec.rb 9.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
require 'spec_helper'

describe API::V3::Files, api: true  do
  include ApiHelpers

  # I have to remove periods from the end of the name
  # This happened when the user's name had a suffix (i.e. "Sr.")
  # This seems to be what git does under the hood. For example, this commit:
  #
  # $ git commit --author='Foo Sr. <foo@example.com>' -m 'Where's my trailing period?'
  #
  # results in this:
  #
  # $ git show --pretty
  # ...
  # Author: Foo Sr <foo@example.com>
  # ...
R
Robert Schilling 已提交
18 19 20 21 22 23 24 25 26 27 28 29

  let(:user) { create(:user) }
  let!(:project) { create(:project, :repository, namespace: user.namespace ) }
  let(:guest) { create(:user) { |u| project.add_guest(u) } }
  let(:file_path) { 'files/ruby/popen.rb' }
  let(:params) do
    {
      file_path: file_path,
      ref: 'master'
    }
  end
  let(:author_email) { FFaker::Internet.email }
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
  let(:author_name) { FFaker::Name.name.chomp("\.") }

  before { project.team << [user, :developer] }

  describe "GET /projects/:id/repository/files" do
    let(:route) { "/projects/#{project.id}/repository/files" }

    shared_examples_for 'repository files' do
      it "returns file info" do
        get v3_api(route, current_user), params

        expect(response).to have_http_status(200)
        expect(json_response['file_path']).to eq(file_path)
        expect(json_response['file_name']).to eq('popen.rb')
        expect(json_response['last_commit_id']).to eq('570e7b2abdd848b95f2f578043fc23bd6f6fd24d')
        expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n")
      end

      context 'when no params are given' do
        it_behaves_like '400 response' do
          let(:request) { get v3_api(route, current_user) }
        end
      end

      context 'when file_path does not exist' do
        let(:params) do
          {
            file_path: 'app/models/application.rb',
            ref: 'master',
          }
        end

        it_behaves_like '404 response' do
          let(:request) { get v3_api(route, current_user), params }
          let(:message) { '404 File Not Found' }
        end
      end

      context 'when repository is disabled' do
        include_context 'disabled repository'

        it_behaves_like '403 response' do
          let(:request) { get v3_api(route, current_user), params }
        end
      end
    end

    context 'when unauthenticated', 'and project is public' do
      it_behaves_like 'repository files' do
        let(:project) { create(:project, :public) }
        let(:current_user) { nil }
      end
    end

    context 'when unauthenticated', 'and project is private' do
      it_behaves_like '404 response' do
        let(:request) { get v3_api(route), params }
        let(:message) { '404 Project Not Found' }
      end
    end

    context 'when authenticated', 'as a developer' do
      it_behaves_like 'repository files' do
        let(:current_user) { user }
      end
    end

    context 'when authenticated', 'as a guest' do
      it_behaves_like '403 response' do
        let(:request) { get v3_api(route, guest), params }
      end
    end
  end

  describe "POST /projects/:id/repository/files" do
    let(:valid_params) do
      {
        file_path: 'newfile.rb',
        branch_name: 'master',
        content: 'puts 8',
        commit_message: 'Added newfile'
      }
    end

    it "creates a new file in project repo" do
      post v3_api("/projects/#{project.id}/repository/files", user), valid_params

      expect(response).to have_http_status(201)
      expect(json_response['file_path']).to eq('newfile.rb')
      last_commit = project.repository.commit.raw
      expect(last_commit.author_email).to eq(user.email)
      expect(last_commit.author_name).to eq(user.name)
    end

    it "returns a 400 bad request if no params given" do
      post v3_api("/projects/#{project.id}/repository/files", user)

      expect(response).to have_http_status(400)
    end

    it "returns a 400 if editor fails to create file" do
D
Douwe Maan 已提交
131
      allow_any_instance_of(Repository).to receive(:create_file).
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
        and_return(false)

      post v3_api("/projects/#{project.id}/repository/files", user), valid_params

      expect(response).to have_http_status(400)
    end

    context "when specifying an author" do
      it "creates a new file with the specified author" do
        valid_params.merge!(author_email: author_email, author_name: author_name)

        post v3_api("/projects/#{project.id}/repository/files", user), valid_params

        expect(response).to have_http_status(201)
        last_commit = project.repository.commit.raw
        expect(last_commit.author_email).to eq(author_email)
        expect(last_commit.author_name).to eq(author_name)
      end
    end
151 152 153 154 155

    context 'when the repo is empty' do
      let!(:project) { create(:project_empty_repo, namespace: user.namespace ) }

      it "creates a new file in project repo" do
D
Douwe Maan 已提交
156
        post v3_api("/projects/#{project.id}/repository/files", user), valid_params
157 158 159 160 161 162 163 164

        expect(response).to have_http_status(201)
        expect(json_response['file_path']).to eq('newfile.rb')
        last_commit = project.repository.commit.raw
        expect(last_commit.author_email).to eq(user.email)
        expect(last_commit.author_name).to eq(user.name)
      end
    end
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
  end

  describe "PUT /projects/:id/repository/files" do
    let(:valid_params) do
      {
        file_path: file_path,
        branch_name: 'master',
        content: 'puts 8',
        commit_message: 'Changed file'
      }
    end

    it "updates existing file in project repo" do
      put v3_api("/projects/#{project.id}/repository/files", user), valid_params

      expect(response).to have_http_status(200)
      expect(json_response['file_path']).to eq(file_path)
      last_commit = project.repository.commit.raw
      expect(last_commit.author_email).to eq(user.email)
      expect(last_commit.author_name).to eq(user.name)
    end

    it "returns a 400 bad request if no params given" do
      put v3_api("/projects/#{project.id}/repository/files", user)

      expect(response).to have_http_status(400)
    end

    context "when specifying an author" do
      it "updates a file with the specified author" do
        valid_params.merge!(author_email: author_email, author_name: author_name, content: "New content")

        put v3_api("/projects/#{project.id}/repository/files", user), valid_params

        expect(response).to have_http_status(200)
        last_commit = project.repository.commit.raw
        expect(last_commit.author_email).to eq(author_email)
        expect(last_commit.author_name).to eq(author_name)
      end
    end
  end

  describe "DELETE /projects/:id/repository/files" do
    let(:valid_params) do
      {
        file_path: file_path,
        branch_name: 'master',
        commit_message: 'Changed file'
      }
    end

    it "deletes existing file in project repo" do
      delete v3_api("/projects/#{project.id}/repository/files", user), valid_params

      expect(response).to have_http_status(200)
      expect(json_response['file_path']).to eq(file_path)
      last_commit = project.repository.commit.raw
      expect(last_commit.author_email).to eq(user.email)
      expect(last_commit.author_name).to eq(user.name)
    end

    it "returns a 400 bad request if no params given" do
      delete v3_api("/projects/#{project.id}/repository/files", user)

      expect(response).to have_http_status(400)
    end

    it "returns a 400 if fails to create file" do
D
Douwe Maan 已提交
233
      allow_any_instance_of(Repository).to receive(:delete_file).and_return(false)
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285

      delete v3_api("/projects/#{project.id}/repository/files", user), valid_params

      expect(response).to have_http_status(400)
    end

    context "when specifying an author" do
      it "removes a file with the specified author" do
        valid_params.merge!(author_email: author_email, author_name: author_name)

        delete v3_api("/projects/#{project.id}/repository/files", user), valid_params

        expect(response).to have_http_status(200)
        last_commit = project.repository.commit.raw
        expect(last_commit.author_email).to eq(author_email)
        expect(last_commit.author_name).to eq(author_name)
      end
    end
  end

  describe "POST /projects/:id/repository/files with binary file" do
    let(:file_path) { 'test.bin' }
    let(:put_params) do
      {
        file_path: file_path,
        branch_name: 'master',
        content: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=',
        commit_message: 'Binary file with a \n should not be touched',
        encoding: 'base64'
      }
    end
    let(:get_params) do
      {
        file_path: file_path,
        ref: 'master',
      }
    end

    before do
      post v3_api("/projects/#{project.id}/repository/files", user), put_params
    end

    it "remains unchanged" do
      get v3_api("/projects/#{project.id}/repository/files", user), get_params

      expect(response).to have_http_status(200)
      expect(json_response['file_path']).to eq(file_path)
      expect(json_response['file_name']).to eq(file_path)
      expect(json_response['content']).to eq(put_params[:content])
    end
  end
end