summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorSean McGivern <sean@gitlab.com>2017-04-12 12:19:45 +0100
committerRémy Coutable <remy@rymai.me>2017-04-14 15:20:55 +0200
commit91ac0e038ab51dd2f30f2bb7c91837fa588ca250 (patch)
tree54b5ea7cb6115a09bbcead558252563664b4898c /spec
parent3cb84e06b7a118fb46b4e1e0d4885026c9d4a4d1 (diff)
downloadgitlab-ce-91ac0e038ab51dd2f30f2bb7c91837fa588ca250.tar.gz
Port 'Add user activities API' to CE
CE port of https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/962
Diffstat (limited to 'spec')
-rw-r--r--spec/lib/gitlab/pagination_delegate_spec.rb155
-rw-r--r--spec/lib/gitlab/user_activities/activity_set_spec.rb77
-rw-r--r--spec/lib/gitlab/user_activities/activity_spec.rb14
-rw-r--r--spec/requests/api/users_spec.rb76
-rw-r--r--spec/requests/api/users_spec.rb.rej124
5 files changed, 408 insertions, 38 deletions
diff --git a/spec/lib/gitlab/pagination_delegate_spec.rb b/spec/lib/gitlab/pagination_delegate_spec.rb
new file mode 100644
index 00000000000..3220d611274
--- /dev/null
+++ b/spec/lib/gitlab/pagination_delegate_spec.rb
@@ -0,0 +1,155 @@
+require 'spec_helper'
+
+describe Gitlab::PaginationDelegate, lib: true do
+ context 'no data' do
+ let(:delegate) do
+ described_class.new(page: 1,
+ per_page: 10,
+ count: 0)
+ end
+
+ it 'shows the correct total count' do
+ expect(delegate.total_count).to eq(0)
+ end
+
+ it 'shows the correct total pages' do
+ expect(delegate.total_pages).to eq(0)
+ end
+
+ it 'shows the correct next page' do
+ expect(delegate.next_page).to be_nil
+ end
+
+ it 'shows the correct previous page' do
+ expect(delegate.prev_page).to be_nil
+ end
+
+ it 'shows the correct current page' do
+ expect(delegate.current_page).to eq(1)
+ end
+
+ it 'shows the correct limit value' do
+ expect(delegate.limit_value).to eq(10)
+ end
+
+ it 'shows the correct first page' do
+ expect(delegate.first_page?).to be true
+ end
+
+ it 'shows the correct last page' do
+ expect(delegate.last_page?).to be true
+ end
+
+ it 'shows the correct offset' do
+ expect(delegate.offset).to eq(0)
+ end
+ end
+
+ context 'with data' do
+ let(:delegate) do
+ described_class.new(page: 5,
+ per_page: 100,
+ count: 1000)
+ end
+
+ it 'shows the correct total count' do
+ expect(delegate.total_count).to eq(1000)
+ end
+
+ it 'shows the correct total pages' do
+ expect(delegate.total_pages).to eq(10)
+ end
+
+ it 'shows the correct next page' do
+ expect(delegate.next_page).to eq(6)
+ end
+
+ it 'shows the correct previous page' do
+ expect(delegate.prev_page).to eq(4)
+ end
+
+ it 'shows the correct current page' do
+ expect(delegate.current_page).to eq(5)
+ end
+
+ it 'shows the correct limit value' do
+ expect(delegate.limit_value).to eq(100)
+ end
+
+ it 'shows the correct first page' do
+ expect(delegate.first_page?).to be false
+ end
+
+ it 'shows the correct last page' do
+ expect(delegate.last_page?).to be false
+ end
+
+ it 'shows the correct offset' do
+ expect(delegate.offset).to eq(400)
+ end
+ end
+
+ context 'last page' do
+ let(:delegate) do
+ described_class.new(page: 10,
+ per_page: 100,
+ count: 1000)
+ end
+
+ it 'shows the correct total count' do
+ expect(delegate.total_count).to eq(1000)
+ end
+
+ it 'shows the correct total pages' do
+ expect(delegate.total_pages).to eq(10)
+ end
+
+ it 'shows the correct next page' do
+ expect(delegate.next_page).to be_nil
+ end
+
+ it 'shows the correct previous page' do
+ expect(delegate.prev_page).to eq(9)
+ end
+
+ it 'shows the correct current page' do
+ expect(delegate.current_page).to eq(10)
+ end
+
+ it 'shows the correct limit value' do
+ expect(delegate.limit_value).to eq(100)
+ end
+
+ it 'shows the correct first page' do
+ expect(delegate.first_page?).to be false
+ end
+
+ it 'shows the correct last page' do
+ expect(delegate.last_page?).to be true
+ end
+
+ it 'shows the correct offset' do
+ expect(delegate.offset).to eq(900)
+ end
+ end
+
+ context 'limits and defaults' do
+ it 'has a maximum limit per page' do
+ expect(described_class.new(page: nil,
+ per_page: 1000,
+ count: 0).limit_value).to eq(described_class::MAX_PER_PAGE)
+ end
+
+ it 'has a default per page' do
+ expect(described_class.new(page: nil,
+ per_page: nil,
+ count: 0).limit_value).to eq(described_class::DEFAULT_PER_PAGE)
+ end
+
+ it 'has a maximum page' do
+ expect(described_class.new(page: 100,
+ per_page: 10,
+ count: 1).current_page).to eq(1)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/user_activities/activity_set_spec.rb b/spec/lib/gitlab/user_activities/activity_set_spec.rb
new file mode 100644
index 00000000000..56745bdf0d1
--- /dev/null
+++ b/spec/lib/gitlab/user_activities/activity_set_spec.rb
@@ -0,0 +1,77 @@
+require 'spec_helper'
+
+describe Gitlab::UserActivities::ActivitySet, :redis, lib: true do
+ let(:user) { create(:user) }
+
+ it 'shows the last user activity' do
+ Timecop.freeze do
+ user.record_activity
+
+ expect(described_class.new.activities.first).to be_an_instance_of(Gitlab::UserActivities::Activity)
+ end
+ end
+
+ context 'pagination delegation' do
+ let(:pagination_delegate) do
+ Gitlab::PaginationDelegate.new(page: 1,
+ per_page: 10,
+ count: 20)
+ end
+
+ let(:delegated_methods) { %i[total_count total_pages current_page limit_value first_page? prev_page last_page? next_page] }
+
+ before do
+ allow(described_class.new).to receive(:pagination_delegate).and_return(pagination_delegate)
+ end
+
+ it 'includes the delegated methods' do
+ expect(described_class.new.public_methods).to include(*delegated_methods)
+ end
+ end
+
+ context 'paginated activities' do
+ before do
+ Timecop.scale(3600)
+
+ 7.times do
+ create(:user).record_activity
+ end
+ end
+
+ after do
+ Timecop.return
+ end
+
+ it 'shows the 5 oldest user activities paginated' do
+ expect(described_class.new(per_page: 5).activities.count).to eq(5)
+ end
+
+ it 'shows the 2 reamining user activities paginated' do
+ expect(described_class.new(per_page: 5, page: 2).activities.count).to eq(2)
+ end
+
+ it 'shows the oldest first' do
+ activities = described_class.new.activities
+
+ expect(activities.first.last_activity_at).to be < activities.last.last_activity_at
+ end
+ end
+
+ context 'filter by date' do
+ before do
+ create(:user).record_activity
+ end
+
+ it 'shows activities from today' do
+ today = Date.today.to_s("%Y-%m-%d")
+
+ expect(described_class.new(from: today).activities.count).to eq(1)
+ end
+
+ it 'filter activities from tomorrow' do
+ tomorrow = Date.tomorrow.to_s("%Y-%m-%d")
+
+ expect(described_class.new(from: tomorrow).activities.count).to eq(0)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/user_activities/activity_spec.rb b/spec/lib/gitlab/user_activities/activity_spec.rb
new file mode 100644
index 00000000000..6a1150f50c1
--- /dev/null
+++ b/spec/lib/gitlab/user_activities/activity_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe Gitlab::UserActivities::Activity, :redis, lib: true do
+ let(:username) { 'user' }
+ let(:activity) { described_class.new('user', Time.new(2016, 12, 12).to_i) }
+
+ it 'has the username' do
+ expect(activity.username).to eq(username)
+ end
+
+ it 'has the last activity at' do
+ expect(activity.last_activity_at).to eq('2016-12-12 00:00:00')
+ end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index f793c0db2f3..a4e8d8e4156 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1,12 +1,12 @@
require 'spec_helper'
-describe API::Users, api: true do
+describe API::Users, api: true do
include ApiHelpers
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
let(:admin) { create(:admin) }
- let(:key) { create(:key, user: user) }
- let(:email) { create(:email, user: user) }
+ let(:key) { create(:key, user: user) }
+ let(:email) { create(:email, user: user) }
let(:omniauth_user) { create(:omniauth_user) }
let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain') }
let(:ldap_blocked_user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') }
@@ -129,7 +129,7 @@ describe API::Users, api: true do
end
describe "POST /users" do
- before{ admin }
+ before { admin }
it "creates user" do
expect do
@@ -214,9 +214,9 @@ describe API::Users, api: true do
it "does not create user with invalid email" do
post api('/users', admin),
- email: 'invalid email',
- password: 'password',
- name: 'test'
+ email: 'invalid email',
+ password: 'password',
+ name: 'test'
expect(response).to have_http_status(400)
end
@@ -242,12 +242,12 @@ describe API::Users, api: true do
it 'returns 400 error if user does not validate' do
post api('/users', admin),
- password: 'pass',
- email: 'test@example.com',
- username: 'test!',
- name: 'test',
- bio: 'g' * 256,
- projects_limit: -1
+ password: 'pass',
+ email: 'test@example.com',
+ username: 'test!',
+ name: 'test',
+ bio: 'g' * 256,
+ projects_limit: -1
expect(response).to have_http_status(400)
expect(json_response['message']['password']).
to eq(['is too short (minimum is 8 characters)'])
@@ -267,19 +267,19 @@ describe API::Users, api: true do
context 'with existing user' do
before do
post api('/users', admin),
- email: 'test@example.com',
- password: 'password',
- username: 'test',
- name: 'foo'
+ email: 'test@example.com',
+ password: 'password',
+ username: 'test',
+ name: 'foo'
end
it 'returns 409 conflict error if user with same email exists' do
expect do
post api('/users', admin),
- name: 'foo',
- email: 'test@example.com',
- password: 'password',
- username: 'foo'
+ name: 'foo',
+ email: 'test@example.com',
+ password: 'password',
+ username: 'foo'
end.to change { User.count }.by(0)
expect(response).to have_http_status(409)
expect(json_response['message']).to eq('Email has already been taken')
@@ -288,10 +288,10 @@ describe API::Users, api: true do
it 'returns 409 conflict error if same username exists' do
expect do
post api('/users', admin),
- name: 'foo',
- email: 'foo@example.com',
- password: 'password',
- username: 'test'
+ name: 'foo',
+ email: 'foo@example.com',
+ password: 'password',
+ username: 'test'
end.to change { User.count }.by(0)
expect(response).to have_http_status(409)
expect(json_response['message']).to eq('Username has already been taken')
@@ -416,12 +416,12 @@ describe API::Users, api: true do
it 'returns 400 error if user does not validate' do
put api("/users/#{user.id}", admin),
- password: 'pass',
- email: 'test@example.com',
- username: 'test!',
- name: 'test',
- bio: 'g' * 256,
- projects_limit: -1
+ password: 'pass',
+ email: 'test@example.com',
+ username: 'test!',
+ name: 'test',
+ bio: 'g' * 256,
+ projects_limit: -1
expect(response).to have_http_status(400)
expect(json_response['message']['password']).
to eq(['is too short (minimum is 8 characters)'])
@@ -488,7 +488,7 @@ describe API::Users, api: true do
key_attrs = attributes_for :key
expect do
post api("/users/#{user.id}/keys", admin), key_attrs
- end.to change{ user.keys.count }.by(1)
+ end.to change { user.keys.count }.by(1)
end
it "returns 400 for invalid ID" do
@@ -580,7 +580,7 @@ describe API::Users, api: true do
email_attrs = attributes_for :email
expect do
post api("/users/#{user.id}/emails", admin), email_attrs
- end.to change{ user.emails.count }.by(1)
+ end.to change { user.emails.count }.by(1)
end
it "returns a 400 for invalid ID" do
@@ -842,7 +842,7 @@ describe API::Users, api: true do
key_attrs = attributes_for :key
expect do
post api("/user/keys", user), key_attrs
- end.to change{ user.keys.count }.by(1)
+ end.to change { user.keys.count }.by(1)
expect(response).to have_http_status(201)
end
@@ -880,7 +880,7 @@ describe API::Users, api: true do
delete api("/user/keys/#{key.id}", user)
expect(response).to have_http_status(204)
- end.to change{user.keys.count}.by(-1)
+ end.to change { user.keys.count}.by(-1)
end
it "returns 404 if key ID not found" do
@@ -963,7 +963,7 @@ describe API::Users, api: true do
email_attrs = attributes_for :email
expect do
post api("/user/emails", user), email_attrs
- end.to change{ user.emails.count }.by(1)
+ end.to change { user.emails.count }.by(1)
expect(response).to have_http_status(201)
end
@@ -989,7 +989,7 @@ describe API::Users, api: true do
delete api("/user/emails/#{email.id}", user)
expect(response).to have_http_status(204)
- end.to change{user.emails.count}.by(-1)
+ end.to change { user.emails.count}.by(-1)
end
it "returns 404 if email ID not found" do
diff --git a/spec/requests/api/users_spec.rb.rej b/spec/requests/api/users_spec.rb.rej
new file mode 100644
index 00000000000..f7ade32ce42
--- /dev/null
+++ b/spec/requests/api/users_spec.rb.rej
@@ -0,0 +1,124 @@
+diff a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb (rejected hunks)
+@@ -1,12 +1,12 @@
+ require 'spec_helper'
+
+-describe API::Users, api: true do
++describe API::Users, api: true do
+ include ApiHelpers
+
+- let(:user) { create(:user) }
++ let(:user) { create(:user) }
+ let(:admin) { create(:admin) }
+- let(:key) { create(:key, user: user) }
+- let(:email) { create(:email, user: user) }
++ let(:key) { create(:key, user: user) }
++ let(:email) { create(:email, user: user) }
+ let(:omniauth_user) { create(:omniauth_user) }
+ let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain') }
+ let(:ldap_blocked_user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') }
+@@ -827,7 +827,7 @@ describe API::Users, api: true do
+ user.save
+ expect do
+ delete api("/user/keys/#{key.id}", user)
+- end.to change{user.keys.count}.by(-1)
++ end.to change { user.keys.count }.by(-1)
+ expect(response).to have_http_status(200)
+ end
+
+@@ -931,7 +931,7 @@ describe API::Users, api: true do
+ user.save
+ expect do
+ delete api("/user/emails/#{email.id}", user)
+- end.to change{user.emails.count}.by(-1)
++ end.to change { user.emails.count }.by(-1)
+ expect(response).to have_http_status(200)
+ end
+
+@@ -984,7 +984,7 @@ describe API::Users, api: true do
+ end
+
+ describe 'PUT /users/:id/unblock' do
+- let(:blocked_user) { create(:user, state: 'blocked') }
++ let(:blocked_user) { create(:user, state: 'blocked') }
+ before { admin }
+
+ it 'unblocks existing user' do
+@@ -1100,4 +1100,78 @@ describe API::Users, api: true do
+ expect(json_response['message']).to eq('404 User Not Found')
+ end
+ end
++
++ context "user activities", :redis do
++ it_behaves_like 'a paginated resources' do
++ let(:request) { get api("/user/activities", admin) }
++ end
++
++ context 'last activity as normal user' do
++ it 'has no permission' do
++ user.record_activity
++
++ get api("/user/activities", user)
++
++ expect(response).to have_http_status(403)
++ end
++ end
++
++ context 'last activity as admin' do
++ it 'returns the last activity' do
++ allow(Time).to receive(:now).and_return(Time.new(2000, 1, 1))
++
++ user.record_activity
++
++ get api("/user/activities", admin)
++
++ activity = json_response.last
++
++ expect(activity['username']).to eq(user.username)
++ expect(activity['last_activity_at']).to eq('2000-01-01 00:00:00')
++ end
++ end
++
++ context 'last activities paginated', :redis do
++ let(:activity) { json_response.first }
++ let(:old_date) { 2.months.ago.to_date }
++
++ before do
++ 5.times do |num|
++ Timecop.freeze(old_date + num)
++
++ create(:user, username: num.to_s).record_activity
++ end
++ end
++
++ after do
++ Timecop.return
++ end
++
++ it 'returns 3 activities' do
++ get api("/user/activities?page=1&per_page=3", admin)
++
++ expect(json_response.count).to eq(3)
++ end
++
++ it 'contains the first activities' do
++ get api("/user/activities?page=1&per_page=3", admin)
++
++ expect(json_response.map { |activity| activity['username'] }).to eq(%w[0 1 2])
++ end
++
++ it 'contains the last activities' do
++ get api("/user/activities?page=2&per_page=3", admin)
++
++ expect(json_response.map { |activity| activity['username'] }).to eq(%w[3 4])
++ end
++
++ it 'contains activities created after user 3 was created' do
++ from = (old_date + 3).to_s("%Y-%m-%d")
++
++ get api("/user/activities?page=1&per_page=5&from=#{from}", admin)
++
++ expect(json_response.map { |activity| activity['username'] }).to eq(%w[3 4])
++ end
++ end
++ end
+ end