defmodule SpazioSolazzo.Accounts.UserTest do use ExUnit.Case, async: true use SpazioSolazzo.DataCase alias SpazioSolazzo.Accounts.User alias SpazioSolazzo.Accounts alias SpazioSolazzo.BookingSystem alias SpazioSolazzo.BookingSystem.Booking describe "update_profile" do test "allows user to update their own name and phone_number" do user = register_user("test@example.com") {:ok, updated_user} = Accounts.update_profile(user, "Updated Name", "+9876543210", actor: user) assert updated_user.name == "Updated Name" assert updated_user.phone_number == "+9876543210" assert to_string(updated_user.email) == "test@example.com" end test "prevents user from updating another user's profile" do user1 = register_user("user1@example.com") user2 = register_user("user2@example.com") result = Accounts.update_profile(user2, "Hacker", "1235837", actor: user1) assert {:error, %Ash.Error.Forbidden{}} = result end test "validates that name is present" do user = register_user("test@example.com") result = Accounts.update_profile(user, "", "+9876543210", actor: user) assert {:error, changeset} = result assert Enum.any?(changeset.errors, fn error -> error.field == :name end) end end describe "terminate_account with delete_history: false (anonymization)" do test "deletes user but preserves bookings with nullified user_id" do user = register_user("delete@example.com") {space, _time_slot} = create_booking_fixtures() {:ok, booking1} = BookingSystem.create_booking( space.id, user.id, Date.utc_today(), ~T[09:00:00], ~T[11:00:00], "John Doe", "john@example.com", "+393627384027", "test booking 1" ) {:ok, booking2} = BookingSystem.create_booking( space.id, user.id, Date.add(Date.utc_today(), 1), ~T[09:00:00], ~T[11:00:00], "Jane Doe", "jane@example.com", "+393627384028", "test booking 2" ) booking1_id = booking1.id booking2_id = booking2.id :ok = Accounts.terminate_account(user, false, actor: user) assert {:error, _} = Ash.get(User, user.id) {:ok, preserved_booking1} = Ash.get(Booking, booking1_id) {:ok, preserved_booking2} = Ash.get(Booking, booking2_id) assert preserved_booking1.user_id == nil assert preserved_booking2.user_id == nil assert preserved_booking1.customer_name == "John Doe" assert preserved_booking2.customer_name == "Jane Doe" end test "cancels future confirmed bookings before anonymizing" do user = register_user("cancel@example.com") {space, _time_slot} = create_booking_fixtures() future_date = Date.add(Date.utc_today(), 7) {:ok, future_booking} = BookingSystem.create_booking( space.id, user.id, future_date, ~T[09:00:00], ~T[11:00:00], "Future User", "future@example.com", "+393627384029", "future booking" ) future_booking_id = future_booking.id :ok = Accounts.terminate_account(user, false, actor: user) {:ok, cancelled_booking} = Ash.get(Booking, future_booking_id, authorize?: false) assert cancelled_booking.state == :cancelled assert cancelled_booking.user_id == nil end end describe "terminate_account with delete_history: true (hard delete)" do test "deletes user and all associated bookings permanently" do user = register_user("harddelete@example.com") {space, _time_slot} = create_booking_fixtures() {:ok, booking1} = BookingSystem.create_booking( space.id, user.id, Date.utc_today(), ~T[09:00:00], ~T[11:00:00], "Delete Me", "deleteme@example.com", "+393627384031", "test booking" ) {:ok, booking2} = BookingSystem.create_booking( space.id, user.id, Date.add(Date.utc_today(), 1), ~T[09:00:00], ~T[11:00:00], "Delete Me Too", "deletemetoo@example.com", "+393627384032", "test booking 2" ) booking1_id = booking1.id booking2_id = booking2.id :ok = Accounts.terminate_account(user, true, actor: user) assert {:error, _} = Ash.get(User, user.id) assert {:error, _} = Ash.get(Booking, booking1_id, authorize?: false) assert {:error, _} = Ash.get(Booking, booking2_id, authorize?: false) end end describe "terminate_account authorization" do test "prevents user from deleting another user's account" do user1 = register_user("user1@example.com") user2 = register_user("user2@example.com") result = Accounts.terminate_account(user2, false, actor: user1) assert {:error, %Ash.Error.Forbidden{}} = result end end defp create_booking_fixtures do unique_id = :erlang.unique_integer([:positive, :monotonic]) {:ok, space} = BookingSystem.create_space( "Test Space #{unique_id}", "test-space-#{unique_id}", "Test description", 10 ) {:ok, time_slot} = BookingSystem.create_time_slot_template( ~T[09:00:00], ~T[18:00:00], :monday, space.id ) {space, time_slot} end end