Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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());
Comment thread
Allimonae marked this conversation as resolved.
}
// 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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -231,30 +232,6 @@ void updateMember_successWithPartialUpdate() throws Exception {
.andExpect(jsonPath("$.payload.firstName").value("UpdatedFirstName"));
}

@Test
void updateMember_badRequestWhenBlankRequiredField() throws Exception {
Comment thread
Allimonae marked this conversation as resolved.
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();
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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());
Expand All @@ -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();
Expand Down Expand Up @@ -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(),
Expand All @@ -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<Member> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
Allimonae marked this conversation as resolved.
Optional.of("https://linkedin.com/in/updated"),
Optional.of("Updated intro"),
Optional.of("Mentor - I am looking for guidance from someone with more experience"),
Expand Down
Loading