diff --git a/test/unit/eh_test_support.erl b/test/unit/eh_test_support.erl index 060545a..bf8b08f 100755 --- a/test/unit/eh_test_support.erl +++ b/test/unit/eh_test_support.erl @@ -96,6 +96,7 @@ ensure_indexes(Tables) when is_list(Tables) -> {verification, [user_id]}, {password_reset, [user_id]}, {notification, [user_id, is_read]}, + {push_subscription, [user_id, endpoint]}, {auth_session, [family_id, subject_id]}, {report, [resolved_by]}, {ticket, [assigned_to]} @@ -179,6 +180,8 @@ table_opts(admin_audit) -> [{ram_copies, [node()]}, {attributes, record_info(fields, admin_audit)}]; table_opts(notification) -> [{ram_copies, [node()]}, {attributes, record_info(fields, notification)}]; +table_opts(push_subscription) -> + [{ram_copies, [node()]}, {attributes, record_info(fields, push_subscription)}]; table_opts(stats_counter) -> [{ram_copies, [node()]}, {attributes, record_info(fields, stats_counter)}]; table_opts(stats_daily) -> diff --git a/test/unit/logic_booking_tests.erl b/test/unit/logic_booking_tests.erl index 38cd873..33f6f6a 100755 --- a/test/unit/logic_booking_tests.erl +++ b/test/unit/logic_booking_tests.erl @@ -3,7 +3,7 @@ -include("records.hrl"). -define(TABLES, [user, calendar, event, booking, admin, subscription, calendar_specialist, - recurrence_exception, notification]). + recurrence_exception, notification, push_subscription]). setup() -> eh_test_support:start_mnesia(), @@ -57,7 +57,9 @@ logic_booking_test_() -> {"Process timeout expires past pending", fun test_process_timeout_expires_past/0}, {"Reminder sends once within lead window", fun test_reminder_within_window/0}, {"Reminder skipped outside lead window", fun test_reminder_outside_window/0}, - {"Reminder skipped for pending", fun test_reminder_skips_pending/0} + {"Reminder skipped for pending", fun test_reminder_skips_pending/0}, + {"Reminder skips email when prefs email=false", fun test_reminder_email_pref_off/0}, + {"Reminder calls web_push when prefs push=true", fun test_reminder_web_push/0} ]}. %% Вспомогательные функции @@ -598,3 +600,74 @@ test_reminder_skips_pending() -> {ok, Stored} = core_booking:get_by_id(Booking#booking.id), ?assertEqual(false, Stored#booking.reminder_sent), application:unset_env(eventhub, reminder_lead_hours). + +test_reminder_email_pref_off() -> + application:set_env(eventhub, reminder_lead_hours, 24), + Self = self(), + application:set_env(eventhub, smtp_host, "smtp.test"), + application:set_env(eventhub, smtp_deliver, + fun(_From, To, Raw, _Opts) -> + Self ! {smtp, To, Raw}, + {ok, mock} + end), + OwnerId = create_test_user(user), + ParticipantId = create_test_user(user), + {ok, _} = logic_notification_prefs:put_prefs(ParticipantId, #{email => false, push => true}), + CalendarId = create_test_calendar(OwnerId, auto), + EventId = create_test_event_at(CalendarId, hours_from_now(2)), + {ok, Booking} = logic_booking:create_booking(ParticipantId, EventId), + ok = logic_booking:process_reminders(), + receive + {smtp, _, _} -> error(unexpected_email_when_pref_off) + after 300 -> + ok + end, + {ok, Stored} = core_booking:get_by_id(Booking#booking.id), + ?assertEqual(true, Stored#booking.reminder_sent), + Notifs = core_notification:list_by_user(ParticipantId), + ?assert(lists:any(fun(#notification{type = event_reminder}) -> true; (_) -> false end, + Notifs)), + application:unset_env(eventhub, smtp_host), + application:unset_env(eventhub, smtp_deliver), + application:unset_env(eventhub, reminder_lead_hours). + +test_reminder_web_push() -> + application:set_env(eventhub, reminder_lead_hours, 24), + application:set_env(eventhub, vapid_public_key, <<"BKtestpublickey0123456789abcdef">>), + application:set_env(eventhub, vapid_private_key, <<"testprivatekey0123456789abcdef">>), + Self = self(), + application:set_env(eventhub, web_push_deliver, + fun(Ep, _P256, _Auth, Payload, _Pub, _Priv) -> + Self ! {push, Ep, Payload}, + ok + end), + OwnerId = create_test_user(user), + ParticipantId = create_test_user(user), + {ok, _} = logic_notification_prefs:put_prefs(ParticipantId, #{email => false, push => true}), + {ok, _} = core_push_subscription:upsert( + ParticipantId, + <<"https://push.example/endpoint-reminder">>, + <<"p256dh-test">>, + <<"auth-test">>), + CalendarId = create_test_calendar(OwnerId, auto), + EventId = create_test_event_at(CalendarId, hours_from_now(2)), + {ok, _} = logic_booking:create_booking(ParticipantId, EventId), + ok = logic_booking:process_reminders(), + receive + {push, Ep, Payload} -> + ?assertEqual(<<"https://push.example/endpoint-reminder">>, Ep), + ?assert(binary:match(Payload, <<"Напоминание"/utf8>>) =/= nomatch) + after 1000 -> + error(timeout_web_push) + end, + {ok, _} = logic_notification_prefs:put_prefs(ParticipantId, #{email => false, push => false}), + ok = logic_web_push:send(ParticipantId, <<"t">>, <<"b">>, <<"/x">>), + receive + {push, _, _} -> error(push_should_be_skipped) + after 300 -> + ok + end, + application:unset_env(eventhub, web_push_deliver), + application:unset_env(eventhub, vapid_public_key), + application:unset_env(eventhub, vapid_private_key), + application:unset_env(eventhub, reminder_lead_hours). diff --git a/test/unit/logic_waitlist_tests.erl b/test/unit/logic_waitlist_tests.erl index e33956f..3ef991d 100644 --- a/test/unit/logic_waitlist_tests.erl +++ b/test/unit/logic_waitlist_tests.erl @@ -3,7 +3,7 @@ -include("records.hrl"). -define(TABLES, [user, calendar, event, booking, waitlist_entry, subscription, - notification, calendar_specialist]). + notification, calendar_specialist, push_subscription]). setup() -> eh_test_support:start_mnesia(), @@ -21,6 +21,7 @@ logic_waitlist_test_() -> {"join when full and enabled", fun test_join_full/0}, {"join rejected when not full", fun test_not_full/0}, {"promote on cancel", fun test_promote_on_cancel/0}, + {"promote respects email=false and sends push", fun test_promote_prefs_push/0}, {"leave waitlist", fun test_leave/0} ]}. @@ -94,6 +95,50 @@ test_promote_on_cancel() -> ?assertEqual(1, length(Active)), ?assertEqual({error, not_found}, core_waitlist:get_waiting(EventId, Waiter)). +test_promote_prefs_push() -> + Self = self(), + application:set_env(eventhub, smtp_host, "smtp.test"), + application:set_env(eventhub, smtp_deliver, + fun(_From, To, Raw, _Opts) -> + Self ! {smtp, To, Raw}, + {ok, mock} + end), + application:set_env(eventhub, vapid_public_key, <<"BKtestpublic">>), + application:set_env(eventhub, vapid_private_key, <<"testprivate">>), + application:set_env(eventhub, web_push_deliver, + fun(Ep, _P, _A, Payload, _Pub, _Priv) -> + Self ! {push, Ep, Payload}, + ok + end), + Owner = create_user(), + Guest = create_user(), + Waiter = create_user(), + {ok, _} = logic_notification_prefs:put_prefs(Waiter, #{email => false, push => true}), + {ok, _} = core_push_subscription:upsert( + Waiter, <<"https://push.example/waitlist">>, <<"p256">>, <<"auth">>), + Cal = create_cal(Owner, true), + EventId = create_event(Cal#calendar.id, 1), + {ok, Booking} = logic_booking:create_booking(Guest, EventId), + {ok, _} = logic_waitlist:join(Waiter, EventId), + {ok, _} = logic_booking:cancel_booking(Booking#booking.id, Guest), + receive + {smtp, _, _} -> error(unexpected_waitlist_email) + after 300 -> + ok + end, + receive + {push, Ep, Payload} -> + ?assertEqual(<<"https://push.example/waitlist">>, Ep), + ?assert(binary:match(Payload, <<"листа ожидания"/utf8>>) =/= nomatch) + after 1000 -> + error(timeout_waitlist_push) + end, + application:unset_env(eventhub, smtp_host), + application:unset_env(eventhub, smtp_deliver), + application:unset_env(eventhub, web_push_deliver), + application:unset_env(eventhub, vapid_public_key), + application:unset_env(eventhub, vapid_private_key). + test_leave() -> Owner = create_user(), Guest = create_user(),