diff options
author | Mark Fletcher <mark@gitlab.com> | 2017-05-29 08:49:17 +0300 |
---|---|---|
committer | Mark Fletcher <mark@gitlab.com> | 2017-06-06 15:16:41 +0300 |
commit | ad3e180ed3d99494414cb1b367f6b4e40ec28b87 (patch) | |
tree | 155c4e0f6b5529b3911a42ae2e8d5e80002c5a21 /spec | |
parent | e34e5761042579686fe149f16e7ec107b80224d2 (diff) |
Introduce an Events API
* Meld the following disparate endpoints:
* `/projects/:id/events`
* `/events`
* `/users/:id/events`
+ Add result filtering to the above endpoints:
* action
* target_type
* before and after dates
Diffstat (limited to 'spec')
-rw-r--r-- | spec/finders/events_finder_spec.rb | 44 | ||||
-rw-r--r-- | spec/requests/api/events_spec.rb | 133 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 58 | ||||
-rw-r--r-- | spec/requests/api/users_spec.rb | 77 |
4 files changed, 177 insertions, 135 deletions
diff --git a/spec/finders/events_finder_spec.rb b/spec/finders/events_finder_spec.rb new file mode 100644 index 00000000000..30a2bd14f10 --- /dev/null +++ b/spec/finders/events_finder_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe EventsFinder do + let(:user) { create(:user) } + let(:other_user) { create(:user) } + let(:project1) { create(:empty_project, :private, creator_id: user.id, namespace: user.namespace) } + let(:project2) { create(:empty_project, :private, creator_id: user.id, namespace: user.namespace) } + let(:closed_issue) { create(:closed_issue, project: project1, author: user) } + let(:opened_merge_request) { create(:merge_request, source_project: project2, author: user) } + let!(:closed_issue_event) { create(:event, project: project1, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 12, 30)) } + let!(:opened_merge_request_event) { create(:event, project: project2, author: user, target: opened_merge_request, action: Event::CREATED, created_at: Date.new(2017, 1, 31)) } + let(:closed_issue2) { create(:closed_issue, project: project1, author: user) } + let(:opened_merge_request2) { create(:merge_request, source_project: project2, author: user) } + let!(:closed_issue_event2) { create(:event, project: project1, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 2, 2)) } + let!(:opened_merge_request_event2) { create(:event, project: project2, author: user, target: opened_merge_request, action: Event::CREATED, created_at: Date.new(2017, 2, 2)) } + + context 'when targeting a user' do + it 'returns events between specified dates filtered on action and type' do + events = described_class.new(source: user, current_user: user, action: 'created', target_type: 'merge_request', after: Date.new(2017, 1, 1), before: Date.new(2017, 2, 1)).execute + + expect(events).to eq([opened_merge_request_event]) + end + + it 'does not return events the current_user does not have access to' do + events = described_class.new(source: user, current_user: other_user).execute + + expect(events).not_to include(opened_merge_request_event) + end + end + + context 'when targeting a project' do + it 'returns project events between specified dates filtered on action and type' do + events = described_class.new(source: project1, current_user: user, action: 'closed', target_type: 'issue', after: Date.new(2016, 12, 1), before: Date.new(2017, 1, 1)).execute + + expect(events).to eq([closed_issue_event]) + end + + it 'does not return events the current_user does not have access to' do + events = described_class.new(source: project2, current_user: other_user).execute + + expect(events).to be_empty + end + end +end diff --git a/spec/requests/api/events_spec.rb b/spec/requests/api/events_spec.rb new file mode 100644 index 00000000000..51e72c39a30 --- /dev/null +++ b/spec/requests/api/events_spec.rb @@ -0,0 +1,133 @@ +require 'spec_helper' + +describe API::Events, api: true do + include ApiHelpers + let(:user) { create(:user) } + let(:non_member) { create(:user) } + let(:other_user) { create(:user, username: 'otheruser') } + let(:private_project) { create(:empty_project, :private, creator_id: user.id, namespace: user.namespace) } + let(:closed_issue) { create(:closed_issue, project: private_project, author: user) } + let!(:closed_issue_event) { create(:event, project: private_project, author: user, target: closed_issue, action: Event::CLOSED, created_at: Date.new(2016, 12, 30)) } + + describe 'GET /events' do + context 'when unauthenticated' do + it 'returns authentication error' do + get api('/events') + + expect(response).to have_http_status(401) + end + end + + context 'when authenticated' do + it 'returns users events' do + get api('/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31', user) + + expect(response).to have_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.size).to eq(1) + end + end + end + + describe 'GET /users/:id/events' do + context "as a user that cannot see the event's project" do + it 'returns no events' do + get api("/users/#{user.id}/events", other_user) + + expect(response).to have_http_status(200) + expect(json_response).to be_empty + end + end + + context "as a user that can see the event's project" do + it 'returns the events' do + get api("/users/#{user.id}/events", user) + + expect(response).to have_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.size).to eq(1) + end + + context 'when there are multiple events from different projects' do + let(:second_note) { create(:note_on_issue, project: create(:empty_project)) } + + before do + second_note.project.add_user(user, :developer) + + [second_note].each do |note| + EventCreateService.new.leave_note(note, user) + end + end + + it 'returns events in the correct order (from newest to oldest)' do + get api("/users/#{user.id}/events", user) + + comment_events = json_response.select { |e| e['action_name'] == 'commented on' } + close_events = json_response.select { |e| e['action_name'] == 'closed' } + + expect(comment_events[0]['target_id']).to eq(second_note.id) + expect(close_events[0]['target_id']).to eq(closed_issue.id) + end + + it 'accepts filter parameters' do + get api("/users/#{user.id}/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31", user) + + expect(json_response.size).to eq(1) + expect(json_response[0]['target_id']).to eq(closed_issue.id) + end + end + end + + it 'returns a 404 error if not found' do + get api('/users/42/events', user) + + expect(response).to have_http_status(404) + expect(json_response['message']).to eq('404 User Not Found') + end + end + + describe 'GET /projects/:id/events' do + context 'when unauthenticated ' do + it 'returns 404 for private project' do + get api("/projects/#{private_project.id}/events") + + expect(response).to have_http_status(404) + end + + it 'returns 200 status for a public project' do + public_project = create(:empty_project, :public) + + get api("/projects/#{public_project.id}/events") + + expect(response).to have_http_status(200) + end + end + + context 'when not permitted to read' do + it 'returns 404' do + get api("/projects/#{private_project.id}/events", non_member) + + expect(response).to have_http_status(404) + end + end + + context 'when authenticated' do + it 'returns project events' do + get api("/projects/#{private_project.id}/events?action=closed&target_type=issue&after=2016-12-1&before=2016-12-31", user) + + expect(response).to have_http_status(200) + expect(response).to include_pagination_headers + expect(json_response).to be_an Array + expect(json_response.size).to eq(1) + end + + it 'returns 404 if project does not exist' do + get api("/projects/1234/events", user) + + expect(response).to have_http_status(404) + end + end + end +end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index c0ecb4d2aaa..86c57204971 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -762,64 +762,6 @@ describe API::Projects do end end - describe 'GET /projects/:id/events' do - shared_examples_for 'project events response' do - it 'returns the project events' do - member = create(:user) - create(:project_member, :developer, user: member, project: project) - note = create(:note_on_issue, note: 'What an awesome day!', project: project) - EventCreateService.new.leave_note(note, note.author) - - get api("/projects/#{project.id}/events", current_user) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - - first_event = json_response.first - expect(first_event['action_name']).to eq('commented on') - expect(first_event['note']['body']).to eq('What an awesome day!') - - last_event = json_response.last - - expect(last_event['action_name']).to eq('joined') - expect(last_event['project_id'].to_i).to eq(project.id) - expect(last_event['author_username']).to eq(member.username) - expect(last_event['author']['name']).to eq(member.name) - end - end - - context 'when unauthenticated' do - it_behaves_like 'project events response' do - let(:project) { create(:empty_project, :public) } - let(:current_user) { nil } - end - end - - context 'when authenticated' do - context 'valid request' do - it_behaves_like 'project events response' do - let(:current_user) { user } - end - end - - it 'returns a 404 error if not found' do - get api('/projects/42/events', user) - - expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 Project Not Found') - end - - it 'returns a 404 error if user is not a member' do - other_user = create(:user) - - get api("/projects/#{project.id}/events", other_user) - - expect(response).to have_http_status(404) - end - end - end - describe 'GET /projects/:id/users' do shared_examples_for 'project users response' do it 'returns the project users' do diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 1c33b8f9502..4efc3e1a1e2 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -1130,83 +1130,6 @@ describe API::Users do end end - describe 'GET /users/:id/events' do - let(:user) { create(:user) } - let(:project) { create(:empty_project) } - let(:note) { create(:note_on_issue, note: 'What an awesome day!', project: project) } - - before do - project.add_user(user, :developer) - EventCreateService.new.leave_note(note, user) - end - - context "as a user than cannot see the event's project" do - it 'returns no events' do - other_user = create(:user) - - get api("/users/#{user.id}/events", other_user) - - expect(response).to have_http_status(200) - expect(json_response).to be_empty - end - end - - context "as a user than can see the event's project" do - context 'joined event' do - it 'returns the "joined" event' do - get api("/users/#{user.id}/events", user) - - expect(response).to have_http_status(200) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - - comment_event = json_response.find { |e| e['action_name'] == 'commented on' } - - expect(comment_event['project_id'].to_i).to eq(project.id) - expect(comment_event['author_username']).to eq(user.username) - expect(comment_event['note']['id']).to eq(note.id) - expect(comment_event['note']['body']).to eq('What an awesome day!') - - joined_event = json_response.find { |e| e['action_name'] == 'joined' } - - expect(joined_event['project_id'].to_i).to eq(project.id) - expect(joined_event['author_username']).to eq(user.username) - expect(joined_event['author']['name']).to eq(user.name) - end - end - - context 'when there are multiple events from different projects' do - let(:second_note) { create(:note_on_issue, project: create(:empty_project)) } - let(:third_note) { create(:note_on_issue, project: project) } - - before do - second_note.project.add_user(user, :developer) - - [second_note, third_note].each do |note| - EventCreateService.new.leave_note(note, user) - end - end - - it 'returns events in the correct order (from newest to oldest)' do - get api("/users/#{user.id}/events", user) - - comment_events = json_response.select { |e| e['action_name'] == 'commented on' } - - expect(comment_events[0]['target_id']).to eq(third_note.id) - expect(comment_events[1]['target_id']).to eq(second_note.id) - expect(comment_events[2]['target_id']).to eq(note.id) - end - end - end - - it 'returns a 404 error if not found' do - get api('/users/42/events', user) - - expect(response).to have_http_status(404) - expect(json_response['message']).to eq('404 User Not Found') - end - end - context "user activities", :redis do let!(:old_active_user) { create(:user, last_activity_on: Time.utc(2000, 1, 1)) } let!(:newly_active_user) { create(:user, last_activity_on: 2.days.ago.midday) } |