From caa5c962605b80a8f8116c5b8386f871c711ae0a Mon Sep 17 00:00:00 2001 From: Ryan Lue Date: Fri, 4 Jan 2019 08:37:30 +0100 Subject: [PATCH] Refactoring: Migrate Calendar unit test to RSpec. --- spec/models/calendar_spec.rb | 146 ++++++++++++++++++++ test/unit/calendar_test.rb | 249 ----------------------------------- 2 files changed, 146 insertions(+), 249 deletions(-) create mode 100644 spec/models/calendar_spec.rb delete mode 100644 test/unit/calendar_test.rb diff --git a/spec/models/calendar_spec.rb b/spec/models/calendar_spec.rb new file mode 100644 index 000000000..a1ff8134b --- /dev/null +++ b/spec/models/calendar_spec.rb @@ -0,0 +1,146 @@ +require 'rails_helper' + +RSpec.describe Calendar, type: :model do + subject(:calendar) { create(:calendar) } + + describe 'attributes' do + describe '#default' do + before { expect(Calendar.pluck(:default)).to eq([true]) } + + context 'when set to true on creation' do + subject(:calendar) { build(:calendar, default: true) } + + it 'stays true and sets all other calendars to default: false' do + expect { calendar.tap(&:save).reload }.not_to change { calendar.default } + expect(Calendar.where(default: true) - [calendar]).to be_empty + end + end + + context 'when set to true on update' do + subject(:calendar) { create(:calendar, default: false) } + before { calendar.default = true } + + it 'stays true and sets all other calendars to default: false' do + expect { calendar.tap(&:save).reload }.not_to change { calendar.default } + expect(Calendar.where(default: true) - [calendar]).to be_empty + end + end + + context 'when set to false on update' do + it 'sets default: true on earliest-created calendar' do + expect { Calendar.first.update(default: false) } + .not_to change { Calendar.first.default } + end + end + + context 'when default calendar is destroyed' do + subject!(:calendar) { create(:calendar, default: false) } + + it 'sets default: true on earliest-created remaining calendar' do + expect { Calendar.first.destroy } + .to change { calendar.reload.default }.to(true) + end + end + end + + describe '#public_holidays' do + subject(:calendar) do + create(:calendar, ical_url: Rails.root.join('test', 'data', 'calendar', 'calendar1.ics')) + end + + before { travel_to Time.zone.parse('2017-08-24T01:04:44Z0') } + + context 'on creation' do + it 'is computed from iCal event data (implicitly via #sync), from one year before to three years after' do + expect(calendar.public_holidays).to eq( + '2016-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2018-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2019-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + ) + end + + context 'with one-time and n-time (recurring) events' do + subject(:calendar) do + create(:calendar, ical_url: Rails.root.join('test', 'data', 'calendar', 'calendar3.ics')) + end + + it 'accurately computes/imports events' do + expect(calendar.public_holidays).to eq( + '2016-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2016-12-26' => { 'active' => true, 'summary' => 'day3', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2016-12-28' => { 'active' => true, 'summary' => 'day5', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-01-26' => { 'active' => true, 'summary' => 'day3', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-02-26' => { 'active' => true, 'summary' => 'day3', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-03-26' => { 'active' => true, 'summary' => 'day3', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-04-26' => { 'active' => true, 'summary' => 'day3', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2018-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2019-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + ) + end + end + end + end + end + + describe '#sync' do + subject(:calendar) do + create(:calendar, ical_url: Rails.root.join('test', 'data', 'calendar', 'calendar1.ics')) + end + + before { travel_to Time.zone.parse('2017-08-24T01:04:44Z0') } + + context 'when called explicitly after creation' do + it 'writes #public_holidays to the cache (valid for 1 day)' do + expect(Cache.get("CalendarIcal::#{calendar.id}")).to be(nil) + + expect { calendar.sync } + .to change { Cache.get("CalendarIcal::#{calendar.id}") } + .to(calendar.attributes.slice('public_holidays', 'ical_url').symbolize_keys) + end + + context 'and neither current date nor iCal URL have changed' do + it 'is idempotent' do + expect { calendar.sync } + .not_to change { calendar.public_holidays } + end + end + + context 'and current date has changed (past cache expiry)' do + before do + calendar # create and sync + travel 1.year + end + + it 'appends newly computed event data to #public_holidays' do + expect { calendar.sync }.to change { calendar.public_holidays }.to( + '2016-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2018-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2019-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2020-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + ) + end + end + + context 'and iCal URL has changed' do + before { calendar.assign_attributes(ical_url: Rails.root.join('test', 'data', 'calendar', 'calendar2.ics')) } + + it 'replaces #public_holidays with event data computed from new iCal URL' do + expect { calendar.save } + .to change { calendar.public_holidays }.to( + '2016-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2016-12-25' => { 'active' => true, 'summary' => 'Christmas2', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2017-12-25' => { 'active' => true, 'summary' => 'Christmas2', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2018-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2018-12-25' => { 'active' => true, 'summary' => 'Christmas2', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2019-12-24' => { 'active' => true, 'summary' => 'Christmas1', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + '2019-12-25' => { 'active' => true, 'summary' => 'Christmas2', 'feed' => Digest::MD5.hexdigest(calendar.ical_url) }, + ) + end + end + end + end +end diff --git a/test/unit/calendar_test.rb b/test/unit/calendar_test.rb deleted file mode 100644 index 0ede03674..000000000 --- a/test/unit/calendar_test.rb +++ /dev/null @@ -1,249 +0,0 @@ -require 'test_helper' - -class CalendarTest < ActiveSupport::TestCase - test 'default test' do - Calendar.destroy_all - calendar1 = Calendar.create_or_update( - name: 'US 1', - timezone: 'America/Los_Angeles', - business_hours: { - mon: { '09:00' => '17:00' }, - tue: { '09:00' => '17:00' }, - wed: { '09:00' => '17:00' }, - thu: { '09:00' => '17:00' }, - fri: { '09:00' => '17:00' } - }, - default: true, - ical_url: nil, - updated_by_id: 1, - created_by_id: 1, - ) - travel 1.second - calendar2 = Calendar.create_or_update( - name: 'US 2', - timezone: 'America/Los_Angeles', - business_hours: { - mon: { '09:00' => '17:00' }, - tue: { '09:00' => '17:00' }, - wed: { '09:00' => '17:00' }, - thu: { '09:00' => '17:00' }, - fri: { '09:00' => '17:00' } - }, - default: false, - ical_url: nil, - updated_by_id: 1, - created_by_id: 1, - ) - - calendar3 = Calendar.create_or_update( - name: 'US 3', - timezone: 'America/Los_Angeles', - business_hours: { - mon: { '09:00' => '17:00' }, - tue: { '09:00' => '17:00' }, - wed: { '09:00' => '17:00' }, - thu: { '09:00' => '17:00' }, - fri: { '09:00' => '17:00' } - }, - default: true, - ical_url: nil, - updated_by_id: 1, - created_by_id: 1, - ) - - calendar1 = Calendar.find_by(name: 'US 1') - calendar2 = Calendar.find_by(name: 'US 2') - calendar3 = Calendar.find_by(name: 'US 3') - - assert_equal(false, calendar1.default) - assert_equal(false, calendar2.default) - assert_equal(true, calendar3.default) - - calendar2.default = true - calendar2.save! - - calendar1 = Calendar.find_by(name: 'US 1') - calendar2 = Calendar.find_by(name: 'US 2') - calendar3 = Calendar.find_by(name: 'US 3') - - assert_equal(false, calendar1.default) - assert_equal(true, calendar2.default) - assert_equal(false, calendar3.default) - - calendar2.default = false - calendar2.save! - - calendar1 = Calendar.find_by(name: 'US 1') - calendar2 = Calendar.find_by(name: 'US 2') - calendar3 = Calendar.find_by(name: 'US 3') - - assert_equal(true, calendar1.default) - assert_equal(false, calendar2.default) - assert_equal(false, calendar3.default) - - calendar1.destroy! - calendar2 = Calendar.find_by(name: 'US 2') - calendar3 = Calendar.find_by(name: 'US 3') - - assert_equal(true, calendar2.default) - assert_equal(false, calendar3.default) - - calendar2.destroy! - calendar3.destroy! - - travel_back - end - - test 'sync test' do - Calendar.destroy_all - - travel_to Time.zone.parse('2017-08-24T01:04:44Z0') - - calendar1 = Calendar.create_or_update( - name: 'Sync 1', - timezone: 'America/Los_Angeles', - business_hours: { - mon: { '09:00' => '17:00' }, - tue: { '09:00' => '17:00' }, - wed: { '09:00' => '17:00' }, - thu: { '09:00' => '17:00' }, - fri: { '09:00' => '17:00' } - }, - default: true, - ical_url: Rails.root.join('test', 'data', 'calendar', 'calendar1.ics'), - updated_by_id: 1, - created_by_id: 1, - ) - - assert_equal(true, calendar1.public_holidays['2016-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2016-12-24']['summary']) - assert_nil(calendar1.public_holidays['2016-12-25']) - assert_equal(true, calendar1.public_holidays['2017-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2017-12-24']['summary']) - assert_nil(calendar1.public_holidays['2017-12-25']) - assert_equal(true, calendar1.public_holidays['2018-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2018-12-24']['summary']) - assert_nil(calendar1.public_holidays['2018-12-25']) - assert_equal(true, calendar1.public_holidays['2019-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2019-12-24']['summary']) - assert_nil(calendar1.public_holidays['2019-12-25']) - assert_nil(calendar1.public_holidays['2020-12-24']) - - Calendar.sync - - assert_equal(true, calendar1.public_holidays['2016-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2016-12-24']['summary']) - assert_nil(calendar1.public_holidays['2016-12-25']) - assert_equal(true, calendar1.public_holidays['2017-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2017-12-24']['summary']) - assert_nil(calendar1.public_holidays['2017-12-25']) - assert_equal(true, calendar1.public_holidays['2018-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2018-12-24']['summary']) - assert_nil(calendar1.public_holidays['2018-12-25']) - assert_equal(true, calendar1.public_holidays['2019-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2019-12-24']['summary']) - assert_nil(calendar1.public_holidays['2019-12-25']) - assert_nil(calendar1.public_holidays['2020-12-24']) - - cache_key = "CalendarIcal::#{calendar1.id}" - cache = Cache.get(cache_key) - - calendar1.update_columns(ical_url: Rails.root.join('test', 'data', 'calendar', 'calendar2.ics').to_s) - cache_key = "CalendarIcal::#{calendar1.id}" - cache = Cache.get(cache_key) - cache[:ical_url] = calendar1.ical_url - Cache.write( - cache_key, - cache, - { expires_in: 1.day }, - ) - - Calendar.sync - - calendar1.reload - assert_equal(true, calendar1.public_holidays['2016-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2016-12-24']['summary']) - assert_nil(calendar1.public_holidays['2016-12-25']) - assert_equal(true, calendar1.public_holidays['2017-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2017-12-24']['summary']) - assert_nil(calendar1.public_holidays['2017-12-25']) - assert_equal(true, calendar1.public_holidays['2018-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2018-12-24']['summary']) - assert_nil(calendar1.public_holidays['2018-12-25']) - assert_equal(true, calendar1.public_holidays['2019-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2019-12-24']['summary']) - assert_nil(calendar1.public_holidays['2019-12-25']) - assert_nil(calendar1.public_holidays['2020-12-24']) - - travel 2.days - - Calendar.sync - - calendar1.reload - assert_equal(true, calendar1.public_holidays['2016-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2016-12-24']['summary']) - assert_equal(true, calendar1.public_holidays['2016-12-25']['active']) - assert_equal('Christmas2', calendar1.public_holidays['2016-12-25']['summary']) - assert_equal(true, calendar1.public_holidays['2017-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2017-12-24']['summary']) - assert_equal(true, calendar1.public_holidays['2017-12-25']['active']) - assert_equal('Christmas2', calendar1.public_holidays['2017-12-25']['summary']) - assert_equal(true, calendar1.public_holidays['2018-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2018-12-24']['summary']) - assert_equal(true, calendar1.public_holidays['2018-12-25']['active']) - assert_equal('Christmas2', calendar1.public_holidays['2018-12-25']['summary']) - assert_equal(true, calendar1.public_holidays['2019-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2019-12-24']['summary']) - assert_equal(true, calendar1.public_holidays['2019-12-25']['active']) - assert_equal('Christmas2', calendar1.public_holidays['2019-12-25']['summary']) - assert_nil(calendar1.public_holidays['2020-12-24']) - assert_nil(calendar1.public_holidays['2020-12-25']) - - Calendar.destroy_all - - calendar1 = Calendar.create_or_update( - name: 'Sync 2', - timezone: 'America/Los_Angeles', - business_hours: { - mon: { '09:00' => '17:00' }, - tue: { '09:00' => '17:00' }, - wed: { '09:00' => '17:00' }, - thu: { '09:00' => '17:00' }, - fri: { '09:00' => '17:00' } - }, - default: true, - ical_url: Rails.root.join('test', 'data', 'calendar', 'calendar3.ics'), - updated_by_id: 1, - created_by_id: 1, - ) - - assert_equal(true, calendar1.public_holidays['2016-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2016-12-24']['summary']) - assert_equal(true, calendar1.public_holidays['2016-12-26']['active']) - assert_equal('day3', calendar1.public_holidays['2016-12-26']['summary']) - assert_equal(true, calendar1.public_holidays['2016-12-28']['active']) - assert_equal('day5', calendar1.public_holidays['2016-12-28']['summary']) - assert_equal(true, calendar1.public_holidays['2017-01-26']['active']) - assert_equal('day3', calendar1.public_holidays['2017-01-26']['summary']) - assert_equal(true, calendar1.public_holidays['2017-02-26']['active']) - assert_equal('day3', calendar1.public_holidays['2017-02-26']['summary']) - assert_equal(true, calendar1.public_holidays['2017-03-26']['active']) - assert_equal('day3', calendar1.public_holidays['2017-03-26']['summary']) - assert_equal(true, calendar1.public_holidays['2017-04-26']['active']) - assert_equal('day3', calendar1.public_holidays['2017-04-26']['summary']) - assert_nil(calendar1.public_holidays['2017-05-26']) - assert_equal(true, calendar1.public_holidays['2017-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2017-12-24']['summary']) - assert_equal(true, calendar1.public_holidays['2018-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2018-12-24']['summary']) - assert_equal(true, calendar1.public_holidays['2019-12-24']['active']) - assert_equal('Christmas1', calendar1.public_holidays['2019-12-24']['summary']) - assert_nil(calendar1.public_holidays['2020-12-24']) - - calendar1.destroy! - - travel_back - - end - -end