-module(logic_waitlist_tests). -include_lib("eunit/include/eunit.hrl"). -include("records.hrl"). -define(TABLES, [user, calendar, event, booking, waitlist_entry, subscription, notification, calendar_specialist]). setup() -> eh_test_support:start_mnesia(), eh_test_support:ensure_tables(?TABLES), ok. cleanup(_) -> eh_test_support:delete_tables(?TABLES), eh_test_support:stop_mnesia(), ok. logic_waitlist_test_() -> {foreach, fun setup/0, fun cleanup/1, [ {"join rejected when waitlist disabled", fun test_disabled/0}, {"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}, {"leave waitlist", fun test_leave/0} ]}. create_user() -> Id = infra_utils:generate_id(8), U = #user{ id = Id, email = <>, password_hash = <<"h">>, role = user, status = active, created_at = calendar:universal_time(), updated_at = calendar:universal_time() }, mnesia:dirty_write(U), Id. ensure_sub(OwnerId) -> {ok, _} = core_subscription:create(OwnerId, monthly, true), ok. create_cal(OwnerId, Waitlist) -> ensure_sub(OwnerId), Settings = #{<<"waitlist_enabled">> => Waitlist}, {ok, Cal} = core_calendar:create(OwnerId, <<"Studio">>, <<"">>, auto, commercial), {ok, Cal2} = core_calendar:update(Cal#calendar.id, [{settings, Settings}]), Cal2. create_event(CalId, Cap) -> Start = eh_test_support:future_start(), {ok, Ev} = core_event:create(CalId, <<"Slot">>, Start, 60), {ok, Ev2} = core_event:update(Ev#event.id, [{capacity, Cap}]), Ev2#event.id. test_disabled() -> Owner = create_user(), Guest = create_user(), Cal = create_cal(Owner, false), EventId = create_event(Cal#calendar.id, 1), {ok, _} = logic_booking:create_booking(Guest, EventId), Other = create_user(), ?assertEqual({error, waitlist_disabled}, logic_waitlist:join(Other, EventId)). test_join_full() -> Owner = create_user(), Guest = create_user(), Cal = create_cal(Owner, true), EventId = create_event(Cal#calendar.id, 1), {ok, _} = logic_booking:create_booking(Guest, EventId), Other = create_user(), {ok, Body} = logic_waitlist:join(Other, EventId), ?assertEqual(1, maps:get(position, Body)). test_not_full() -> Owner = create_user(), Cal = create_cal(Owner, true), EventId = create_event(Cal#calendar.id, 2), ?assertEqual({error, not_full}, logic_waitlist:join(create_user(), EventId)). test_promote_on_cancel() -> application:set_env(eventhub, smtp_host, undefined), Owner = create_user(), Guest = create_user(), Waiter = create_user(), 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), {ok, WaiterBookings} = core_booking:list_by_user(Waiter), Active = [B || B <- WaiterBookings, B#booking.event_id =:= EventId, B#booking.status =:= confirmed orelse B#booking.status =:= pending], ?assertEqual(1, length(Active)), ?assertEqual({error, not_found}, core_waitlist:get_waiting(EventId, Waiter)). test_leave() -> Owner = create_user(), Guest = create_user(), Waiter = create_user(), Cal = create_cal(Owner, true), EventId = create_event(Cal#calendar.id, 1), {ok, _} = logic_booking:create_booking(Guest, EventId), {ok, _} = logic_waitlist:join(Waiter, EventId), ?assertEqual(ok, logic_waitlist:leave(Waiter, EventId)), ?assertEqual({error, not_found}, core_waitlist:get_waiting(EventId, Waiter)).