diff options
Diffstat (limited to 'spec/services/todo_service_spec.rb')
-rw-r--r-- | spec/services/todo_service_spec.rb | 302 |
1 files changed, 126 insertions, 176 deletions
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb index 4894cf12372..f6e1608acbe 100644 --- a/spec/services/todo_service_spec.rb +++ b/spec/services/todo_service_spec.rb @@ -27,6 +27,39 @@ describe TodoService do project.add_developer(skipped) end + shared_examples 'reassigned target' do + it 'creates a pending todo for new assignee' do + target_unassigned.assignees = [john_doe] + service.send(described_method, target_unassigned, author) + + should_create_todo(user: john_doe, target: target_unassigned, action: Todo::ASSIGNED) + end + + it 'does not create a todo if unassigned' do + target_assigned.assignees = [] + + should_not_create_any_todo { service.send(described_method, target_assigned, author) } + end + + it 'creates a todo if new assignee is the current user' do + target_assigned.assignees = [john_doe] + service.send(described_method, target_assigned, john_doe) + + should_create_todo(user: john_doe, target: target_assigned, author: john_doe, action: Todo::ASSIGNED) + end + + it 'does not create a todo for guests' do + service.send(described_method, target_assigned, author) + should_not_create_todo(user: guest, target: target_assigned, action: Todo::MENTIONED) + end + + it 'does not create a directly addressed todo for guests' do + service.send(described_method, addressed_target_assigned, author) + + should_not_create_todo(user: guest, target: addressed_target_assigned, action: Todo::DIRECTLY_ADDRESSED) + end + end + describe 'Issues' do let(:issue) { create(:issue, project: project, assignees: [john_doe], author: author, description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") } let(:addressed_issue) { create(:issue, project: project, assignees: [john_doe], author: author, description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") } @@ -274,12 +307,12 @@ describe TodoService do end end - describe '#mark_pending_todos_as_done' do + describe '#resolve_todos_for_target' 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) + service.resolve_todos_for_target(issue, john_doe) expect(first_todo.reload).to be_done expect(second_todo.reload).to be_done @@ -293,7 +326,7 @@ describe TodoService do 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) + service.resolve_todos_for_target(issue, john_doe) expect(john_doe.todos_done_count).to eq(1) expect(john_doe.todos_pending_count).to eq(0) @@ -301,59 +334,6 @@ describe TodoService do end end - shared_examples 'updating todos state' do |meth, state, new_state| - let!(:first_todo) { create(:todo, state, user: john_doe, project: project, target: issue, author: author) } - let!(:second_todo) { create(:todo, state, user: john_doe, project: project, target: issue, author: author) } - - it 'updates related todos for the user with the new_state' do - service.send(meth, collection, john_doe) - - expect(first_todo.reload.state?(new_state)).to be true - expect(second_todo.reload.state?(new_state)).to be true - end - - it 'returns the updated ids' do - expect(service.send(meth, collection, john_doe)).to match_array([first_todo.id, second_todo.id]) - end - - describe 'cached counts' do - it 'updates when todos change' do - expect(john_doe.todos.where(state: new_state).count).to eq(0) - expect(john_doe.todos.where(state: state).count).to eq(2) - expect(john_doe).to receive(:update_todos_count_cache).and_call_original - - service.send(meth, collection, john_doe) - - expect(john_doe.todos.where(state: new_state).count).to eq(2) - expect(john_doe.todos.where(state: state).count).to eq(0) - end - end - end - - describe '#mark_todos_as_done' do - it_behaves_like 'updating todos state', :mark_todos_as_done, :pending, :done do - let(:collection) { Todo.all } - end - end - - describe '#mark_todos_as_done_by_ids' do - it_behaves_like 'updating todos state', :mark_todos_as_done_by_ids, :pending, :done do - let(:collection) { [first_todo, second_todo].map(&:id) } - end - end - - describe '#mark_todos_as_pending' do - it_behaves_like 'updating todos state', :mark_todos_as_pending, :done, :pending do - let(:collection) { Todo.all } - end - end - - describe '#mark_todos_as_pending_by_ids' do - it_behaves_like 'updating todos state', :mark_todos_as_pending_by_ids, :done, :pending do - let(:collection) { [first_todo, second_todo].map(&:id) } - end - end - 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) } @@ -575,51 +555,21 @@ describe TodoService do end describe '#reassigned_issuable' do - shared_examples 'reassigned issuable' do - it 'creates a pending todo for new assignee' do - issuable_unassigned.assignees = [john_doe] - service.reassigned_issuable(issuable_unassigned, author) - - should_create_todo(user: john_doe, target: issuable_unassigned, action: Todo::ASSIGNED) - end - - it 'does not create a todo if unassigned' do - issuable_assigned.assignees = [] - - should_not_create_any_todo { service.reassigned_issuable(issuable_assigned, author) } - end - - it 'creates a todo if new assignee is the current user' do - issuable_assigned.assignees = [john_doe] - service.reassigned_issuable(issuable_assigned, john_doe) - - should_create_todo(user: john_doe, target: issuable_assigned, author: john_doe, action: Todo::ASSIGNED) - end - - it 'does not create a todo for guests' do - service.reassigned_issuable(issuable_assigned, author) - should_not_create_todo(user: guest, target: issuable_assigned, action: Todo::MENTIONED) - end - - it 'does not create a directly addressed todo for guests' do - service.reassigned_issuable(addressed_issuable_assigned, author) - should_not_create_todo(user: guest, target: addressed_issuable_assigned, action: Todo::DIRECTLY_ADDRESSED) - end - end + let(:described_method) { :reassigned_issuable } context 'issuable is a merge request' do - it_behaves_like 'reassigned issuable' do - let(:issuable_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") } - let(:addressed_issuable_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") } - let(:issuable_unassigned) { create(:merge_request, source_project: project, author: author, assignees: []) } + it_behaves_like 'reassigned target' do + let(:target_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") } + let(:addressed_target_assigned) { create(:merge_request, source_project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") } + let(:target_unassigned) { create(:merge_request, source_project: project, author: author, assignees: []) } end end context 'issuable is an issue' do - it_behaves_like 'reassigned issuable' do - let(:issuable_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") } - let(:addressed_issuable_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") } - let(:issuable_unassigned) { create(:issue, project: project, author: author, assignees: []) } + it_behaves_like 'reassigned target' do + let(:target_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "- [ ] Task 1\n- [ ] Task 2 #{mentions}") } + let(:addressed_target_assigned) { create(:issue, project: project, author: author, assignees: [john_doe], description: "#{directly_addressed}\n- [ ] Task 1\n- [ ] Task 2") } + let(:target_unassigned) { create(:issue, project: project, author: author, assignees: []) } end end end @@ -809,6 +759,16 @@ describe TodoService do end end + describe '#assign_alert' do + let(:described_method) { :assign_alert } + + it_behaves_like 'reassigned target' do + let(:target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) } + let(:addressed_target_assigned) { create(:alert_management_alert, project: project, assignees: [john_doe]) } + let(:target_unassigned) { create(:alert_management_alert, project: project, assignees: []) } + end + end + describe '#merge_request_build_failed' do let(:merge_participants) { [mr_unassigned.author, admin] } @@ -1000,121 +960,111 @@ describe TodoService do expect(john_doe.todos_pending_count).to eq(1) end - describe '#mark_todos_as_done' do - let(:issue) { create(:issue, project: project, author: author, assignees: [john_doe]) } - let(:another_issue) { create(:issue, project: project, author: author, assignees: [john_doe]) } + shared_examples 'updating todos state' do |state, new_state, new_resolved_by = nil| + let!(:first_todo) { create(:todo, state, user: john_doe) } + let!(:second_todo) { create(:todo, state, user: john_doe) } + let(:collection) { Todo.all } - it 'marks a relation of todos as done' do - create(:todo, :mentioned, user: john_doe, target: issue, project: project) + it 'updates related todos for the user with the new_state' do + method_call - todos = TodosFinder.new(john_doe, {}).execute - expect { described_class.new.mark_todos_as_done(todos, john_doe) } - .to change { john_doe.todos.done.count }.from(0).to(1) + expect(collection.all? { |todo| todo.reload.state?(new_state)}).to be_truthy end - it 'marks an array of todos as done' do - todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) + if new_resolved_by + it 'updates resolution mechanism' do + method_call - todos = TodosFinder.new(john_doe, {}).execute - expect { described_class.new.mark_todos_as_done(todos, john_doe) } - .to change { todo.reload.state }.from('pending').to('done') + expect(collection.all? { |todo| todo.reload.resolved_by_action == new_resolved_by }).to be_truthy + end end - it 'returns the ids of updated todos' do # Needed on API - todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) - - todos = TodosFinder.new(john_doe, {}).execute - expect(described_class.new.mark_todos_as_done(todos, john_doe)).to eq([todo.id]) + it 'returns the updated ids' do + expect(method_call).to match_array([first_todo.id, second_todo.id]) end - context 'when some of the todos are done already' do - let!(:first_todo) { create(:todo, :mentioned, user: john_doe, target: issue, project: project) } - let!(:second_todo) { create(:todo, :mentioned, user: john_doe, target: another_issue, project: project) } - - it 'returns the ids of those still pending' do - described_class.new.mark_pending_todos_as_done(issue, john_doe) - - expect(described_class.new.mark_todos_as_done(Todo.all, john_doe)).to eq([second_todo.id]) - end + describe 'cached counts' do + it 'updates when todos change' do + expect(john_doe.todos.where(state: new_state).count).to eq(0) + expect(john_doe.todos.where(state: state).count).to eq(2) + expect(john_doe).to receive(:update_todos_count_cache).and_call_original - it 'returns an empty array if all are done' do - described_class.new.mark_pending_todos_as_done(issue, john_doe) - described_class.new.mark_pending_todos_as_done(another_issue, john_doe) + method_call - expect(described_class.new.mark_todos_as_done(Todo.all, john_doe)).to eq([]) + expect(john_doe.todos.where(state: new_state).count).to eq(2) + expect(john_doe.todos.where(state: state).count).to eq(0) end end end - describe '#mark_todo_as_done' do - it 'marks a todo done' do - todo1 = create(:todo, :pending, user: john_doe) - - described_class.new.mark_todo_as_done(todo1, john_doe) - - expect(todo1.reload.state).to eq('done') - end - - context 'when todo is already in state done' do - let(:todo1) { create(:todo, :done, user: john_doe) } - - it 'does not update the todo' do - expect { described_class.new.mark_todo_as_done(todo1, john_doe) }.not_to change(todo1.reload, :state) + describe '#resolve_todos' do + it_behaves_like 'updating todos state', :pending, :done, 'mark_done' do + subject(:method_call) do + service.resolve_todos(collection, john_doe, resolution: :done, resolved_by_action: :mark_done) end + end + end - it 'does not update cache count' do - expect(john_doe).not_to receive(:update_todos_count_cache) - - described_class.new.mark_todo_as_done(todo1, john_doe) + describe '#restore_todos' do + it_behaves_like 'updating todos state', :done, :pending do + subject(:method_call) do + service.restore_todos(collection, john_doe) end end end - describe '#mark_all_todos_as_done_by_user' do - it 'marks all todos done' do - todo1 = create(:todo, user: john_doe, state: :pending) - todo2 = create(:todo, user: john_doe, state: :done) - todo3 = create(:todo, user: john_doe, state: :pending) + describe '#resolve_todo' do + let!(:todo) { create(:todo, :assigned, user: john_doe) } - ids = described_class.new.mark_all_todos_as_done_by_user(john_doe) + it 'marks pending todo as done' do + expect do + service.resolve_todo(todo, john_doe) + todo.reload + end.to change { todo.done? }.to(true) + end - expect(ids).to contain_exactly(todo1.id, todo3.id) - expect(todo1.reload.state).to eq('done') - expect(todo2.reload.state).to eq('done') - expect(todo3.reload.state).to eq('done') + it 'saves resolution mechanism' do + expect do + service.resolve_todo(todo, john_doe, resolved_by_action: :mark_done) + todo.reload + end.to change { todo.resolved_by_mark_done? }.to(true) end - end - describe '#mark_todos_as_done_by_ids' do - let(:issue) { create(:issue, project: project, author: author, assignees: [john_doe]) } - let(:another_issue) { create(:issue, project: project, author: author, assignees: [john_doe]) } + context 'cached counts' do + it 'updates when todos change' do + 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 - it 'marks an array of todo ids as done' do - todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) - another_todo = create(:todo, :mentioned, user: john_doe, target: another_issue, project: project) + service.resolve_todo(todo, john_doe) - expect { described_class.new.mark_todos_as_done_by_ids([todo.id, another_todo.id], john_doe) } - .to change { john_doe.todos.done.count }.from(0).to(2) + expect(john_doe.todos_done_count).to eq(1) + expect(john_doe.todos_pending_count).to eq(0) + end end + end - it 'marks a single todo id as done' do - todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) + describe '#restore_todo' do + let!(:todo) { create(:todo, :done, user: john_doe) } - expect { described_class.new.mark_todos_as_done_by_ids(todo.id, john_doe) } - .to change { todo.reload.state }.from('pending').to('done') + it 'marks resolved todo as pending' do + expect do + service.restore_todo(todo, john_doe) + todo.reload + end.to change { todo.pending? }.to(true) end - it 'caches the number of todos of a user', :use_clean_rails_memory_store_caching do - create(:todo, :mentioned, user: john_doe, target: issue, project: project) - todo = create(:todo, :mentioned, user: john_doe, target: issue, project: project) + context 'cached counts' do + it 'updates when todos change' do + expect(john_doe.todos_done_count).to eq(1) + expect(john_doe.todos_pending_count).to eq(0) + expect(john_doe).to receive(:update_todos_count_cache).and_call_original - described_class.new.mark_todos_as_done_by_ids(todo, john_doe) + service.restore_todo(todo, john_doe) - # Make sure no TodosFinder is inialized to perform counting - expect(TodosFinder).not_to receive(:new) - - expect(john_doe.todos_done_count).to eq(1) - expect(john_doe.todos_pending_count).to eq(1) + expect(john_doe.todos_done_count).to eq(0) + expect(john_doe.todos_pending_count).to eq(1) + end end end |