From 16860259074f9a977479008be7530d8bf222eb7f Mon Sep 17 00:00:00 2001 From: Allison Lee Date: Wed, 26 Aug 2026 19:46:29 -0400 Subject: [PATCH] Update Member: Remove email change support --- .../components/MemberProfileForm.tsx | 5 +- .../patchats/api/member/MemberService.java | 15 +++--- .../api/member/MemberControllerTest.java | 26 +---------- .../api/member/MemberServiceTest.java | 46 ++++++++++++++----- .../api/member/MemberTestFixtures.java | 2 +- 5 files changed, 48 insertions(+), 46 deletions(-) diff --git a/js/src/features/member-profile/components/MemberProfileForm.tsx b/js/src/features/member-profile/components/MemberProfileForm.tsx index 17f2dfcc..843c694b 100644 --- a/js/src/features/member-profile/components/MemberProfileForm.tsx +++ b/js/src/features/member-profile/components/MemberProfileForm.tsx @@ -162,9 +162,10 @@ export function MemberProfileForm({ id }: { id: string }) { required type="email" label="Email Address" - description="Use an email address you check regularly, as this is how we will contact you about your matches!" + description="Use an email address you check regularly, as this is how we will contact you about your matches! (Email changes are not currently supported.)" value={values.email} - disabled={!isEditing} + // Always disabled for now until we implement email change verification + disabled onChange={(event) => handleFieldChange("email", event.target.value)} onBlur={() => handleFieldBlur("email")} error={errors.email} diff --git a/src/main/java/org/patinanetwork/patchats/api/member/MemberService.java b/src/main/java/org/patinanetwork/patchats/api/member/MemberService.java index c1246dbe..7d5caffd 100644 --- a/src/main/java/org/patinanetwork/patchats/api/member/MemberService.java +++ b/src/main/java/org/patinanetwork/patchats/api/member/MemberService.java @@ -15,7 +15,6 @@ import org.patinanetwork.patchats.common.web.exception.MemberDuplicateException; import org.patinanetwork.patchats.common.web.exception.MemberNotFoundException; import org.patinanetwork.patchats.common.web.exception.ValidationException; -import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; @Service @@ -73,9 +72,12 @@ public MemberDto updateMember(UpdateMemberRequest request, UUID id) { return MemberDto.from(member); } + if (request.email().isPresent() && !request.email().get().equals(member.getEmail())) { + throw new ValidationException("Email changes are not currently supported"); + } + validateAndUpdate(request.firstName(), member::setFirstName, "firstName", true); validateAndUpdate(request.lastName(), member::setLastName, "lastName", true); - validateAndUpdate(request.email(), member::setEmail, "email", true); validateAndUpdate(request.introduction(), member::setIntroduction, "introduction", true); validateAndUpdate(request.linkedInUrl(), member::setLinkedInUrl, "linkedInUrl", false); validateAndUpdate(request.matchPref(), member::setMatchPref, "matchPref", false); @@ -84,12 +86,9 @@ public MemberDto updateMember(UpdateMemberRequest request, UUID id) { validateAndUpdate(request.topics(), member::setTopics, "topics", false); validateAndUpdate(request.extraNotes(), member::setExtraNotes, "extraNotes", false); - try { - Member updatedMember = memberRepo.updateMember(member).orElseThrow(() -> new MemberNotFoundException(id)); - return MemberDto.from(updatedMember); - } catch (DuplicateKeyException e) { - throw new MemberDuplicateException(member.getEmail()); - } + // Duplicate-email check removed with email-change support; see 512ed6f — revisit once email verification ships + Member updatedMember = memberRepo.updateMember(member).orElseThrow(() -> new MemberNotFoundException(id)); + return MemberDto.from(updatedMember); } private void validateAndUpdate( diff --git a/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java b/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java index f2fa06ef..3fa277f9 100644 --- a/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java +++ b/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java @@ -16,6 +16,7 @@ import java.util.Optional; import java.util.UUID; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.patinanetwork.patchats.api.member.db.repos.MemberFilterCriteria; import org.patinanetwork.patchats.api.member.dto.CreateMemberRequest; @@ -231,30 +232,6 @@ void updateMember_successWithPartialUpdate() throws Exception { .andExpect(jsonPath("$.payload.firstName").value("UpdatedFirstName")); } - @Test - void updateMember_badRequestWhenBlankRequiredField() throws Exception { - final UUID id = UUID.randomUUID(); - final UpdateMemberRequest request = new UpdateMemberRequest( - Optional.of(""), - Optional.of("UpdatedLastName"), - Optional.of("updated@example.com"), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty(), - Optional.empty()); - - when(memberService.updateMember(any(), any())).thenThrow(new ValidationException("firstName cannot be empty")); - - mockMvc.perform(patch("/api/members/{id}", id) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message").value("firstName cannot be empty")); - } - @Test void updateMember_notFoundWhenMemberDoesNotExist() throws Exception { final UUID id = UUID.randomUUID(); @@ -280,6 +257,7 @@ void updateMember_notFoundWhenMemberDoesNotExist() throws Exception { .andExpect(jsonPath("$.success").value(false)); } + @Disabled("Email changes are not currently supported, so this test is not applicable.") @Test void updateMember_conflictWhenEmailIsDuplicate() throws Exception { final UUID id = UUID.randomUUID(); diff --git a/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java b/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java index f14a39c9..d0bab771 100644 --- a/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java +++ b/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Optional; import java.util.UUID; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.patinanetwork.patchats.api.member.db.models.Member; @@ -23,6 +24,7 @@ import org.patinanetwork.patchats.api.member.dto.UpdateMemberRequest; import org.patinanetwork.patchats.common.web.exception.MemberDuplicateException; import org.patinanetwork.patchats.common.web.exception.MemberNotFoundException; +import org.patinanetwork.patchats.common.web.exception.ValidationException; import org.springframework.dao.DuplicateKeyException; class MemberServiceTest { @@ -272,7 +274,6 @@ void updateMemberSuccessWithAllFields() { assertEquals("UpdatedFirstName", captured.getFirstName()); assertEquals("UpdatedLastName", captured.getLastName()); - assertEquals("updated@example.com", captured.getEmail()); assertEquals("https://linkedin.com/in/updated", captured.getLinkedInUrl()); assertEquals("Updated intro", captured.getIntroduction()); assertEquals("Mentor - I am looking for guidance from someone with more experience", captured.getMatchPref()); @@ -282,6 +283,7 @@ void updateMemberSuccessWithAllFields() { assertEquals("Notes", captured.getExtraNotes()); } + @Disabled("Email changes are not currently supported, so this test is not applicable.") @Test void updateMember_throwsExceptionWhenEmailIsDuplicate() { final UUID id = UUID.randomUUID(); @@ -310,11 +312,39 @@ void updateMember_throwsExceptionWhenEmailIsDuplicate() { } @Test - void updateMember_successWhenUpdatingWithSameEmail() { + void updateMember_throwsValidationExceptionWhenEmailIsChanged() { final UUID id = UUID.randomUUID(); final UpdateMemberRequest request = new UpdateMemberRequest( Optional.empty(), Optional.empty(), + Optional.of("new@example.com"), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty()); + + final Member existingMember = Member.builder() + .id(id) + .firstName("John") + .lastName("Doe") + .email("john@example.com") + .build(); + + when(memberRepo.getMemberById(id)).thenReturn(Optional.of(existingMember)); + + assertThrows(ValidationException.class, () -> memberService.updateMember(request, id)); + verify(memberRepo, never()).updateMember(any()); + } + + @Test + void updateMember_successWhenUpdatingOtherFieldsWithUnchangedEmail() { + final UUID id = UUID.randomUUID(); + final UpdateMemberRequest request = new UpdateMemberRequest( + Optional.of("UpdatedFirstName"), + Optional.empty(), Optional.of("john@example.com"), Optional.empty(), Optional.empty(), @@ -329,25 +359,19 @@ void updateMember_successWhenUpdatingWithSameEmail() { .firstName("John") .lastName("Doe") .email("john@example.com") - .linkedInUrl("https://linkedin.com/in/john") - .introduction("intro") - .matchPref("Mentor") - .industryPref("Tech") - .rolePref("Engineer") - .topics("AI") - .extraNotes("notes") .build(); when(memberRepo.getMemberById(id)).thenReturn(Optional.of(existingMember)); - when(memberRepo.updateMember(any())).thenReturn(Optional.of(existingMember)); + when(memberRepo.updateMember(any(Member.class))).thenReturn(Optional.of(existingMember)); final ArgumentCaptor captor = ArgumentCaptor.forClass(Member.class); memberService.updateMember(request, id); + verify(memberRepo).updateMember(captor.capture()); final Member captured = captor.getValue(); + assertEquals("UpdatedFirstName", captured.getFirstName()); assertEquals("john@example.com", captured.getEmail()); - verify(memberRepo, never()).getMemberByEmail(any()); } @Test diff --git a/src/test/java/org/patinanetwork/patchats/api/member/MemberTestFixtures.java b/src/test/java/org/patinanetwork/patchats/api/member/MemberTestFixtures.java index 78d79101..524c3c56 100644 --- a/src/test/java/org/patinanetwork/patchats/api/member/MemberTestFixtures.java +++ b/src/test/java/org/patinanetwork/patchats/api/member/MemberTestFixtures.java @@ -22,7 +22,7 @@ final class MemberTestFixtures { static final UpdateMemberRequest UPDATE_REQUEST_ALL_FIELDS = new UpdateMemberRequest( Optional.of("UpdatedFirstName"), Optional.of("UpdatedLastName"), - Optional.of("updated@example.com"), + Optional.empty(), // Email changes are not currently supported Optional.of("https://linkedin.com/in/updated"), Optional.of("Updated intro"), Optional.of("Mentor - I am looking for guidance from someone with more experience"),