diff options
author | Rémy Coutable <remy@rymai.me> | 2017-03-07 19:34:43 +0100 |
---|---|---|
committer | Rémy Coutable <remy@rymai.me> | 2017-04-14 15:20:55 +0200 |
commit | cfe19b795e076b73df75ee57839640667283651c (patch) | |
tree | e5de8f36de866a24a9e1068063a115640062e801 /spec/lib | |
parent | 91ac0e038ab51dd2f30f2bb7c91837fa588ca250 (diff) | |
download | gitlab-ce-cfe19b795e076b73df75ee57839640667283651c.tar.gz |
Add a new Gitlab::UserActivities class to track user activities
This new class uses a Redis Hash instead of a Sorted Set.
Signed-off-by: Rémy Coutable <remy@rymai.me>
Diffstat (limited to 'spec/lib')
-rw-r--r-- | spec/lib/gitlab/user_activities/activity_set_spec.rb | 77 | ||||
-rw-r--r-- | spec/lib/gitlab/user_activities/activity_spec.rb | 14 | ||||
-rw-r--r-- | spec/lib/gitlab/user_activities_spec.rb | 127 |
3 files changed, 127 insertions, 91 deletions
diff --git a/spec/lib/gitlab/user_activities/activity_set_spec.rb b/spec/lib/gitlab/user_activities/activity_set_spec.rb deleted file mode 100644 index 56745bdf0d1..00000000000 --- a/spec/lib/gitlab/user_activities/activity_set_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -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 deleted file mode 100644 index 6a1150f50c1..00000000000 --- a/spec/lib/gitlab/user_activities/activity_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -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/lib/gitlab/user_activities_spec.rb b/spec/lib/gitlab/user_activities_spec.rb new file mode 100644 index 00000000000..187d88c8c58 --- /dev/null +++ b/spec/lib/gitlab/user_activities_spec.rb @@ -0,0 +1,127 @@ +require 'spec_helper' + +describe Gitlab::UserActivities, :redis, lib: true do + let(:now) { Time.now } + + describe '.record' do + context 'with no time given' do + it 'uses Time.now and records an activity in Redis' do + Timecop.freeze do + now # eager-load now + described_class.record(42) + end + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]]) + end + end + end + + context 'with a time given' do + it 'uses the given time and records an activity in Redis' do + described_class.record(42, now) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]]) + end + end + end + end + + describe '.delete' do + context 'with a single key' do + context 'and key exists' do + it 'removes the pair from Redis' do + described_class.record(42, now) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]]) + end + + subject.delete(42) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []]) + end + end + end + + context 'and key does not exist' do + it 'removes the pair from Redis' do + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []]) + end + + subject.delete(42) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []]) + end + end + end + end + + context 'with multiple keys' do + context 'and all keys exist' do + it 'removes the pair from Redis' do + described_class.record(41, now) + described_class.record(42, now) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['41', now.to_i.to_s], ['42', now.to_i.to_s]]]) + end + + subject.delete(41, 42) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []]) + end + end + end + + context 'and some keys does not exist' do + it 'removes the existing pair from Redis' do + described_class.record(42, now) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]]) + end + + subject.delete(41, 42) + + Gitlab::Redis.with do |redis| + expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []]) + end + end + end + end + end + + describe 'Enumerable' do + before do + described_class.record(40, now) + described_class.record(41, now) + described_class.record(42, now) + end + + it 'allows to read the activities sequentially' do + expected = { '40' => now.to_i.to_s, '41' => now.to_i.to_s, '42' => now.to_i.to_s } + + actual = described_class.new.each_with_object({}) do |(key, time), actual| + actual[key] = time + end + + expect(actual).to eq(expected) + end + + context 'with many records' do + before do + 1_000.times { |i| described_class.record(i, now) } + end + + it 'is possible to loop through all the records' do + expect(described_class.new.count).to eq(1_000) + end + end + end +end |