todo_service_spec.rb 27.5 KB
Newer Older
1 2 3 4
require 'spec_helper'

describe TodoService, services: true do
  let(:author) { create(:user) }
5 6 7
  let(:assignee) { create(:user) }
  let(:non_member) { create(:user) }
  let(:member) { create(:user) }
8
  let(:guest) { create(:user) }
9 10
  let(:admin) { create(:admin) }
  let(:john_doe) { create(:user) }
11
  let(:project) { create(:project) }
12
  let(:mentions) { [author, assignee, john_doe, member, guest, non_member, admin].map(&:to_reference).join(' ') }
13 14 15
  let(:service) { described_class.new }

  before do
16
    project.team << [guest, :guest]
17
    project.team << [author, :developer]
18
    project.team << [member, :developer]
19 20 21 22
    project.team << [john_doe, :developer]
  end

  describe 'Issues' do
23
    let(:issue) { create(:issue, project: project, assignee: john_doe, author: author, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
24
    let(:unassigned_issue) { create(:issue, project: project, assignee: nil) }
25
    let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee, description: mentions) }
26 27 28 29 30 31 32 33 34 35 36 37

    describe '#new_issue' do
      it 'creates a todo if assigned' do
        service.new_issue(issue, author)

        should_create_todo(user: john_doe, target: issue, action: Todo::ASSIGNED)
      end

      it 'does not create a todo if unassigned' do
        should_not_create_any_todo { service.new_issue(unassigned_issue, author) }
      end

38 39 40 41 42
      it 'creates a todo if assignee is the current user' do
        unassigned_issue.update_attribute(:assignee, john_doe)
        service.new_issue(unassigned_issue, john_doe)

        should_create_todo(user: john_doe, target: unassigned_issue, author: john_doe, action: Todo::ASSIGNED)
43 44 45 46 47
      end

      it 'creates a todo for each valid mentioned user' do
        service.new_issue(issue, author)

48
        should_create_todo(user: member, target: issue, action: Todo::MENTIONED)
49
        should_create_todo(user: guest, target: issue, action: Todo::MENTIONED)
50
        should_create_todo(user: author, target: issue, action: Todo::MENTIONED)
51
        should_not_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED)
52 53 54
        should_not_create_todo(user: non_member, target: issue, action: Todo::MENTIONED)
      end

55
      it 'does not create todo if user can not see the issue when issue is confidential' do
56 57 58 59 60 61
        service.new_issue(confidential_issue, john_doe)

        should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::ASSIGNED)
        should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
        should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
        should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
62
        should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
63
        should_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
64
      end
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

      context 'when a private group is mentioned' do
        let(:group) { create :group, :private }
        let(:project) { create :project, :private, group: group }
        let(:issue) { create :issue, author: author, project: project, description: group.to_reference }

        before do
          group.add_owner(author)
          group.add_user(member, Gitlab::Access::DEVELOPER)
          group.add_user(john_doe, Gitlab::Access::DEVELOPER)

          service.new_issue(issue, author)
        end

        it 'creates a todo for group members' do
          should_create_todo(user: member, target: issue)
          should_create_todo(user: john_doe, target: issue)
        end
      end
84 85 86 87 88 89
    end

    describe '#update_issue' do
      it 'creates a todo for each valid mentioned user' do
        service.update_issue(issue, author)

90
        should_create_todo(user: member, target: issue, action: Todo::MENTIONED)
91
        should_create_todo(user: guest, target: issue, action: Todo::MENTIONED)
92
        should_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED)
93
        should_create_todo(user: author, target: issue, action: Todo::MENTIONED)
94
        should_not_create_todo(user: non_member, target: issue, action: Todo::MENTIONED)
95 96 97
      end

      it 'does not create a todo if user was already mentioned' do
98
        create(:todo, :mentioned, user: member, project: project, target: issue, author: author)
99

100 101 102
        expect { service.update_issue(issue, author) }.not_to change(member.todos, :count)
      end

103
      it 'does not create todo if user can not see the issue when issue is confidential' do
104 105 106 107 108 109
        service.update_issue(confidential_issue, john_doe)

        should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
        should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
        should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
        should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
110
        should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
111
        should_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED)
112
      end
113

114 115 116 117 118 119 120 121 122 123 124 125 126
      context 'issues with a task list' do
        it 'does not create todo when tasks are marked as completed' do
          issue.update(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")

          service.update_issue(issue, author)

          should_not_create_todo(user: admin, target: issue, action: Todo::MENTIONED)
          should_not_create_todo(user: assignee, target: issue, action: Todo::MENTIONED)
          should_not_create_todo(user: author, target: issue, action: Todo::MENTIONED)
          should_not_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED)
          should_not_create_todo(user: member, target: issue, action: Todo::MENTIONED)
          should_not_create_todo(user: non_member, target: issue, action: Todo::MENTIONED)
        end
127

128 129
        it 'does not raise an error when description not change' do
          issue.update(title: 'Sample')
130

131 132
          expect { service.update_issue(issue, author) }.not_to raise_error
        end
133
      end
134 135 136 137 138 139 140 141 142 143 144 145 146 147
    end

    describe '#close_issue' do
      it 'marks related pending todos to the target for the user as done' do
        first_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)
        second_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)

        service.close_issue(issue, john_doe)

        expect(first_todo.reload).to be_done
        expect(second_todo.reload).to be_done
      end
    end

148 149 150 151 152 153 154 155
    describe '#destroy_issue' do
      it 'refresh the todos count cache for the user' do
        expect(john_doe).to receive(:update_todos_count_cache).and_call_original

        service.destroy_issue(issue, john_doe)
      end
    end

156 157 158 159 160 161 162 163 164 165 166 167 168 169
    describe '#reassigned_issue' do
      it 'creates a pending todo for new assignee' do
        unassigned_issue.update_attribute(:assignee, john_doe)
        service.reassigned_issue(unassigned_issue, author)

        should_create_todo(user: john_doe, target: unassigned_issue, action: Todo::ASSIGNED)
      end

      it 'does not create a todo if unassigned' do
        issue.update_attribute(:assignee, nil)

        should_not_create_any_todo { service.reassigned_issue(issue, author) }
      end

170
      it 'creates a todo if new assignee is the current user' do
171
        unassigned_issue.update_attribute(:assignee, john_doe)
172
        service.reassigned_issue(unassigned_issue, john_doe)
173

174
        should_create_todo(user: john_doe, target: unassigned_issue, author: john_doe, action: Todo::ASSIGNED)
175 176 177 178 179 180 181 182 183 184 185 186 187
      end
    end

    describe '#mark_pending_todos_as_done' do
      it 'marks related pending todos to the target for the user as done' do
        first_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)
        second_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)

        service.mark_pending_todos_as_done(issue, john_doe)

        expect(first_todo.reload).to be_done
        expect(second_todo.reload).to be_done
      end
P
Paco Guzman 已提交
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

      describe 'cached counts' do
        it 'updates when todos change' do
          create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)

          expect(john_doe.todos_done_count).to eq(0)
          expect(john_doe.todos_pending_count).to eq(1)
          expect(john_doe).to receive(:update_todos_count_cache).and_call_original

          service.mark_pending_todos_as_done(issue, john_doe)

          expect(john_doe.todos_done_count).to eq(1)
          expect(john_doe.todos_pending_count).to eq(0)
        end
      end
    end

205 206 207
    shared_examples 'marking todos as done' do |meth|
      let!(:first_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) }
      let!(:second_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) }
P
Paco Guzman 已提交
208

209 210
      it 'marks related todos for the user as done' do
        service.send(meth, collection, john_doe)
P
Paco Guzman 已提交
211 212 213 214 215 216 217 218

        expect(first_todo.reload).to be_done
        expect(second_todo.reload).to be_done
      end

      describe 'cached counts' do
        it 'updates when todos change' do
          expect(john_doe.todos_done_count).to eq(0)
219
          expect(john_doe.todos_pending_count).to eq(2)
P
Paco Guzman 已提交
220 221
          expect(john_doe).to receive(:update_todos_count_cache).and_call_original

222
          service.send(meth, collection, john_doe)
P
Paco Guzman 已提交
223

224
          expect(john_doe.todos_done_count).to eq(2)
P
Paco Guzman 已提交
225 226 227
          expect(john_doe.todos_pending_count).to eq(0)
        end
      end
228 229
    end

230 231 232 233 234 235
    describe '#mark_todos_as_done' do
      it_behaves_like 'marking todos as done', :mark_todos_as_done do
        let(:collection) { [first_todo, second_todo] }
      end
    end

236 237
    describe '#mark_todos_as_done_by_ids' do
      it_behaves_like 'marking todos as done', :mark_todos_as_done_by_ids do
238 239 240 241
        let(:collection) { [first_todo, second_todo].map(&:id) }
      end
    end

242 243 244
    describe '#new_note' do
      let!(:first_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) }
      let!(:second_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) }
245
      let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignee: assignee) }
246
      let(:note) { create(:note, project: project, noteable: issue, author: john_doe, note: mentions) }
247
      let(:note_on_commit) { create(:note_on_commit, project: project, author: john_doe, note: mentions) }
248
      let(:note_on_confidential_issue) { create(:note_on_issue, noteable: confidential_issue, project: project, note: mentions) }
249
      let(:note_on_project_snippet) { create(:note_on_project_snippet, project: project, author: john_doe, note: mentions) }
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
      let(:system_note) { create(:system_note, project: project, noteable: issue) }

      it 'mark related pending todos to the noteable for the note author as done' do
        first_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)
        second_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author)

        service.new_note(note, john_doe)

        expect(first_todo.reload).to be_done
        expect(second_todo.reload).to be_done
      end

      it 'does not mark related pending todos it is a system note' do
        service.new_note(system_note, john_doe)

        expect(first_todo.reload).to be_pending
        expect(second_todo.reload).to be_pending
      end

      it 'creates a todo for each valid mentioned user' do
        service.new_note(note, john_doe)

272
        should_create_todo(user: member, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
273
        should_create_todo(user: guest, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
274
        should_create_todo(user: author, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
275
        should_create_todo(user: john_doe, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
276 277 278
        should_not_create_todo(user: non_member, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
      end

279
      it 'does not create todo if user can not see the issue when leaving a note on a confidential issue' do
280 281 282 283 284 285
        service.new_note(note_on_confidential_issue, john_doe)

        should_create_todo(user: author, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
        should_create_todo(user: assignee, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
        should_create_todo(user: member, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
        should_create_todo(user: admin, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
286
        should_not_create_todo(user: guest, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
287
        should_create_todo(user: john_doe, target: confidential_issue, author: john_doe, action: Todo::MENTIONED, note: note_on_confidential_issue)
288
      end
289

290 291 292
      it 'creates a todo for each valid mentioned user when leaving a note on commit' do
        service.new_note(note_on_commit, john_doe)

293
        should_create_todo(user: member, target_id: nil, target_type: 'Commit', commit_id: note_on_commit.commit_id, author: john_doe, action: Todo::MENTIONED, note: note_on_commit)
294
        should_create_todo(user: author, target_id: nil, target_type: 'Commit', commit_id: note_on_commit.commit_id, author: john_doe, action: Todo::MENTIONED, note: note_on_commit)
295
        should_create_todo(user: john_doe, target_id: nil, target_type: 'Commit', commit_id: note_on_commit.commit_id, author: john_doe, action: Todo::MENTIONED, note: note_on_commit)
296
        should_not_create_todo(user: non_member, target_id: nil, target_type: 'Commit', commit_id: note_on_commit.commit_id, author: john_doe, action: Todo::MENTIONED, note: note_on_commit)
297 298 299 300 301
      end

      it 'does not create todo when leaving a note on snippet' do
        should_not_create_any_todo { service.new_note(note_on_project_snippet, john_doe) }
      end
302
    end
P
Phil Hughes 已提交
303 304 305 306 307 308 309 310

    describe '#mark_todo' do
      it 'creates a todo from a issue' do
        service.mark_todo(unassigned_issue, author)

        should_create_todo(user: author, target: unassigned_issue, action: Todo::MARKED)
      end
    end
311 312 313 314 315 316 317 318 319 320 321 322

    describe '#todo_exists?' do
      it 'returns false when no todo exist for the given issuable' do
        expect(service.todo_exist?(unassigned_issue, author)).to be_falsy
      end

      it 'returns true when a todo exist for the given issuable' do
        service.mark_todo(unassigned_issue, author)

        expect(service.todo_exist?(unassigned_issue, author)).to be_truthy
      end
    end
323 324 325
  end

  describe 'Merge Requests' do
326
    let(:mr_assigned) { create(:merge_request, source_project: project, author: author, assignee: john_doe, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") }
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
    let(:mr_unassigned) { create(:merge_request, source_project: project, author: author, assignee: nil) }

    describe '#new_merge_request' do
      it 'creates a pending todo if assigned' do
        service.new_merge_request(mr_assigned, author)

        should_create_todo(user: john_doe, target: mr_assigned, action: Todo::ASSIGNED)
      end

      it 'does not create a todo if unassigned' do
        should_not_create_any_todo { service.new_merge_request(mr_unassigned, author) }
      end

      it 'does not create a todo if assignee is the current user' do
        should_not_create_any_todo { service.new_merge_request(mr_unassigned, john_doe) }
      end

      it 'creates a todo for each valid mentioned user' do
        service.new_merge_request(mr_assigned, author)

347
        should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED)
V
Valery Sizov 已提交
348
        should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
349
        should_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED)
350
        should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED)
351
        should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED)
352 353 354 355 356 357 358
      end
    end

    describe '#update_merge_request' do
      it 'creates a todo for each valid mentioned user' do
        service.update_merge_request(mr_assigned, author)

359
        should_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED)
V
Valery Sizov 已提交
360
        should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
361
        should_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED)
362
        should_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED)
363
        should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED)
364 365 366
      end

      it 'does not create a todo if user was already mentioned' do
367
        create(:todo, :mentioned, user: member, project: project, target: mr_assigned, author: author)
368

369
        expect { service.update_merge_request(mr_assigned, author) }.not_to change(member.todos, :count)
370
      end
371

372 373 374
      context 'with a task list' do
        it 'does not create todo when tasks are marked as completed' do
          mr_assigned.update(description: "- [x] Task 1\n- [X] Task 2 #{mentions}")
375

376
          service.update_merge_request(mr_assigned, author)
377

378 379 380 381 382 383
          should_not_create_todo(user: admin, target: mr_assigned, action: Todo::MENTIONED)
          should_not_create_todo(user: assignee, target: mr_assigned, action: Todo::MENTIONED)
          should_not_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED)
          should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED)
          should_not_create_todo(user: member, target: mr_assigned, action: Todo::MENTIONED)
          should_not_create_todo(user: non_member, target: mr_assigned, action: Todo::MENTIONED)
V
Valery Sizov 已提交
384
          should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
385 386 387 388 389 390 391
        end

        it 'does not raise an error when description not change' do
          mr_assigned.update(title: 'Sample')

          expect { service.update_merge_request(mr_assigned, author) }.not_to raise_error
        end
392
      end
393 394 395 396 397 398 399 400 401 402 403 404 405
    end

    describe '#close_merge_request' do
      it 'marks related pending todos to the target for the user as done' do
        first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
        second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
        service.close_merge_request(mr_assigned, john_doe)

        expect(first_todo.reload).to be_done
        expect(second_todo.reload).to be_done
      end
    end

406 407 408 409 410 411 412 413
    describe '#destroy_merge_request' do
      it 'refresh the todos count cache for the user' do
        expect(john_doe).to receive(:update_todos_count_cache).and_call_original

        service.destroy_merge_request(mr_assigned, john_doe)
      end
    end

414 415 416 417 418 419 420 421 422 423 424 425 426 427
    describe '#reassigned_merge_request' do
      it 'creates a pending todo for new assignee' do
        mr_unassigned.update_attribute(:assignee, john_doe)
        service.reassigned_merge_request(mr_unassigned, author)

        should_create_todo(user: john_doe, target: mr_unassigned, action: Todo::ASSIGNED)
      end

      it 'does not create a todo if unassigned' do
        mr_assigned.update_attribute(:assignee, nil)

        should_not_create_any_todo { service.reassigned_merge_request(mr_assigned, author) }
      end

428
      it 'creates a todo if new assignee is the current user' do
429
        mr_assigned.update_attribute(:assignee, john_doe)
430
        service.reassigned_merge_request(mr_assigned, john_doe)
431

432
        should_create_todo(user: john_doe, target: mr_assigned, author: john_doe, action: Todo::ASSIGNED)
433
      end
V
Valery Sizov 已提交
434 435 436 437 438

      it 'does not create a todo for guests' do
        service.reassigned_merge_request(mr_assigned, author)
        should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
      end
439 440 441 442 443 444 445 446 447 448 449
    end

    describe '#merge_merge_request' do
      it 'marks related pending todos to the target for the user as done' do
        first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
        second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author)
        service.merge_merge_request(mr_assigned, john_doe)

        expect(first_todo.reload).to be_done
        expect(second_todo.reload).to be_done
      end
V
Valery Sizov 已提交
450 451 452 453 454

      it 'does not create todo for guests' do
        service.merge_merge_request(mr_assigned, john_doe)
        should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
      end
455
    end
456 457 458 459 460 461 462 463 464

    describe '#new_award_emoji' do
      it 'marks related pending todos to the target for the user as done' do
        todo = create(:todo, user: john_doe, project: project, target: mr_assigned, author: author)
        service.new_award_emoji(mr_assigned, john_doe)

        expect(todo.reload).to be_done
      end
    end
465

466 467 468 469 470 471
    describe '#merge_request_build_failed' do
      it 'creates a pending todo for the merge request author' do
        service.merge_request_build_failed(mr_unassigned)

        should_create_todo(user: author, target: mr_unassigned, action: Todo::BUILD_FAILED)
      end
472 473 474 475 476 477 478

      it 'creates a pending todo for merge_user' do
        mr_unassigned.update(merge_when_build_succeeds: true, merge_user: admin)
        service.merge_request_build_failed(mr_unassigned)

        should_create_todo(user: admin, author: admin, target: mr_unassigned, action: Todo::BUILD_FAILED)
      end
479 480 481 482 483 484 485 486 487 488 489 490
    end

    describe '#merge_request_push' do
      it 'marks related pending todos to the target for the user as done' do
        first_todo = create(:todo, :build_failed, user: author, project: project, target: mr_assigned, author: john_doe)
        second_todo = create(:todo, :build_failed, user: john_doe, project: project, target: mr_assigned, author: john_doe)
        service.merge_request_push(mr_assigned, author)

        expect(first_todo.reload).to be_done
        expect(second_todo.reload).not_to be_done
      end
    end
P
Phil Hughes 已提交
491

492 493 494 495 496 497 498 499 500
    describe '#merge_request_became_unmergeable' do
      it 'creates a pending todo for a merge_user' do
        mr_unassigned.update(merge_when_build_succeeds: true, merge_user: admin)
        service.merge_request_became_unmergeable(mr_unassigned)

        should_create_todo(user: admin, author: admin, target: mr_unassigned, action: Todo::UNMERGEABLE)
      end
    end
    
P
Phil Hughes 已提交
501 502 503 504 505 506 507
    describe '#mark_todo' do
      it 'creates a todo from a merge request' do
        service.mark_todo(mr_unassigned, author)

        should_create_todo(user: author, target: mr_unassigned, action: Todo::MARKED)
      end
    end
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524

    describe '#new_note' do
      let(:mention) { john_doe.to_reference }
      let(:diff_note_on_merge_request) { create(:diff_note_on_merge_request, project: project, noteable: mr_unassigned, author: author, note: "Hey #{mention}") }
      let(:legacy_diff_note_on_merge_request) { create(:legacy_diff_note_on_merge_request, project: project, noteable: mr_unassigned, author: author, note: "Hey #{mention}") }

      it 'creates a todo for mentioned user on new diff note' do
        service.new_note(diff_note_on_merge_request, author)

        should_create_todo(user: john_doe, target: mr_unassigned, author: author, action: Todo::MENTIONED, note: diff_note_on_merge_request)
      end

      it 'creates a todo for mentioned user on legacy diff note' do
        service.new_note(legacy_diff_note_on_merge_request, author)

        should_create_todo(user: john_doe, target: mr_unassigned, author: author, action: Todo::MENTIONED, note: legacy_diff_note_on_merge_request)
      end
V
Valery Sizov 已提交
525 526 527 528 529 530 531

      it 'does not create todo for guests' do
        note_on_merge_request = create :note_on_merge_request, project: project, noteable: mr_assigned, note: mentions
        service.new_note(note_on_merge_request, author)

        should_not_create_todo(user: guest, target: mr_assigned, action: Todo::MENTIONED)
      end
532
    end
533 534
  end

P
Paco Guzman 已提交
535 536 537 538 539 540 541 542 543 544 545 546
  it 'updates cached counts when a todo is created' do
    issue = create(:issue, project: project, assignee: john_doe, author: author, description: mentions)

    expect(john_doe.todos_pending_count).to eq(0)
    expect(john_doe).to receive(:update_todos_count_cache)

    service.new_issue(issue, author)

    expect(Todo.where(user_id: john_doe.id, state: :pending).count).to eq 1
    expect(john_doe.todos_pending_count).to eq(1)
  end

547 548
  describe '#mark_todos_as_done' do
    let(:issue) { create(:issue, project: project, author: author, assignee: john_doe) }
549
    let(:another_issue) { create(:issue, project: project, author: author, assignee: john_doe) }
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571

    it 'marks a relation of todos as done' do
      create(:todo, :mentioned, user: john_doe, target: issue, project: project)

      todos = TodosFinder.new(john_doe, {}).execute
      expect { TodoService.new.mark_todos_as_done(todos, john_doe) }
       .to change { john_doe.todos.done.count }.from(0).to(1)
    end

    it 'marks an array of todos as done' do
      todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project)

      expect { TodoService.new.mark_todos_as_done([todo], john_doe) }
        .to change { todo.reload.state }.from('pending').to('done')
    end

    it 'returns the number of updated todos' do # Needed on API
      todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project)

      expect(TodoService.new.mark_todos_as_done([todo], john_doe)).to eq(1)
    end

572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
    context 'when some of the todos are done already' do
      before do
        create(:todo, :mentioned, user: john_doe, target: issue, project: project)
        create(:todo, :mentioned, user: john_doe, target: another_issue, project: project)
      end

      it 'returns the number of those still pending' do
        TodoService.new.mark_pending_todos_as_done(issue, john_doe)

        expect(TodoService.new.mark_todos_as_done(Todo.all, john_doe)).to eq(1)
      end

      it 'returns 0 if all are done' do
        TodoService.new.mark_pending_todos_as_done(issue, john_doe)
        TodoService.new.mark_pending_todos_as_done(another_issue, john_doe)

        expect(TodoService.new.mark_todos_as_done(Todo.all, john_doe)).to eq(0)
      end
    end

592 593 594 595 596 597 598 599 600 601 602 603
    it 'caches the number of todos of a user', :caching do
      create(:todo, :mentioned, user: john_doe, target: issue, project: project)
      todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project)
      TodoService.new.mark_todos_as_done([todo], john_doe)

      expect_any_instance_of(TodosFinder).not_to receive(:execute)

      expect(john_doe.todos_done_count).to eq(1)
      expect(john_doe.todos_pending_count).to eq(1)
    end
  end

604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
  def should_create_todo(attributes = {})
    attributes.reverse_merge!(
      project: project,
      author: author,
      state: :pending
    )

    expect(Todo.where(attributes).count).to eq 1
  end

  def should_not_create_todo(attributes = {})
    attributes.reverse_merge!(
      project: project,
      author: author,
      state: :pending
    )

    expect(Todo.where(attributes).count).to eq 0
  end

  def should_not_create_any_todo
    expect { yield }.not_to change(Todo, :count)
  end
end