From ab4786d7b98d6c9509599a26af8a5022eda9907a Mon Sep 17 00:00:00 2001 From: Eugene Burmakin Date: Tue, 7 Oct 2025 21:24:38 +0200 Subject: [PATCH] Fix minor bugs in Stat model related to sharing settings --- app/models/stat.rb | 6 +- spec/models/stat_spec.rb | 218 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+), 3 deletions(-) diff --git a/app/models/stat.rb b/app/models/stat.rb index 36421b97..1bcb2cbf 100644 --- a/app/models/stat.rb +++ b/app/models/stat.rb @@ -33,14 +33,14 @@ class Stat < ApplicationRecord end def sharing_enabled? - sharing_settings['enabled'] == true + sharing_settings.try(:[], 'enabled') == true end def sharing_expired? - expiration = sharing_settings['expiration'] + expiration = sharing_settings.try(:[], 'expiration') return false if expiration.blank? - expires_at_value = sharing_settings['expires_at'] + expires_at_value = sharing_settings.try(:[], 'expires_at') return true if expires_at_value.blank? expires_at = begin diff --git a/spec/models/stat_spec.rb b/spec/models/stat_spec.rb index e6a5cadb..6b70b59b 100644 --- a/spec/models/stat_spec.rb +++ b/spec/models/stat_spec.rb @@ -262,5 +262,223 @@ RSpec.describe Stat, type: :model do end end end + + describe 'sharing settings' do + let(:user) { create(:user) } + let(:stat) { create(:stat, year: 2024, month: 6, user: user) } + + describe '#sharing_enabled?' do + context 'when sharing_settings is nil' do + before { stat.update_column(:sharing_settings, nil) } + + it 'returns false' do + expect(stat.sharing_enabled?).to be false + end + end + + context 'when sharing_settings is empty hash' do + before { stat.update(sharing_settings: {}) } + + it 'returns false' do + expect(stat.sharing_enabled?).to be false + end + end + + context 'when enabled is false' do + before { stat.update(sharing_settings: { 'enabled' => false }) } + + it 'returns false' do + expect(stat.sharing_enabled?).to be false + end + end + + context 'when enabled is true' do + before { stat.update(sharing_settings: { 'enabled' => true }) } + + it 'returns true' do + expect(stat.sharing_enabled?).to be true + end + end + + context 'when enabled is a string "true"' do + before { stat.update(sharing_settings: { 'enabled' => 'true' }) } + + it 'returns false (strict boolean check)' do + expect(stat.sharing_enabled?).to be false + end + end + end + + describe '#sharing_expired?' do + context 'when sharing_settings is nil' do + before { stat.update_column(:sharing_settings, nil) } + + it 'returns false' do + expect(stat.sharing_expired?).to be false + end + end + + context 'when expiration is blank' do + before { stat.update(sharing_settings: { 'enabled' => true }) } + + it 'returns false' do + expect(stat.sharing_expired?).to be false + end + end + + context 'when expiration is present but expires_at is blank' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h' + }) + end + + it 'returns true' do + expect(stat.sharing_expired?).to be true + end + end + + context 'when expires_at is in the future' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => 1.hour.from_now.iso8601 + }) + end + + it 'returns false' do + expect(stat.sharing_expired?).to be false + end + end + + context 'when expires_at is in the past' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => 1.hour.ago.iso8601 + }) + end + + it 'returns true' do + expect(stat.sharing_expired?).to be true + end + end + + context 'when expires_at is 1 second in the future' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => 1.second.from_now.iso8601 + }) + end + + it 'returns false (not yet expired)' do + expect(stat.sharing_expired?).to be false + end + end + + context 'when expires_at is invalid date string' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => 'invalid-date' + }) + end + + it 'returns true (treats as expired)' do + expect(stat.sharing_expired?).to be true + end + end + + context 'when expires_at is nil' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => nil + }) + end + + it 'returns true' do + expect(stat.sharing_expired?).to be true + end + end + + context 'when expires_at is empty string' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => '' + }) + end + + it 'returns true' do + expect(stat.sharing_expired?).to be true + end + end + end + + describe '#public_accessible?' do + context 'when sharing_settings is nil' do + before { stat.update_column(:sharing_settings, nil) } + + it 'returns false' do + expect(stat.public_accessible?).to be false + end + end + + context 'when sharing is not enabled' do + before { stat.update(sharing_settings: { 'enabled' => false }) } + + it 'returns false' do + expect(stat.public_accessible?).to be false + end + end + + context 'when sharing is enabled but expired' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => 1.hour.ago.iso8601 + }) + end + + it 'returns false' do + expect(stat.public_accessible?).to be false + end + end + + context 'when sharing is enabled and not expired' do + before do + stat.update(sharing_settings: { + 'enabled' => true, + 'expiration' => '1h', + 'expires_at' => 1.hour.from_now.iso8601 + }) + end + + it 'returns true' do + expect(stat.public_accessible?).to be true + end + end + + context 'when sharing is enabled with no expiration' do + before do + stat.update(sharing_settings: { 'enabled' => true }) + end + + it 'returns true' do + expect(stat.public_accessible?).to be true + end + end + end + end end end