2019-04-04 20:35:16 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2017-07-06 15:07:05 +08:00
|
|
|
require 'rails_helper'
|
|
|
|
|
|
|
|
describe User, type: :model do
|
2019-05-08 21:28:07 +08:00
|
|
|
let(:user) { build :user }
|
|
|
|
|
|
|
|
it 'is valid' do
|
|
|
|
expect(user).to be_valid
|
|
|
|
end
|
2017-07-06 15:07:05 +08:00
|
|
|
it 'should be of class User' do
|
|
|
|
expect(subject.class).to eq User
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'Database table' do
|
2017-07-10 20:38:18 +08:00
|
|
|
it { should have_db_column :id }
|
|
|
|
it { should have_db_column :full_name }
|
|
|
|
it { should have_db_column :initials }
|
|
|
|
it { should have_db_column :email }
|
|
|
|
it { should have_db_column :encrypted_password }
|
|
|
|
it { should have_db_column :reset_password_token }
|
|
|
|
it { should have_db_column :reset_password_sent_at }
|
|
|
|
it { should have_db_column :sign_in_count }
|
|
|
|
it { should have_db_column :current_sign_in_at }
|
|
|
|
it { should have_db_column :last_sign_in_at }
|
|
|
|
it { should have_db_column :current_sign_in_ip }
|
|
|
|
it { should have_db_column :last_sign_in_ip }
|
|
|
|
it { should have_db_column :created_at }
|
|
|
|
it { should have_db_column :updated_at }
|
|
|
|
it { should have_db_column :confirmation_token }
|
|
|
|
it { should have_db_column :confirmed_at }
|
|
|
|
it { should have_db_column :confirmation_sent_at }
|
|
|
|
it { should have_db_column :unconfirmed_email }
|
|
|
|
it { should have_db_column :invitation_token }
|
|
|
|
it { should have_db_column :invitation_created_at }
|
|
|
|
it { should have_db_column :invitation_sent_at }
|
|
|
|
it { should have_db_column :invitation_accepted_at }
|
|
|
|
it { should have_db_column :invitation_limit }
|
|
|
|
it { should have_db_column :invited_by_id }
|
|
|
|
it { should have_db_column :invited_by_type }
|
|
|
|
it { should have_db_column :invitations_count }
|
2017-08-10 17:30:57 +08:00
|
|
|
it { should have_db_column :settings }
|
2018-10-16 03:40:59 +08:00
|
|
|
it { should have_db_column :variables }
|
2017-07-10 20:38:18 +08:00
|
|
|
it { should have_db_column :current_team_id }
|
|
|
|
it { should have_db_column :authentication_token }
|
2017-07-06 15:07:05 +08:00
|
|
|
end
|
|
|
|
|
2017-07-06 23:37:29 +08:00
|
|
|
describe 'Relations' do
|
2017-07-10 20:38:18 +08:00
|
|
|
it { should have_many :teams }
|
|
|
|
it { should have_many :user_projects }
|
|
|
|
it { should have_many :projects }
|
|
|
|
it { should have_many :user_my_modules }
|
|
|
|
it { should have_many :comments }
|
|
|
|
it { should have_many :activities }
|
|
|
|
it { should have_many :results }
|
|
|
|
it { should have_many :repository_table_states }
|
|
|
|
it { should have_many :steps }
|
|
|
|
it { should have_many :reports }
|
|
|
|
it { should have_many :created_assets }
|
|
|
|
it { should have_many :modified_assets }
|
|
|
|
it { should have_many :created_checklists }
|
|
|
|
it { should have_many :modified_checklists }
|
|
|
|
it { should have_many :created_checklist_items }
|
|
|
|
it { should have_many :modified_checklist_items }
|
|
|
|
it { should have_many :modified_comments }
|
|
|
|
it { should have_many :created_my_module_groups }
|
|
|
|
it { should have_many :created_my_module_tags }
|
|
|
|
it { should have_many :created_my_modules }
|
|
|
|
it { should have_many :modified_my_modules }
|
|
|
|
it { should have_many :archived_my_modules }
|
|
|
|
it { should have_many :restored_my_modules }
|
|
|
|
it { should have_many :created_teams }
|
|
|
|
it { should have_many :modified_teams }
|
|
|
|
it { should have_many :created_projects }
|
|
|
|
it { should have_many :modified_projects }
|
|
|
|
it { should have_many :archived_projects }
|
|
|
|
it { should have_many :restored_projects }
|
|
|
|
it { should have_many :modified_reports }
|
|
|
|
it { should have_many :archived_results }
|
|
|
|
it { should have_many :restored_results }
|
|
|
|
it { should have_many :created_tables }
|
|
|
|
it { should have_many :modified_tables }
|
|
|
|
it { should have_many :created_tags }
|
|
|
|
it { should have_many :tokens }
|
|
|
|
it { should have_many :modified_tags }
|
|
|
|
it { should have_many :assigned_user_my_modules }
|
|
|
|
it { should have_many :assigned_user_projects }
|
|
|
|
it { should have_many :added_protocols }
|
|
|
|
it { should have_many :archived_protocols }
|
|
|
|
it { should have_many :restored_protocols }
|
|
|
|
it { should have_many :assigned_my_module_repository_rows }
|
|
|
|
it { should have_many :user_notifications }
|
|
|
|
it { should have_many :notifications }
|
|
|
|
it { should have_many :zip_exports }
|
2023-07-26 21:21:55 +08:00
|
|
|
it { should have_many(:shareable_links).dependent(:destroy) }
|
2017-11-20 16:41:14 +08:00
|
|
|
|
|
|
|
it 'have many repositories' do
|
|
|
|
table = User.reflect_on_association(:repositories)
|
|
|
|
expect(table.macro).to eq(:has_many)
|
|
|
|
end
|
|
|
|
|
2017-11-23 22:30:08 +08:00
|
|
|
it 'have many modified results' do
|
2017-11-20 16:41:14 +08:00
|
|
|
table = User.reflect_on_association(:modified_results)
|
|
|
|
expect(table.macro).to eq(:has_many)
|
|
|
|
end
|
|
|
|
|
2017-11-23 22:30:08 +08:00
|
|
|
it 'have many modified steps' do
|
2017-11-20 16:41:14 +08:00
|
|
|
table = User.reflect_on_association(:modified_steps)
|
|
|
|
expect(table.macro).to eq(:has_many)
|
|
|
|
end
|
2017-07-06 23:37:29 +08:00
|
|
|
end
|
|
|
|
|
2019-05-08 21:28:07 +08:00
|
|
|
describe 'Validations' do
|
2017-07-06 23:37:29 +08:00
|
|
|
it { should validate_presence_of :full_name }
|
|
|
|
it { should validate_presence_of :initials }
|
|
|
|
it { should validate_presence_of :email }
|
2017-07-06 15:07:05 +08:00
|
|
|
|
|
|
|
it do
|
|
|
|
should validate_length_of(:full_name).is_at_most(
|
|
|
|
Constants::NAME_MAX_LENGTH
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it do
|
|
|
|
should validate_length_of(:initials).is_at_most(
|
|
|
|
Constants::USER_INITIALS_MAX_LENGTH
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
it do
|
|
|
|
should validate_length_of(:email).is_at_most(
|
|
|
|
Constants::EMAIL_MAX_LENGTH
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'Should return a user name' do
|
|
|
|
let(:user) { build :user, full_name: 'Tinker' }
|
|
|
|
|
|
|
|
it 'should return a user full name' do
|
|
|
|
expect(user.name).to eq 'Tinker'
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'should to be able to change full name' do
|
|
|
|
user.name = 'Axe'
|
|
|
|
expect(user.name).to_not eq 'Tinker'
|
|
|
|
expect(user.name).to eq 'Axe'
|
|
|
|
end
|
|
|
|
end
|
2017-08-25 22:07:37 +08:00
|
|
|
|
2017-10-05 21:53:05 +08:00
|
|
|
describe 'user settings' do
|
|
|
|
it { is_expected.to respond_to(:time_zone) }
|
|
|
|
it { is_expected.to respond_to(:assignments_notification) }
|
|
|
|
it { is_expected.to respond_to(:assignments_email_notification) }
|
|
|
|
it { is_expected.to respond_to(:recent_notification) }
|
|
|
|
it { is_expected.to respond_to(:recent_email_notification) }
|
|
|
|
end
|
2018-01-03 20:48:59 +08:00
|
|
|
|
2018-10-16 03:40:59 +08:00
|
|
|
describe 'user variables' do
|
|
|
|
it { is_expected.to respond_to(:export_vars) }
|
|
|
|
end
|
|
|
|
|
2018-01-03 20:48:59 +08:00
|
|
|
describe '#last_activities' do
|
|
|
|
let!(:user) { create :user }
|
|
|
|
let!(:project) { create :project }
|
2019-01-15 20:45:05 +08:00
|
|
|
let!(:user_projects) do
|
|
|
|
create :user_project, :viewer, project: project, user: user
|
|
|
|
end
|
2019-02-20 19:04:01 +08:00
|
|
|
let!(:activity_one) { create :activity, owner: user, project: project }
|
|
|
|
let!(:activity_two) { create :activity, owner: user, project: project }
|
2018-01-03 20:48:59 +08:00
|
|
|
|
|
|
|
it 'is expected to return an array of user\'s activities' do
|
|
|
|
activities = user.last_activities
|
|
|
|
expect(activities.count).to eq 2
|
|
|
|
expect(activities).to include activity_one
|
|
|
|
expect(activities).to include activity_two
|
|
|
|
end
|
|
|
|
end
|
2019-01-24 23:43:24 +08:00
|
|
|
|
|
|
|
describe '#increase_daily_exports_counter!' do
|
|
|
|
let(:user) { create :user }
|
|
|
|
context 'when last_export_timestamp is set' do
|
|
|
|
it 'increases counter by 1' do
|
|
|
|
expect { user.increase_daily_exports_counter! }
|
|
|
|
.to change {
|
|
|
|
user.reload.export_vars['num_of_export_all_last_24_hours']
|
|
|
|
}.from(0).to(1)
|
|
|
|
end
|
|
|
|
|
2019-04-04 20:35:16 +08:00
|
|
|
it 'sets last_export_timestamp on today\'s timestamp' do
|
2019-01-24 23:43:24 +08:00
|
|
|
user.export_vars['last_export_timestamp'] = Date.yesterday.to_time.to_i
|
|
|
|
user.save
|
|
|
|
|
|
|
|
expect { user.increase_daily_exports_counter! }
|
|
|
|
.to change {
|
|
|
|
user.reload.export_vars['last_export_timestamp']
|
2019-04-04 20:35:16 +08:00
|
|
|
}.to(Time.now.utc.beginning_of_day.to_i..Time.now.utc.end_of_day.to_i)
|
2019-01-24 23:43:24 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'sets new counter for today' do
|
|
|
|
user.export_vars = {
|
|
|
|
'num_of_export_all_last_24_hours': 3,
|
|
|
|
'last_export_timestamp': Date.yesterday.to_time.to_i
|
|
|
|
}
|
|
|
|
user.save
|
|
|
|
|
|
|
|
expect { user.increase_daily_exports_counter! }
|
|
|
|
.to change {
|
|
|
|
user.reload.export_vars['num_of_export_all_last_24_hours']
|
|
|
|
}.from(3).to(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when last_export_timestamp not exists (existing users)' do
|
2019-04-04 20:35:16 +08:00
|
|
|
it 'sets last_export_timestamp on today\'s timestamp' do
|
2019-01-24 23:43:24 +08:00
|
|
|
user.export_vars.delete('last_export_timestamp')
|
|
|
|
user.save
|
|
|
|
|
|
|
|
expect { user.increase_daily_exports_counter! }
|
|
|
|
.to change {
|
|
|
|
user.reload.export_vars['last_export_timestamp']
|
2019-04-04 20:35:16 +08:00
|
|
|
}.from(nil).to(Time.now.utc.beginning_of_day.to_i..Time.now.utc.end_of_day.to_i)
|
2019-01-24 23:43:24 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'starts count reports with 1' do
|
|
|
|
user.export_vars.delete('last_export_timestamp')
|
|
|
|
user.export_vars['num_of_export_all_last_24_hours'] = 2
|
|
|
|
user.save
|
|
|
|
|
|
|
|
expect { user.increase_daily_exports_counter! }
|
|
|
|
.to change {
|
|
|
|
user.reload.export_vars['num_of_export_all_last_24_hours']
|
|
|
|
}.from(2).to(1)
|
|
|
|
end
|
|
|
|
end
|
2019-04-15 22:38:19 +08:00
|
|
|
|
|
|
|
context 'when num_of_export not exists' do
|
|
|
|
it 'starts count reports with 1' do
|
|
|
|
user.export_vars.delete('num_of_export_all_last_24_hours')
|
|
|
|
user.save
|
|
|
|
|
|
|
|
expect { user.increase_daily_exports_counter! }
|
|
|
|
.to change {
|
|
|
|
user.reload.export_vars['num_of_export_all_last_24_hours']
|
|
|
|
}.from(nil).to(1)
|
|
|
|
end
|
|
|
|
end
|
2019-01-24 23:43:24 +08:00
|
|
|
end
|
2019-01-25 21:53:06 +08:00
|
|
|
|
2019-04-15 22:38:19 +08:00
|
|
|
describe '#has_available_exports?' do
|
2019-04-04 20:35:16 +08:00
|
|
|
let(:user) { create :user }
|
|
|
|
|
2019-04-15 22:38:19 +08:00
|
|
|
context 'when user have export_vars' do
|
|
|
|
it 'returns true when user has avaiable export' do
|
|
|
|
expect(user.has_available_exports?).to be_truthy
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns false when user has no avaiable export' do
|
|
|
|
user.export_vars['num_of_export_all_last_24_hours'] = 3
|
|
|
|
|
|
|
|
expect(user.has_available_exports?).to be_falsey
|
|
|
|
end
|
2019-04-04 20:35:16 +08:00
|
|
|
end
|
|
|
|
|
2019-04-15 22:38:19 +08:00
|
|
|
context 'when user do not have export_vars' do
|
|
|
|
it 'returns false when user has no avaiable export' do
|
|
|
|
user.export_vars = {}
|
2019-04-04 20:35:16 +08:00
|
|
|
|
2019-04-15 22:38:19 +08:00
|
|
|
expect(user.has_available_exports?).to be_truthy
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe '#exports_left' do
|
|
|
|
let(:user) { create :user }
|
|
|
|
context 'when user do have export_vars' do
|
|
|
|
it 'returns 3 when user has all exports avaible' do
|
|
|
|
expect(user.exports_left).to be == 3
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns 0 when user has no avaiable export' do
|
|
|
|
user.export_vars['num_of_export_all_last_24_hours'] = 3
|
|
|
|
|
|
|
|
expect(user.exports_left).to be == 0
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'returns 3 when user has invalid number from the past' do
|
|
|
|
user.export_vars['num_of_export_all_last_24_hours'] = -4
|
|
|
|
user.export_vars['last_export_timestamp'] = Date.yesterday.to_time.utc.to_i
|
|
|
|
|
|
|
|
expect(user.exports_left).to be == 3
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user do not have export_vars' do
|
|
|
|
it 'returns false when user has no avaiable export' do
|
|
|
|
user.export_vars = {}
|
|
|
|
|
|
|
|
expect(user.exports_left).to be == 3
|
|
|
|
end
|
2019-04-04 20:35:16 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-08-11 19:18:58 +08:00
|
|
|
describe 'Email downcase' do
|
|
|
|
it 'downcases email before validating and saving user' do
|
|
|
|
user = User.new(email: 'Test@Email.com')
|
|
|
|
user.save
|
|
|
|
expect(user.email).to eq('test@email.com')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-06-30 20:16:00 +08:00
|
|
|
describe 'valid_otp?' do
|
|
|
|
let(:user) { create :user }
|
|
|
|
before do
|
2020-07-02 17:24:33 +08:00
|
|
|
user.assign_2fa_token!
|
2020-06-30 20:16:00 +08:00
|
|
|
allow_any_instance_of(ROTP::TOTP).to receive(:verify).and_return(nil)
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user has set otp_secret' do
|
|
|
|
it 'returns nil' do
|
|
|
|
expect(user.valid_otp?('someString')).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when user does not have otp_secret' do
|
|
|
|
it 'raises an error' do
|
|
|
|
user.update_column(:otp_secret, nil)
|
|
|
|
|
|
|
|
expect { user.valid_otp?('someString') }.to raise_error(StandardError, 'Missing otp_secret')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2017-07-06 15:07:05 +08:00
|
|
|
end
|