Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions backend/app/controllers/api/v1/profiles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ def update

if time_changed || initial_onboarding_reminder
delete_old_job(@profile.reminder_job_id)

job_id = CheckinReminderJob.perform_in(get_reminder_time.minutes, @profile.id, @profile.checkin_reminder_at)
@profile.update_column(:reminder_job_id, job_id)
@profile.update_column(:reminder_job_id, schedule_reminder)
end

current_user.profile.reload
Expand All @@ -59,6 +57,19 @@ def transform_hash_time
{checkin_reminder_at: user_time.try(:to_time, :utc)}
end

# Returns the id of the newly scheduled job, or nil when there is no time to
# remind at (e.g. the user opted out of reminders during onboarding).
def schedule_reminder
return if @profile.checkin_reminder_at.blank?

CheckinReminderJob.perform_in(
get_reminder_time.minutes,
@profile.id,
# Sidekiq only accepts native JSON types as job arguments.
@profile.checkin_reminder_at.iso8601
)
end

def get_reminder_time
time_zone_name = @profile.time_zone_name
checkin_at_timezone = @profile.checkin_reminder_at.strftime("%H:%M").in_time_zone(time_zone_name)
Expand Down
63 changes: 63 additions & 0 deletions backend/spec/controllers/api/v1/profiles_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
require "rails_helper"
require "sidekiq/testing"

# Requiring sidekiq/testing switches Sidekiq into fake mode for the whole suite;
# keep the default as-is and opt in per example group instead.
Sidekiq::Testing.disable!

RSpec.describe Api::V1::ProfilesController do
let(:user) { create(:user) }
Expand Down Expand Up @@ -81,5 +86,63 @@
end
end
end

context "reminder scheduling" do
before { sign_in user }

around do |example|
Sidekiq::Testing.fake! do
CheckinReminderJob.clear
example.run
end
end

context "when the user opts out of reminders" do
let(:opt_out_params) { {checkin_reminder: false, onboarding_reminder: true} }

it "responds successfully without scheduling a reminder" do
put :update, params: {id: profile.id, profile: opt_out_params}

expect(response.status).to eq 200
expect(CheckinReminderJob.jobs).to be_empty
end

it "clears a previously scheduled job id" do
profile.update_column(:reminder_job_id, "stale-job-id")

put :update, params: {id: profile.id, profile: opt_out_params}

expect(profile.reload.reminder_job_id).to be_nil
end
end

context "when the user picks a reminder time" do
let(:reminder_params) do
{
checkin_reminder: true,
onboarding_reminder: true,
time_zone_name: "America/New_York",
checkin_reminder_at: {hours: 20, minutes: 30}
}
end

it "schedules a reminder and stores its job id" do
put :update, params: {id: profile.id, profile: reminder_params}

expect(response.status).to eq 200
expect(CheckinReminderJob.jobs.size).to eq 1
expect(profile.reload.reminder_job_id).to eq CheckinReminderJob.jobs.first["jid"]
end

it "passes only native JSON types to the job" do
put :update, params: {id: profile.id, profile: reminder_params}

profile_id, reminder_at = CheckinReminderJob.jobs.first["args"]
expect(profile_id).to eq profile.id
expect(reminder_at).to be_a String
expect(Time.parse(reminder_at).utc.strftime("%H:%M")).to eq "20:30"
end
end
end
end
end
Loading