diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ae5be7748d8..9573c04d2ab 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -133,10 +133,12 @@ Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​ [d/DA * When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. * You can remove all the person’s tags by typing `t/` without specifying any tags after it. +* For optional fields (email, emergency contact, address, date of last visit) you can delete them by entering the prefix without specifying any value after. Examples: * `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. -* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +* `edit 2 n/Betsy Crower t/ e/` Edits the name of the 2nd person to be `Betsy Crower`, clears all existing tags and deletes the stored email. + ### Locating persons by name: `find` diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 2d0deb19b9a..5ba866bab9b 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -76,8 +76,9 @@ public static Phone parsePhone(String phone) throws ParseException { public static Optional
parseAddress(Optional address) throws ParseException { requireNonNull(address); - if (address.isEmpty()) { + if (address.isEmpty() || address.get().trim().isEmpty()) { // if an address prefix was never entered by the user + // or an empty string ("") was entered indicating no address return Optional.empty(); } @@ -97,8 +98,9 @@ public static Optional
parseAddress(Optional address) throws Pa public static Optional parseEmail(Optional email) throws ParseException { requireNonNull(email); - if (email.isEmpty()) { + if (email.isEmpty() || email.get().trim().isEmpty()) { // if an email prefix was never entered by the user + // or an empty string ("") was entered indicating no email return Optional.empty(); } String trimmedEmail = email.get().trim(); @@ -144,8 +146,9 @@ public static Optional parseDateOfLastVisit(Optional da throws ParseException { requireNonNull(dateOfLastVisit); - if (dateOfLastVisit.isEmpty()) { + if (dateOfLastVisit.isEmpty() || dateOfLastVisit.get().trim().isEmpty()) { // if dateOfLastVisit prefix was never entered by the user + // or an empty string ("") was entered indicating no date of last visit return Optional.empty(); } @@ -166,8 +169,9 @@ public static Optional parseEmergencyContact(Optional throws ParseException { requireNonNull(emergencyContact); - if (emergencyContact.isEmpty()) { + if (emergencyContact.isEmpty() || emergencyContact.get().trim().isEmpty()) { // if emergencyContact prefix was never entered by the user + // or an empty string ("") was entered indicating no emergency contact return Optional.empty(); } diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java index 4c42060142a..983e469dfc9 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java @@ -64,6 +64,11 @@ public class CommandTestUtil { public static final String DATEOFLASTVISIT_DESC_BOB = " " + PREFIX_DATEOFLASTVISIT + VALID_DATEOFLASTVISIT_BOB; + public static final String ADDRESS_DELETION = " " + PREFIX_ADDRESS; + public static final String EMAIL_DELETION = " " + PREFIX_EMAIL; + public static final String EMERGENCY_CONTACT_DELETION = " " + PREFIX_EMERGENCY_CONTACT; + public static final String DATEOFLASTVISIT_DELETION = " " + PREFIX_DATEOFLASTVISIT; + // whitespace-only names are invalid public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + " "; // 'a' not allowed in phones, emergency contacts diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java index f3d3aed9fb2..7b305dbf114 100644 --- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java @@ -1,12 +1,16 @@ package seedu.address.logic.parser; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DELETION; import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.DATEOFLASTVISIT_DELETION; import static seedu.address.logic.commands.CommandTestUtil.DATEOFLASTVISIT_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.DATEOFLASTVISIT_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DELETION; import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.EMERGENCY_CONTACT_DELETION; import static seedu.address.logic.commands.CommandTestUtil.EMERGENCY_CONTACT_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.EMERGENCY_CONTACT_DESC_BOB; import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; @@ -46,7 +50,6 @@ import seedu.address.logic.Messages; import seedu.address.logic.commands.AddCommand; -import seedu.address.model.person.Address; import seedu.address.model.person.DateOfLastVisit; import seedu.address.model.person.Email; import seedu.address.model.person.EmergencyContact; @@ -226,6 +229,15 @@ public void parse_optionalFieldsMissing_success() { .withTags().withEmergencyContact().build(); assertParseSuccess(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + DATEOFLASTVISIT_DESC_BOB, new AddCommand(expectedPersonWithoutAddressOrEmergencyContact)); + + // Providing empty ("") email, address, dateoflastvisit, emergency contact + Person expectedPersonWithoutAnyOptionalFields = new PersonBuilder(BOB).withEmail().withAddress() + .withDateOfLastVisit().withEmergencyContact().withTags().build(); + assertParseSuccess( + //Note DELETION refers to the empty string ex. EMAIL DELETION = "e/" + parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DELETION + EMERGENCY_CONTACT_DELETION + + ADDRESS_DELETION + DATEOFLASTVISIT_DELETION, + new AddCommand(expectedPersonWithoutAnyOptionalFields)); } @Test @@ -274,12 +286,6 @@ public void parse_invalidValue_failure() { + TAG_DESC_HUSBAND + TAG_DESC_FRIEND + DATEOFLASTVISIT_DESC_BOB, Email.MESSAGE_CONSTRAINTS); - // invalid address - assertParseFailure( - parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC - + TAG_DESC_HUSBAND + TAG_DESC_FRIEND + DATEOFLASTVISIT_DESC_BOB, - Address.MESSAGE_CONSTRAINTS); - // invalid tag assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + INVALID_TAG_DESC + VALID_TAG_FRIEND + DATEOFLASTVISIT_DESC_BOB, Tag.MESSAGE_CONSTRAINTS); diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java index e7583307e34..b62a67ba7cb 100644 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java @@ -1,12 +1,16 @@ package seedu.address.logic.parser; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DELETION; import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.DATEOFLASTVISIT_DELETION; import static seedu.address.logic.commands.CommandTestUtil.DATEOFLASTVISIT_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.DATEOFLASTVISIT_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DELETION; import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; +import static seedu.address.logic.commands.CommandTestUtil.EMERGENCY_CONTACT_DELETION; import static seedu.address.logic.commands.CommandTestUtil.EMERGENCY_CONTACT_DESC_AMY; import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; import static seedu.address.logic.commands.CommandTestUtil.INVALID_DATEOFLASTVISIT_DESC; @@ -41,13 +45,14 @@ import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON; +import java.util.Optional; + import org.junit.jupiter.api.Test; import seedu.address.commons.core.index.Index; import seedu.address.logic.Messages; import seedu.address.logic.commands.EditCommand; import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.person.Address; import seedu.address.model.person.DateOfLastVisit; import seedu.address.model.person.Email; import seedu.address.model.person.EmergencyContact; @@ -100,8 +105,6 @@ public void parse_invalidValue_failure() { assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid email assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); - // invalid address - assertParseFailure(parser, "1" + INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid tag assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid dateOfLastVisit @@ -204,6 +207,21 @@ public void parse_oneFieldSpecified_success() { assertParseSuccess(parser, userInput, expectedCommand); } + @Test + public void parse_optionalFieldDeletion_success() { + //One test case to cover all valid deletions + Index targetIndex = INDEX_THIRD_PERSON; + String userInput = targetIndex.getOneBased() + ADDRESS_DELETION + + EMAIL_DELETION + DATEOFLASTVISIT_DELETION + EMERGENCY_CONTACT_DELETION; + EditPersonDescriptor descriptor = new EditPersonDescriptor(); + descriptor.setAddress(Optional.empty()); + descriptor.setEmail(Optional.empty()); + descriptor.setDateOfLastVisit(Optional.empty()); + descriptor.setEmergencyContact(Optional.empty()); + EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); + assertParseSuccess(parser, userInput, expectedCommand); + } + @Test public void parse_multipleRepeatedFields_failure() { // More extensive testing of duplicate parameter detections is done in diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java index 59956d06e4a..c49afa7b268 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/seedu/address/logic/parser/ParserUtilTest.java @@ -24,16 +24,19 @@ import seedu.address.model.tag.Tag; public class ParserUtilTest { + private static final String EMPTY_ENTRY = " "; + private static final String INVALID_NAME = " \t \n "; private static final String INVALID_PHONE = "+651234"; private static final String INVALID_SHORT_PHONE = "999"; private static final String INVALID_LONG_PHONE = "123456789"; - private static final String INVALID_ADDRESS = " "; private static final String INVALID_EMAIL = "example.com"; private static final String INVALID_EMERGENCY_CONTACT = INVALID_PHONE; private static final String INVALID_TAG = "#friend"; private static final String INVALID_DATEOFLASTVISIT = "13/13/2024"; + private static final String NO_ENTRY = ""; + private static final String VALID_NAME = "Rachel Walker-Runner"; private static final String VALID_PHONE = "12345678"; private static final String VALID_ADDRESS = "123 Main Street #0505"; @@ -114,13 +117,18 @@ public void parsePhone_validValueWithWhitespace_returnsTrimmedPhone() throws Exc } @Test - public void parseAddress_null_optionalEmpty() throws Exception { - assertEquals(Optional.empty(), ParserUtil.parseAddress(Optional.ofNullable((String) null))); + public void parseAddress_emptyValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseAddress(Optional.of(EMPTY_ENTRY))); } @Test - public void parseAddress_invalidValue_throwsParseException() { - assertThrows(ParseException.class, () -> ParserUtil.parseAddress(Optional.of(INVALID_ADDRESS))); + public void parseAddress_noValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseAddress(Optional.of(NO_ENTRY))); + } + + @Test + public void parseAddress_null_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseAddress(Optional.ofNullable((String) null))); } @Test @@ -137,6 +145,17 @@ public void parseAddress_validValueWithWhitespace_returnsTrimmedAddress() throws ParserUtil.parseAddress(Optional.of(addressWithWhitespace))); } + @Test + public void parseEmail_emptyValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseEmail(Optional.of(EMPTY_ENTRY))); + } + + @Test + public void parseEmail_noValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseEmail(Optional.of(NO_ENTRY))); + } + + @Test public void parseEmail_null_optionalEmpty() throws Exception { assertEquals(Optional.empty(), ParserUtil.parseEmail(Optional.ofNullable((String) null))); @@ -207,7 +226,17 @@ public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception { } @Test - public void parseDateOfLastVisit_null_throwsNullPointerException() throws Exception { + public void parseDateOfLastVisit_emptyValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseDateOfLastVisit(Optional.of(EMPTY_ENTRY))); + } + + @Test + public void parseDateOfLastVisit_noValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseDateOfLastVisit(Optional.of(NO_ENTRY))); + } + + @Test + public void parseDateOfLastVisit_null_optionalEmpty() throws Exception { assertEquals(Optional.empty(), ParserUtil.parseDateOfLastVisit(Optional.ofNullable((String) null))); } @@ -233,6 +262,17 @@ public void parseDateOfLastVisit_validValueWithWhitespace_returnsTrimmedDateOfLa ParserUtil.parseDateOfLastVisit(Optional.of(dateOfLastVisitWithWhitespace))); } + @Test + public void parseEmergencyContact_emptyValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseEmergencyContact(Optional.of(EMPTY_ENTRY))); + } + + @Test + public void parseEmergencyContact_noValue_optionalEmpty() throws Exception { + assertEquals(Optional.empty(), ParserUtil.parseEmergencyContact(Optional.of(NO_ENTRY))); + } + + @Test public void parseEmergencyContact_null_optionalEmpty() throws Exception { assertEquals(Optional.empty(), ParserUtil.parseEmergencyContact(Optional.ofNullable((String) null)));