pipeline_schedules_controller_spec.rb 16.4 KB
Newer Older
1 2 3
require 'spec_helper'

describe Projects::PipelineSchedulesController do
4 5
  include AccessMatchersForController

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  set(:project) { create(:empty_project, :public) }
  let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) }

  describe 'GET #index' do
    let(:scope) { nil }
    let!(:inactive_pipeline_schedule) do
      create(:ci_pipeline_schedule, :inactive, project: project)
    end

    it 'renders the index view' do
      visit_pipelines_schedules

      expect(response).to have_http_status(:ok)
      expect(response).to render_template(:index)
    end

22 23 24 25 26 27 28 29
    it 'avoids N + 1 queries' do
      control_count = ActiveRecord::QueryRecorder.new { visit_pipelines_schedules }.count

      create_list(:ci_pipeline_schedule, 2, project: project)

      expect { visit_pipelines_schedules }.not_to exceed_query_limit(control_count)
    end

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    context 'when the scope is set to active' do
      let(:scope) { 'active' }

      before do
        visit_pipelines_schedules
      end

      it 'only shows active pipeline schedules' do
        expect(response).to have_http_status(:ok)
        expect(assigns(:schedules)).to include(pipeline_schedule)
        expect(assigns(:schedules)).not_to include(inactive_pipeline_schedule)
      end
    end

    def visit_pipelines_schedules
      get :index, namespace_id: project.namespace.to_param, project_id: project, scope: scope
    end
  end

49
  describe 'GET #new' do
Shinya Maeda's avatar
Shinya Maeda committed
50 51
    set(:user) { create(:user) }

52
    before do
Shinya Maeda's avatar
Shinya Maeda committed
53 54
      project.add_developer(user)
      sign_in(user)
55
    end
56

57 58 59 60 61 62 63 64 65
    it 'initializes a pipeline schedule model' do
      get :new, namespace_id: project.namespace.to_param, project_id: project

      expect(response).to have_http_status(:ok)
      expect(assigns(:schedule)).to be_a_new(Ci::PipelineSchedule)
    end
  end

  describe 'POST #create' do
66
    describe 'functionality' do
Shinya Maeda's avatar
Shinya Maeda committed
67 68
      set(:user) { create(:user) }

69
      before do
Shinya Maeda's avatar
Shinya Maeda committed
70 71
        project.add_developer(user)
        sign_in(user)
72 73
      end

74 75
      let(:basic_param) do
        { description: 'aaaaaaaa', cron: '0 4 * * *', cron_timezone: 'UTC', ref: 'master', active: '1' }
76 77
      end

78 79
      context 'when variables_attributes is empty' do
        let(:schedule) { basic_param }
80

81
        it 'creates a new schedule' do
Shinya Maeda's avatar
Shinya Maeda committed
82
          expect { go }
83 84
            .to change { Ci::PipelineSchedule.count }.by(1)
            .and change { Ci::PipelineScheduleVariable.count }.by(0)
85

86 87
          expect(response).to have_http_status(:found)
        end
88 89
      end

90 91 92
      context 'when variables_attributes has one variable' do
        let(:schedule) do
          basic_param.merge({
Shinya Maeda's avatar
Shinya Maeda committed
93
            variables_attributes: [{ key: 'AAA', value: 'AAA123' }]
94 95
          })
        end
96

97
        it 'creates a new schedule' do
Shinya Maeda's avatar
Shinya Maeda committed
98
          expect { go }
99 100
            .to change { Ci::PipelineSchedule.count }.by(1)
            .and change { Ci::PipelineScheduleVariable.count }.by(1)
101

102 103 104 105
          expect(response).to have_http_status(:found)
          expect(Ci::PipelineScheduleVariable.last.key).to eq("AAA")
          expect(Ci::PipelineScheduleVariable.last.value).to eq("AAA123")
        end
106

107 108
        context 'when the same key has already been persisted' do
          it 'returns an error that the key of variable is invaild' do
Shinya Maeda's avatar
Shinya Maeda committed
109
            go
110

111 112 113
            pipeline_schedule_variable = build(:ci_pipeline_schedule_variable, key: 'AAA', pipeline_schedule: assigns(:schedule))
            expect(pipeline_schedule_variable).to be_invalid
          end
114 115 116
        end
      end

117
      context 'when variables_attributes has one variable and key is empty' do
118 119
        let(:schedule) do
          basic_param.merge({
Shinya Maeda's avatar
Shinya Maeda committed
120
            variables_attributes: [{ key: '', value: 'AAA123' }]
121 122 123
          })
        end

124
        it 'returns an error that the key of variable is invaild' do
Shinya Maeda's avatar
Shinya Maeda committed
125
          expect { go }
126 127
            .to change { Ci::PipelineSchedule.count }.by(0)
            .and change { Ci::PipelineScheduleVariable.count }.by(0)
128

129
          expect(assigns(:schedule).errors['variables.key']).not_to be_empty
130 131 132
        end
      end

133
      context 'when variables_attributes has two variables and unique' do
134 135
        let(:schedule) do
          basic_param.merge({
Shinya Maeda's avatar
Shinya Maeda committed
136
            variables_attributes: [{ key: 'AAA', value: 'AAA123' }, { key: 'BBB', value: 'BBB123' }]
137 138 139
          })
        end

140
        it 'creates a new schedule' do
Shinya Maeda's avatar
Shinya Maeda committed
141
          expect { go }
142 143
            .to change { Ci::PipelineSchedule.count }.by(1)
            .and change { Ci::PipelineScheduleVariable.count }.by(2)
144 145

          expect(response).to have_http_status(:found)
146 147 148 149
          expect(Ci::PipelineScheduleVariable.first.key).to eq("AAA")
          expect(Ci::PipelineScheduleVariable.first.value).to eq("AAA123")
          expect(Ci::PipelineScheduleVariable.last.key).to eq("BBB")
          expect(Ci::PipelineScheduleVariable.last.value).to eq("BBB123")
150 151 152
        end
      end

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
      context 'when variables_attributes has two variables and duplicted' do
        let(:schedule) do
          basic_param.merge({
            variables_attributes: [{ key: 'AAA', value: 'AAA123' }, { key: 'AAA', value: 'BBB123' }]
          })
        end

        it 'returns an error that the keys of variable are duplicated' do
          expect { go }
            .to change { Ci::PipelineSchedule.count }.by(0)
            .and change { Ci::PipelineScheduleVariable.count }.by(0)

          expect(assigns(:schedule).errors['variables.key']).not_to be_empty
        end
      end
168 169
    end

170
    describe 'security' do
171 172
      let(:schedule) { { description: 'aaaaaaaa', cron: '0 4 * * *', cron_timezone: 'UTC', ref: 'master', active: '1' } }

Shinya Maeda's avatar
Shinya Maeda committed
173 174 175 176 177 178 179 180 181
      it { expect { go }.to be_allowed_for(:admin) }
      it { expect { go }.to be_allowed_for(:owner).of(project) }
      it { expect { go }.to be_allowed_for(:master).of(project) }
      it { expect { go }.to be_allowed_for(:developer).of(project) }
      it { expect { go }.to be_denied_for(:reporter).of(project) }
      it { expect { go }.to be_denied_for(:guest).of(project) }
      it { expect { go }.to be_denied_for(:user) }
      it { expect { go }.to be_denied_for(:external) }
      it { expect { go }.to be_denied_for(:visitor) }
182
    end
Shinya Maeda's avatar
Shinya Maeda committed
183

184 185
    def go
      post :create, namespace_id: project.namespace.to_param, project_id: project, schedule: schedule
186 187
    end
  end
188

189 190
  describe 'PUT #update' do
    describe 'functionality' do
Shinya Maeda's avatar
Shinya Maeda committed
191
      set(:user) { create(:user) }
192
      let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: user) }
193

194 195 196
      before do
        project.add_developer(user)
        sign_in(user)
197
      end
198

199 200 201 202 203 204 205 206 207
      context 'when a pipeline schedule has no variables' do
        let(:basic_param) do
          { description: 'updated_desc', cron: '0 1 * * *', cron_timezone: 'UTC', ref: 'patch-x', active: '1' }
        end

        context 'when params do not include variables' do
          let(:schedule) { basic_param }

          it 'updates only scheduled pipeline attributes' do
Shinya Maeda's avatar
Shinya Maeda committed
208
            go
209 210 211 212 213 214 215 216 217 218 219 220 221

            pipeline_schedule.reload
            expect(response).to have_http_status(:found)
            expect(pipeline_schedule.description).to eq('updated_desc')
            expect(pipeline_schedule.cron).to eq('0 1 * * *')
            expect(pipeline_schedule.cron_timezone).to eq('UTC')
            expect(pipeline_schedule.ref).to eq('patch-x')
            expect(pipeline_schedule.active).to eq(true)
            expect(pipeline_schedule.variables).to be_empty
          end
        end

        context 'when params include one variable' do
222 223
          let(:schedule) do
            basic_param.merge({
Shinya Maeda's avatar
Shinya Maeda committed
224
              variables_attributes: [{ key: 'AAA', value: 'AAA123' }]
225 226 227
            })
          end

228
          it 'inserts new variable to the pipeline schedule' do
Shinya Maeda's avatar
Shinya Maeda committed
229
            expect { go }.to change { Ci::PipelineScheduleVariable.count }.by(1)
230

231 232
            pipeline_schedule.reload
            expect(response).to have_http_status(:found)
233
            expect(pipeline_schedule.variables.last.key).to eq('AAA')
234
            expect(pipeline_schedule.variables.last.value).to eq('AAA123')
235 236 237
          end
        end

238
        context 'when params include two unique variables' do
239 240
          let(:schedule) do
            basic_param.merge({
Shinya Maeda's avatar
Shinya Maeda committed
241
              variables_attributes: [{ key: 'AAA', value: 'AAA123' }, { key: 'BBB', value: 'BBB123' }]
242 243 244
            })
          end

245
          it 'inserts two new variables to the pipeline schedule' do
Shinya Maeda's avatar
Shinya Maeda committed
246
            expect { go }.to change { Ci::PipelineScheduleVariable.count }.by(2)
247

248 249 250 251 252 253
            pipeline_schedule.reload
            expect(response).to have_http_status(:found)
            expect(pipeline_schedule.variables.first.key).to eq('AAA')
            expect(pipeline_schedule.variables.first.value).to eq('AAA123')
            expect(pipeline_schedule.variables.last.key).to eq('BBB')
            expect(pipeline_schedule.variables.last.value).to eq('BBB123')
254 255 256
          end
        end

257 258 259 260 261 262 263 264 265 266 267 268 269 270
        context 'when params include two duplicated variables' do
          let(:schedule) do
            basic_param.merge({
              variables_attributes: [{ key: 'AAA', value: 'AAA123' }, { key: 'AAA', value: 'BBB123' }]
            })
          end

          it 'returns an error that variables are duplciated' do
            put :update, namespace_id: project.namespace.to_param,
              project_id: project, id: pipeline_schedule, schedule: schedule

            expect(assigns(:schedule).errors['variables.key']).not_to be_empty
          end
        end
271 272
      end

273 274 275 276
      context 'when a pipeline schedule has one variable' do
        let(:basic_param) do
          { description: 'updated_desc', cron: '0 1 * * *', cron_timezone: 'UTC', ref: 'patch-x', active: '1' }
        end
277

278
        let!(:pipeline_schedule_variable) do
279 280
          create(:ci_pipeline_schedule_variable,
            key: 'CCC', pipeline_schedule: pipeline_schedule)
281
        end
282

283 284 285 286
        context 'when params do not include variables' do
          let(:schedule) { basic_param }

          it 'updates only scheduled pipeline attributes' do
Shinya Maeda's avatar
Shinya Maeda committed
287
            go
288

289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
            pipeline_schedule.reload
            expect(response).to have_http_status(:found)
            expect(pipeline_schedule.description).to eq('updated_desc')
            expect(pipeline_schedule.cron).to eq('0 1 * * *')
            expect(pipeline_schedule.cron_timezone).to eq('UTC')
            expect(pipeline_schedule.ref).to eq('patch-x')
            expect(pipeline_schedule.active).to eq(true)
            expect(pipeline_schedule.variables.count).to eq(1)
            expect(pipeline_schedule.variables.last.key).to eq('CCC')
          end
        end

        context 'when params include one variable' do
          context 'when adds a new variable' do
            let(:schedule) do
              basic_param.merge({
305
                variables_attributes: [{ key: 'AAA', value: 'AAA123' }]
306 307 308 309
              })
            end

            it 'adds the new variable' do
Shinya Maeda's avatar
Shinya Maeda committed
310
              expect { go }.to change { Ci::PipelineScheduleVariable.count }.by(1)
311

312
              pipeline_schedule.reload
313 314 315 316 317 318 319
              expect(pipeline_schedule.variables.last.key).to eq('AAA')
            end
          end

          context 'when updates a variable' do
            let(:schedule) do
              basic_param.merge({
320
                variables_attributes: [{ id: pipeline_schedule_variable.id, value: 'new_value' }]
321 322 323 324
              })
            end

            it 'updates the variable' do
Shinya Maeda's avatar
Shinya Maeda committed
325
              expect { go }.not_to change { Ci::PipelineScheduleVariable.count }
326 327 328 329 330 331 332 333 334

              pipeline_schedule_variable.reload
              expect(pipeline_schedule_variable.value).to eq('new_value')
            end
          end

          context 'when deletes a variable' do
            let(:schedule) do
              basic_param.merge({
335
                variables_attributes: [{ id: pipeline_schedule_variable.id, _destroy: true }]
336 337 338 339
              })
            end

            it 'delete the existsed variable' do
Shinya Maeda's avatar
Shinya Maeda committed
340
              expect { go }.to change { Ci::PipelineScheduleVariable.count }.by(-1)
341 342 343
            end
          end
        end
344 345
      end
    end
346

347
    describe 'security' do
348 349 350 351 352
      let(:schedule) { { description: 'updated_desc' } }

      it { expect { go }.to be_allowed_for(:admin) }
      it { expect { go }.to be_allowed_for(:owner).of(project) }
      it { expect { go }.to be_allowed_for(:master).of(project) }
353
      it { expect { go }.to be_allowed_for(:developer).of(project).own([pipeline_schedule]) }
354 355 356 357 358 359
      it { expect { go }.to be_denied_for(:reporter).of(project) }
      it { expect { go }.to be_denied_for(:guest).of(project) }
      it { expect { go }.to be_denied_for(:user) }
      it { expect { go }.to be_denied_for(:external) }
      it { expect { go }.to be_denied_for(:visitor) }

360 361 362 363 364 365
      context 'when a developer created a pipeline schedule' do
        let(:developer_1) { create(:user) }
        let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: developer_1) }

        before do
          project.add_developer(developer_1)
366
        end
367

368 369 370
        it { expect { go }.to be_allowed_for(developer_1) }
        it { expect { go }.to be_denied_for(:developer).of(project) }
        it { expect { go }.to be_allowed_for(:master).of(project) }
371
      end
372

373 374 375 376 377 378 379 380
      context 'when a master created a pipeline schedule' do
        let(:master_1) { create(:user) }
        let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project, owner: master_1) }

        before do
          project.add_master(master_1)
        end

381 382 383
        it { expect { go }.to be_allowed_for(master_1) }
        it { expect { go }.to be_allowed_for(:master).of(project) }
        it { expect { go }.to be_denied_for(:developer).of(project) }
384
      end
385
    end
Shinya Maeda's avatar
Shinya Maeda committed
386 387 388 389

    def go
      put :update, namespace_id: project.namespace.to_param,
                   project_id: project, id: pipeline_schedule,
390
                   schedule: schedule
Shinya Maeda's avatar
Shinya Maeda committed
391
    end
392
  end
393

394 395 396
  describe 'GET #edit' do
    describe 'functionality' do
      let(:user) { create(:user) }
397

398 399 400 401 402 403 404 405 406 407 408 409
      before do
        project.add_master(user)
        sign_in(user)
      end

      it 'loads the pipeline schedule' do
        get :edit, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id

        expect(response).to have_http_status(:ok)
        expect(assigns(:schedule)).to eq(pipeline_schedule)
      end
    end
410

411 412 413 414
    describe 'security' do
      it { expect { go }.to be_allowed_for(:admin) }
      it { expect { go }.to be_allowed_for(:owner).of(project) }
      it { expect { go }.to be_allowed_for(:master).of(project) }
415
      it { expect { go }.to be_allowed_for(:developer).of(project).own([pipeline_schedule]) }
416 417 418 419 420
      it { expect { go }.to be_denied_for(:reporter).of(project) }
      it { expect { go }.to be_denied_for(:guest).of(project) }
      it { expect { go }.to be_denied_for(:user) }
      it { expect { go }.to be_denied_for(:external) }
      it { expect { go }.to be_denied_for(:visitor) }
421 422
    end

423
    def go
424
      get :edit, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
425 426
    end
  end
427

428 429 430 431 432
  describe 'GET #take_ownership' do
    describe 'security' do
      it { expect { go }.to be_allowed_for(:admin) }
      it { expect { go }.to be_allowed_for(:owner).of(project) }
      it { expect { go }.to be_allowed_for(:master).of(project) }
433
      it { expect { go }.to be_allowed_for(:developer).of(project).own([pipeline_schedule]) }
434 435 436 437 438 439 440 441 442
      it { expect { go }.to be_denied_for(:reporter).of(project) }
      it { expect { go }.to be_denied_for(:guest).of(project) }
      it { expect { go }.to be_denied_for(:user) }
      it { expect { go }.to be_denied_for(:external) }
      it { expect { go }.to be_denied_for(:visitor) }
    end

    def go
      post :take_ownership, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
443 444 445
    end
  end

446 447
  describe 'DELETE #destroy' do
    set(:user) { create(:user) }
448

449 450 451 452
    context 'when a developer makes the request' do
      before do
        project.add_developer(user)
        sign_in(user)
453

454
        delete :destroy, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
455
      end
Shinya Maeda's avatar
Shinya Maeda committed
456

457 458 459
      it 'does not delete the pipeline schedule' do
        expect(response).not_to have_http_status(:ok)
      end
Shinya Maeda's avatar
Shinya Maeda committed
460
    end
461

462
    context 'when a master makes the request' do
463 464 465 466 467
      before do
        project.add_master(user)
        sign_in(user)
      end

468 469 470 471
      it 'destroys the pipeline schedule' do
        expect do
          delete :destroy, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id
        end.to change { project.pipeline_schedules.count }.by(-1)
472

473
        expect(response).to have_http_status(302)
474 475
      end
    end
476
  end
477
end