Developer Guide
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
-
Appendix: Requirements
- Product scope
- User stories
-
Use cases
- Use Case: UC01 - Getting Help
- Use Case: UC02 - Add a contact
- Use Case: UC03 - Edit a contact
- Use Case: UC04 - Delete a contact
- Use Case: UC05 - Add a tag to an existing contact
- Use Case: UC06 - Remove a Tag from a Contact
- Use Case: UC07 - Clearing all tags of a type from a contact
- Use Case: UC08 - Listing All Contacts
- Use Case: UC09 - Sorting contacts
- Use Case: UC10 - Search contacts
- Use Case: UC11 - Undo previous action
- Use Case: UC12 - Navigating Command History
- Use Case: UC13 - Clearing all contacts
- Use Case: UC14 - Exiting
- Non-Functional Requirements
- Glossary
- Appendix: Instructions for manual testing
Acknowledgements
- Libraries used: JavaFX, Jackson, JUnit5
- This project is based on the AddressBook-Level3 project created by the SE-EDU initiative.
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.puml files used to create diagrams are in this document docs/diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Architecture

The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main (consisting of classes Main and MainApp) is in charge of the app launch and shut down.
- At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
- At shut down, it shuts down the other components and invokes cleanup methods where necessary.
The bulk of the app’s work is done by the following four components:
-
UI: The UI of the App. -
Logic: The command executor. -
Model: Holds the data of the App in memory. -
Storage: Reads data from, and writes data to, the hard disk.
Commons represents a collection of classes used by multiple other components.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete i/1.

Each of the four main components (also shown in the diagram above),
- defines its API in an
interfacewith the same name as the Component. - implements its functionality using a concrete
{Component Name}Managerclass (which follows the corresponding APIinterfacementioned in the previous point.
For example, the Logic component defines its API in the Logic.java interface and implements its functionality using the LogicManager.java class which follows the Logic interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component’s being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.

The sections below give more details of each component.
UI component
The API of this component is specified in Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class which captures the commonalities between classes that represent parts of the visible GUI.
The UI component uses the JavaFX UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml
The UI component,
- executes user commands using the
Logiccomponent. - listens for changes to
Modeldata so that the UI can be updated with the modified data. - keeps a reference to the
Logiccomponent, because theUIrelies on theLogicto execute commands. - depends on some classes in the
Modelcomponent, as it displaysPersonobject residing in theModel.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic component:

The sequence diagram below illustrates the interactions within the Logic component, taking execute("delete i/1") API call as an example.

DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
How the Logic component works:
- When
Logicis called upon to execute a command,LogicManagerpasses the user input toAddressBookParser. -
AddressBookParseridentifies the command word and delegates to the corresponding parser (e.g.,DeleteCommandParser) to construct aCommandobject. -
LogicManagerexecutes the command against theModel. - If the command is undoable (
command.isUndoable()),LogicManagerpushes it to an internal undo history stack. - If the command is
undo,LogicManagerhandles it directly by invokingundo(model)on the most recent undoable command in that history stack. More details on the undo feature are provided in the Current Undo feature section under Implementation. - After command execution,
LogicManagerpersists changes throughStorage, then returns aCommandResultto the caller.
Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:

How the parsing works:
-
AddressBookParserroutes each command to anXYZCommandParser(XYZis a placeholder for the specific command name, e.g.,AddCommandParser) that validates input and creates anXYZCommandobject. - Commands with no parameters (
list,clear,exit,undo) are validated directly inAddressBookParser; any extra arguments are rejected. - Most command parsers use
ArgumentTokenizerandParserUtilhelpers to enforce:- required/optional prefixes,
- duplicate-prefix checks for single-valued fields,
- detection of invalid or unexpected prefixes,
- command-specific constraints (e.g., exactly one of
i/ore/fordelete).
- All
XYZCommandParserclasses implement theParserinterface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java

The Model component,
- stores the address book data i.e., all
Personobjects (which are contained in aUniquePersonListobject). - A person is considered a duplicate if another person already has the same email, or the same Telegram handle ignoring case.
- stores the currently ‘selected’
Personobjects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Person>that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores a
UserPrefobject that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPrefobject. - does not depend on any of the other three components (as the
Modelrepresents data entities of the domain, they should make sense on their own without depending on other components)
Tag list in the AddressBook, which Person references. This allows AddressBook to only require one Tag object per unique tag, instead of each Person needing their own Tag objects.
Storage component
API : Storage.java

The Storage component,
- can save both address book data and user preference data in JSON format, and read them back into corresponding objects.
- inherits from both
AddressBookStorageandUserPrefsStorage, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Modelcomponent (because theStoragecomponent’s job is to save/retrieve objects that belong to theModel)
Adapter pattern for JSON serialization
The Storage component uses an adapter pattern to bridge between the domain model and JSON representation. Three adapter classes handle the conversion:
-
JsonSerializableAddressBook— wraps the entire address book for serialization; itstoModelType()method converts back to aReadOnlyAddressBook, checking for duplicate persons in the process. -
JsonAdaptedPerson— represents a singlePersonin JSON form. The fieldsphoneandtelegramHandleare optional (nullable);nameandemailare required.toModelType()validates each field and throwsIllegalValueExceptionif any value is invalid. -
JsonAdaptedTag— represents a singleTag, storing bothtagNameandtagType.
JSON data format
Data is stored in two JSON files:
-
data/addressbook.json— contact list:{ "addressbook": { "persons": [ { "name": "Alex Yeoh", "phone": "87438807", "email": "alexyeoh@example.com", "telegramHandle": "alexyeoh", "tags": [{ "tagName": "cs2103t", "tagType": "COURSE" }] } ] } } -
preferences.json— GUI window size/position and the address book file path:{ "guiSettings": { "windowWidth": 740.0, "windowHeight": 574.0, "windowCoordinates": { "x": 100, "y": 100 } }, "addressBookFilePath": "data/addressbook.json" }
Error handling on startup
When CampusBridge starts, it attempts to read the address book file and handles three cases:
- File not found — sample data is loaded and the file is created on the next save or exit.
- File is malformed or contains invalid data — an empty address book is used and a warning is logged; the corrupted file is left untouched.
- File is valid — data is loaded normally.
Common classes
Classes used by multiple components are in the seedu.address.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Add feature
Implementation
The add command is implemented using AddCommandParser and AddCommand.
When the user enters an add command, AddressBookParser delegates the input to AddCommandParser. AddCommandParser tokenizes the input using only the prefixes supported by add: n/, e/, p/, and h/.
The parser enforces the following rules:
-
n/NAMEande/EMAILare compulsory. -
p/PHONEandh/TELEGRAM_HANDLEare optional. - Values are trimmed before validation.
- Repeated single-valued prefixes are rejected.
- Any non-empty preamble is rejected.
- Known prefixes belonging to other commands, such as
t/,tr/,tc/,tg/,i/,o/, andr/, are treated as unexpected extra input in anaddcommand.
After tokenization, AddCommandParser uses ParserUtil to validate and convert each supplied value into the corresponding model type. It then constructs a Person object and returns an AddCommand.
The sequence diagram below illustrates the interactions within the Logic component for a typical successful add command.

When AddCommand executes, it first checks for duplicate conflicts using model.getDuplicateConflict(toAdd). If a duplicate email, duplicate Telegram handle, or both are detected, the command fails. Otherwise, the person is added to the model and a CommandResult is returned. If the added person’s email is not an NUS-domain email, the success message also includes a warning.
AddCommand is undoable. Undoing an add removes the previously added person, unless that person no longer exists in the model.
Duplicate detection
Duplicate detection for add is based on Person#isSamePerson(...).
Two persons are considered the same person if they have:
- the same email, or
- the same non-null Telegram handle.
This identity rule is used by UniquePersonList when adding and updating persons. As a result, the add command rejects contacts that duplicate either an existing email or an existing Telegram handle.
Current Undo feature
Current Implementation
Currently, the undo feature is implemented using the Command pattern, where each undoable command encapsulates its own undo logic. The overall undo process is managed by LogicManager.
When an undoable command is executed, it is added to an internal stack (undoHistory : Deque<Command>) maintained by LogicManager.
When the undo command is invoked, LogicManager retrieves the most recent command from undoHistory using peek(). The undo(Model) method of that command is then executed to revert its effects. If the undo operation is successful, the command is removed from the stack using pop().
This design ensures that each command is responsible for reversing its own changes, providing flexibility and adhering to the Command pattern.
The following sequence diagram illustrates how the undo operation is executed:

The following class diagram shows the structure of the undo feature:

The following Activity diagram illustrates the control flow of command execution in the undo feature.

Note: Undo methods in commands directly interact with the Model to revert changes. Hence, we are not having an object diagram here. UI and Storage components are omitted from the diagrams as they are not directly involved in the undo mechanism.
Design considerations:
Aspect: How undo & redo executes:
-
Alternative 1 : Saves the entire address book.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2 (current choice): Individual command knows how to undo by
itself.
- Pros: Will use less memory (e.g. for
delete, just save the person being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
{more aspects and alternatives to be added}
[Proposed] Data archiving
{Explain here how the data archiving feature will be implemented}
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile: NUS undergraduate students who
- Need to organize contact information of their Professors, Teaching Assistants and Groupmates.
- Values efficiency and prefers tools that save time and reduce friction.
- Prefer using CLI over GUI.
Value proposition: CampusBridge helps NUS undergraduate students to organize and access contact information for their academic peers across different modules and faculties.
It does so by providing a centralized, easy-to-use system to save, search, and manage academic contacts efficiently.
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
Current version
| Priority | As a … | I can … | So that I can… |
|---|---|---|---|
* * * |
user | add a contact | store and organize important academic contact information in one place |
* * * |
user | view all my contacts | quickly see everyone in one place |
* * * |
user | delete a contact | keep my contact list accurate and organized |
* * * |
user | edit a specific contact | quickly correct mistakes in their contact information |
* * * |
user | exit the application | safely close CampusBridge when I am done using it |
* * * |
user | have my contacts saved automatically | prevent losing my data when the application closes |
* * * |
user | validate my input | minimize incorrect information |
* * * |
new user | see clear error messages | understand what went wrong and correct my input without feeling confused |
* * * |
regular user | search contacts by name, email and tags | quickly find someone |
* * * |
new user | view help details | see specific examples and parameter requirements for that command |
* * |
regular user | sort contacts by name, email, or phone in ascending or descending order | browse them more easily |
* * |
new user | view preloaded sample modules and contacts | understand the app’s layout and value without adding real data |
* * |
user | add new tags to an existing contact | keep their information updated as the semester evolves |
* * |
user | delete specific tags from a contact without deleting the entire contact | keep my contact information accurate |
* * |
user | clear all tags from a contact | reset the contact’s categorization without manually deleting every individual tag |
* * |
expert user | undo my last action | instantly revert an accidental deletion without stress |
* * |
expert user | have keyboard shortcuts | operate the system efficiently |
* * |
expert user | copy any contact field | efficiently transfer information to other applications without manual typing |
* * |
expert user | view colour-coded tags | quickly identify and prioritize important information. |
* * |
regular user | navigate command history | execute or modify past commands without retyping them |
Near-future version
| Priority | As a … | I can … | So that I can… |
|---|---|---|---|
* |
user | export contact data in a human-readable format like JSON | can edit it easily |
* |
regular user | mark a preferred contact method | know the fastest way to reach someone |
* |
regular user | mark certain contacts as favorites | keep my most important connections easily accessible at the top of my list |
* |
frequent user | add notes to contacts | store useful contextual information |
* |
fast typing user | use short aliases for commands | minimize keystrokes |
* |
forgetful student | see a list of “Available Now” contacts based on their office hours | know exactly who I want to visit for a walk-in consultation |
* |
regular user | create a personal profile | tailor the application experience to my specific preferences and needs |
* |
user | view a list of command history | recall what I just changed |
* |
advanced user | bulk add contacts at once | save time when entering many contacts |
* |
advanced user | bulk delete contacts at once | remove outdated or unnecessary contacts efficiently |
* |
advanced user | bulk edit contacts at once | manage large contact groups with minimal effort |
* |
user managing multiple semesters | toggle between “current semester” and “past semesters” views | reference old contacts without cluttering my main screen |
* |
user desiring full control | customize the GUI theme | personalize my experience |
* |
regular user | create “sub-groups” for teammates within a module | manage project-specific communication efficiently |
* |
frequent user | set custom reminders for prof/TA office hours | stay on top of opportunities for academic help |
* |
new user | import my existing contacts | avoid manually adding them |
* |
user with many past contacts | archive old semester contacts | have my active list remain uncluttered and focused on current needs |
* |
user | add my current semester’s modules by searching NUS module codes | categorize contacts accurately and save time |
See the full list on GitHub
Use cases
(For all use cases below, the System is the CampusBridge and the Actor is the user, unless specified otherwise)
Use Case: UC01 - Getting Help
Preconditions: Application is running
MSS:
- User requests for help.
- CampusBridge displays the relevant section of the user guide.
Extension:
- 1a. User provides an unrecognised command name.
- 1a1. CampusBridge shows an error listing all valid commands. Use case ends.
- 1b. User provides more than one word.
- 1b1. CampusBridge shows an invalid command format error. Use case ends.
Use case ends.
Use Case: UC02 - Add a contact
Preconditions: Application is running
MSS:
- User requests to add a contact.
- User provides the contact details.
- CampusBridge validates the input.
- CampusBridge adds the contact and updates the contact list.
- CampusBridge shows a success message.
Use case ends.
Extension:
- 3a. Input does not follow the specified format.
- 3a1. CampusBridge shows an error message indicating the invalid format.
- 3a2. CampusBridge requests the user to re-enter input.
- 3a3. User enters a new input.
Steps 3a1 - 3a3 are repeated until input is valid. Use case resumes at step 4.
- 3b. Email or Telegram handle already exists in the contact list.
- 3b1. CampusBridge shows a failure message indicating that the contact already exists.
Use case ends.
- 4a. Contact cannot be added.
- 4a1. CampusBridge shows an error message indicating the contact could not be added.
Use case ends.
- 4b. Storage file cannot be written or accessed.
- 4b1. CampusBridge shows an error message indicating the contact list could not be saved.
Use case ends.
Use Case: UC03 - Edit a contact
Preconditions: Application is running and the user has added a contact.
MSS:
- User requests to list contacts (UC04).
- User requests to edit a contact in the list.
- User provides new contact details for that contact.
- CampusBridge validates the input.
- CampusBridge edits the contact and updates the contact list.
- CampusBridge shows a success message.
Use case ends.
Extension:
- 4a. Target contact identifier does not exist.
- 4a1. CampusBridge shows an error message indicating the contact does not exist.
Use case ends.
- 4b. Input does not follow the specified format.
- 4b1. CampusBridge shows an error message indicating the invalid format.
- 4b2. CampusBridge requests the user to re-enter input.
- 4b3. User enters a new input.
Steps 4b1 - 4b3 are repeated until input is valid. Use case resumes at step 5.
- 5a. Contact cannot be updated.
- 5a1. CampusBridge shows an error message indicating the contact could not be updated.
Use case ends.
- 5b. Storage file cannot be written or accessed.
- 5b1. CampusBridge shows an error message indicating the contact list could not be saved.
Use case ends.
Use Case: UC04 - Delete a contact
Preconditions: Application is running and the user has added a contact.
MSS:
- User requests to list contacts (UC04).
- User requests to delete a contact in the list.
- CampusBridge validates the input.
- CampusBridge deletes the contact and updates the contact list.
- CampusBridge shows a success message.
Use case ends.
Extensions:
- 3a. Target contact identifier does not exist.
- 3a1. CampusBridge shows an error message indicating the contact does not exist.
Use case ends.
- 3b. Input does not follow the specified format.
- 3b1. CampusBridge shows an error message indicating the invalid format.
- 3b2. CampusBridge requests the user to re-enter input.
- 3b3. User enters a new input.
Steps 3b1 - 3b3 are repeated until input is valid. Use case resumes at step 4.
- 4a. Contact cannot be deleted.
- 4a1. CampusBridge shows an error message indicating the contact could not be deleted.
Use case ends.
- 4b. Storage file cannot be written or accessed.
- 4b1. CampusBridge shows an error message indicating the contact list could not be saved.
Use case ends.
Use Case: UC05 - Add a tag to an existing contact
Preconditions: Application is running and the user has added a contact.
MSS:
- User requests to tag a contact in the list.
- User provides tag details for that contact.
- CampusBridge validates the input.
- CampusBridge adds the tag and updates the contact list.
- CampusBridge shows a success message.
Use case ends.
Extensions:
- 3a. Target contact identifier does not exist.
- 3a1. CampusBridge shows an error message indicating the contact does not exist.
Use case ends.
- 3b. Input does not follow the specified format.
- 3b1. CampusBridge shows an error message indicating the invalid format.
- 3b2. CampusBridge requests the user to re-enter input.
- 3b3. User enters a new input.
Steps 3b1 - 3b3 are repeated until input is valid. Use case resumes at step 4.
- 3c. Tag already exists for contact.
- 3c1. CampusBridge informs user that the contact already has this tag.
Use case ends.
- 4a. Tag cannot be added.
- 4a1. CampusBridge shows an error message indicating the tag could not be added.
Use case ends.
- 4b. Storage file cannot be written or accessed.
- 4b1. CampusBridge shows an error message indicating the contact list could not be saved.
Use case ends.
Use Case: UC06 - Remove a Tag from a Contact
Preconditions: Application is running
MSS:
- User requests to remove one or more tags from a contact.
- CampusBridge removes the specified tags and displays the updated contact.
Use case ends.
Extensions:
- 1a. Input does not follow the specified format.
- 1a1. CampusBridge shows an invalid command format error.
Use case ends.
- 1b. Specified contact does not exist.
- 1b1. CampusBridge shows an error indicating the contact does not exist.
Use case ends.
- 1c. None of the specified tags exist on the contact.
- 1c1. CampusBridge shows an error indicating none of the tags were found.
Use case ends.
- 2a. Some but not all specified tags exist on the contact.
- 2a1. CampusBridge removes the existing tags and displays the updated contact.
- 2a2. CampusBridge informs the user which tags were not found.
Use case ends.
Use Case: UC07 - Clearing all tags of a type from a contact
Preconditions: Application is running
MSS:
- User requests to list contacts (UC08).
- User requests to clear tags of a specific type.
- CampusBridge clears all the tags of the specific type and updates the contact list.
- CampusBridge shows a success message.
Use case ends.
Extensions:
- 2a. Target contact identifier does not exist.
- 2a1. CampusBridge shows an error message indicating the contact does not exist.
Use case ends.
- 2b. Input does not follow the specified format.
- 2b1. CampusBridge shows an error message indicating the invalid format.
- 2b2. CampusBridge requests the user to re-enter input.
- 2b3. User enters a new input.
Steps 2b1 - 2b3 are repeated until input is valid. Use case resumes at step 3.
- 2c. No tags of specified type exist.
- 2c1. CampusBridge shows an error indicating no tags found to clear.
Use case ends.
- 3a. Storage file cannot be written or accessed.
- 3a1. CampusBridge shows an error message indicating the contact list could not be saved.
Use case ends.
Use Case: UC08 - Listing All Contacts
Preconditions: Application is running
MSS:
- User requests to list all contacts.
- CampusBridge shows a list of all contacts.
Use case ends.
Extensions:
- 1a. User provides extra arguments.
- 1a1. CampusBridge shows an invalid command format error.
Use case ends.
Use Case: UC09 - Sorting contacts
Preconditions: Application is running
MSS:
- User requests to sort contacts.
- User provides sort field (name/email/phone/reset) and optional reverse order.
- CampusBridge validates the input.
- CampusBridge sorts the contacts based on the specified criteria.
- CampusBridge displays the list of contacts in the specified sorted order.
Use case ends.
Extensions:
- 3a. Input does not follow the specified format.
- 3a1. CampusBridge shows an invalid command format error.
Use case ends.
Use Case: UC10 - Search contacts
Preconditions: Application is running
MSS:
- User requests to search for contacts.
- User provides the search details.
- CampusBridge validates the input.
- CampusBridge shows the contacts matching the search query.
Use case ends.
Extensions:
- 3a. Input does not follow the specified format.
- 3a1. CampusBridge shows an error message indicating the invalid format.
- 3a2. CampusBridge requests the user to re-enter input.
- 3a3. User enters a new input.
Steps 3a1 - 3a3 are repeated until input is valid. Use case resumes at step 4.
- 4a. No contacts exist in the list.
- 4a1. CampusBridge informs the user that no contacts match the search query.
Use case ends.
Use Case: UC11 - Undo previous action
Preconditions: Application is running
MSS:
- User requests to undo the most recent action.
- CampusBridge retrieves the most recent undoable command from the undo history.
- CampusBridge invokes the undo operation of that command.
- The command reverses its own effects on the application state.
- CampusBridge updates the undo history.
- CampusBridge shows the updated state and a success message.
Use case ends.
Extensions:
- 2a. No undoable commands available in undo history.
- 2a1. CampusBridge shows an error message indicating that there are no actions to undo.
Use case ends.
- 3a. Command fails to execute its undo operation.
- 3a1. CampusBridge shows an error message indicating that the undo operation failed.
Use case ends.
- 5a. Storage file cannot be written or accessed.
- 5a1. CampusBridge shows an error message indicating the state could not be saved.
Use case ends.
Use Case: UC12 - Navigating Command History
Preconditions: Application is running
MSS:
- User requests to navigate to an earlier command.
- CampusBridge displays the earlier command. Steps 1-2 are repeated until the user is satisfied.
Use case ends.
Extensions:
- 1a. No command history exists.
- 1a1. CampusBridge does nothing.
Use case ends.
- 2a. User requests to navigate to a more recent command.
- 2a1. CampusBridge displays the more recent command.
Use case resumes at step 1.
- 2b. No earlier command exists.
- 2b1. CampusBridge does nothing.
Use case resumes at step 1.
- 2c. No more recent command exists.
- 2c1. CampusBridge does nothing.
Use case resumes at step 1.
Use Case: UC13 - Clearing all contacts
Preconditions: Application is running
MSS:
- User requests to clear all contacts.
- CampusBridge clears all contacts.
Use case ends.
Extensions:
- 1a. User provides extra arguments.
- 1a1. CampusBridge shows an invalid command format error.
Use case ends.
Use Case: UC14 - Exiting
Preconditions: Application is running
MSS:
- User requests to exit the app.
- CampusBridge terminates.
Use case ends.
Extensions:
- 1a. User provides extra arguments.
- 1a1. CampusBridge shows an invalid command format error.
Use case ends.
Use case ends.
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
17or above installed. - Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- Changes should be implemented incrementally, i.e. in a way that allows the app to be usable after each increment, even if some features are not yet implemented.
- All logics and storage should be implemented locally, to ensure testability and usability in secure environments without internet access.
- The distributed JAR file should not be bloated, preferably less than 10MB, to ensure that it can be easily downloaded and stored on devices with limited storage.
Glossary
- Mainstream OS: Windows, Linux, Unix, MacOS
- Private contact detail: A contact detail that is not meant to be shared with others
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by running
java -jar campusbridge.jarin the terminal.Expected: The most recent window size and location is retained.
-
-
Shutting down
-
Test case:
exit
Expected: The application closes. -
Alternative: Press F3 (or Fn + F3 on Mac).
Expected: Same as above. -
Test case:
exit 123
Expected: Application does not close. Error details shown indicating command does not take in any parameter.
-
Viewing help
-
Opening general help
-
Test case:
help
Expected: The User Guide opens in the system default browser. Status message showsOpened user guide in browser. -
Alternative: Press F1 (or Fn + F1 on Mac).
Expected: Same as above.
-
-
Opening command-specific help
-
Test case:
help add
Expected: The User Guide opens in the system default browser at theaddcommand section. Status message showsOpening user guide for 'add' command. -
Other valid command names to try:
help list,help edit,help delete,help find,help sort,help tag,help untag,help cleartag,help clear,help exit
Expected: The User Guide opens at the respective command section. Status message names the command.
-
-
Invalid help arguments
-
Test case:
help INVALID
Expected: The User Guide does not open. Error details shown in the status message. -
Test case:
help ADD(uppercase)
Expected: Same as above. Command names are case-sensitive and must be lowercase. -
Test case:
help add extra
Expected: Same as above. Only a single command name is accepted; extra words cause a format error.
-
Adding a person
-
Adding a person with all fields
-
Prerequisites: Start with the sample data loaded. Ensure the email and Telegram handle used below do not already exist.
-
Test case:
add n/John Doe e/johndoe@example.com p/91234567 h/john_doe
Expected: A new contact is added to the list. The success message shows the added person’s details.
-
-
Adding a person with only compulsory fields
-
Prerequisites: Ensure the email used below does not already exist.
-
Test case:
add n/Jane Doe e/janedoe@example.com
Expected: A new contact is added without phone number and Telegram handle. The success message shows the added person’s details.
-
-
Adding a person with a non-NUS email
-
Prerequisites: Ensure the email used below does not already exist.
-
Test case:
add n/Alex Tan e/alextan@gmail.com
Expected: A new contact is added. A warning is shown indicating that the email is not an NUS domain.
-
-
Adding a person with duplicate email or Telegram handle
-
Prerequisites: Add a contact using
add n/Test Person e/testperson@example.com h/test_person. -
Test case:
add n/Another Person e/testperson@example.com
Expected: No person is added. Error details shown in the status message indicating that a person with this email already exists. -
Test case:
add n/Another Person e/anotherperson@example.com h/test_person
Expected: No person is added. Error details shown in the status message indicating that a person with this Telegram handle already exists. -
Test case:
add n/Case Person e/caseperson@example.com h/TEST_PERSON
Expected: No person is added. Error details shown in the status message indicating that a person with this Telegram handle already exists. -
Test case:
add n/Another Person e/testperson@example.com h/test_person
Expected: No person is added. Error details shown in the status message indicating that a person with this email and Telegram handle already exists.
-
-
Invalid add commands
-
Test case:
add n/John Doe
Expected: No person is added. Error details shown in the status message. -
Test case:
add e/johndoe@example.com
Expected: No person is added. Error details shown in the status message. -
Test case:
add n/John Doe e/invalid-email
Expected: No person is added. Error details shown in the status message. -
Test case:
add n/John Doe n/Jane Doe e/johndoe@example.com
Expected: No person is added. Error details shown in the status message indicating duplicate prefixes. -
Test case:
add n/John Doe e/johndoe@example.com tg/friend
Expected: No person is added. Error details shown in the status message indicating unexpected extra input.
-
Editing a person
- Editing a person with all fields
-
Prerequisites: Start with the sample data loaded. Ensure the email and Telegram handle used below do not already exist. At least one person in the list.
-
Test case:
edit 1 n/John Lim e/johnlim@nus.edu.sg p/81234567 h/john_LIM
Expected: The first contact is updated with the new details. The success message shows the edited person’s details.
-
- Editing a person with one field
-
Prerequisites: Start with the sample data loaded. Ensure the email and Telegram handle used below do not already exist. At least one person in the list.
-
Test case:
edit 1 n/John Lim
Expected: The first contact’s name is updated. All other fields remain unchanged. The success message shows the edited person’s details. -
Test case:
edit 1 e/johnlim@u.nus.edu
Expected: The first contact’s email is updated. All other fields remain unchanged. The success message shows the edited person’s details. -
Test case:
edit 1 p/12345678
Expected: The first contact’s phone number is updated. All other fields remain unchanged. The success message shows the edited person’s details. -
Test case:
edit 1 h/johnlimm
Expected: The first contact’s telegram handle is updated. All other fields remain unchanged. The success message shows the edited person’s details.
-
- Editing a person with a non-NUS email
-
Prerequisites: Start with the sample data loaded. Ensure the email used below do not already exist. At least one person in the list.
-
Test case:
edit 1 e/john@gmail.com
Expected: The first contact’s email is updated. A warning is shown indicating that the email is not an NUS domain.
-
- Editing a person with duplicate email or Telegram handle
-
Prerequisites: Start with the sample data loaded. The first contact has email
johnlim@u.nus.eduand Telegram handlejohnlimm. At least two person in the list. -
Test case:
edit 2 e/johnlim@u.nus.edu
Expected: No changes made. Error details shown indicating a person with this email already exists. -
Test case:
edit 2 h/johnlimm
Expected: No changes made. Error details shown indicating a person with this Telegram handle already exists.
-
- Invalid edit commands
-
Test case:
edit
Expected: No changes made. Invalid command format error shown. -
Test case:
edit 1
Expected: No changes made. Invalid command format error shown. -
Test case:
edit 0 n/John Lim
Expected: No changes made. Error details shown indicating the index should be a positive integer. -
Test case:
edit 999 n/John Lim(where 999 is larger than list size)
Expected: No changes made. Error details shown in the status message indicating no person exists at that index and tip to uselistcommand. -
Test case:
edit 1 n/John Lim n/Jane Lim
Expected: No changes made. Error details shown indicating duplicate prefixes. -
Test case:
edit 1 n/John Lim tg/friend
Expected: No changes made. Error details shown indicating unexpected extra input.
-
Deleting a person
-
Deleting a person by index
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. -
Test case:
delete i/1
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message.
-
-
Deleting a person by email
-
Prerequisites: Ensure a person with email
alicetan@u.nus.eduexists in the address book. -
Test case:
delete e/alicetan@u.nus.edu
Expected: Person with the specified email is deleted from the list. Details of the deleted contact shown in the status message.
-
-
Invalid delete commands
-
Test case:
delete
Expected: No person deleted. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
delete i/0
Expected: No person deleted. Error details shown in the status message indicating index must be a positive integer (1, 2, 3…). -
Test case:
delete e/invalid-email
Expected: No person deleted. Error details shown in the status message indicating email constraints. -
Test case:
delete 1(missing prefix)
Expected: No person deleted. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
delete i/1 i/2(multiple same prefixes)
Expected: No person deleted. Error details shown in the status message indicating multiple values specified for the following single-valued field(s):i/. -
Test case:
delete e/alicetan@u.nus.edu i/1(both prefixes)
Expected: No person deleted. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
delete i/1 n/alice p/12345678(multiple invalid prefixes)
Expected: No person deleted. Error details shown in the status message invalid command format and unexpected extra input. -
Test case:
delete i/100(where 100 is larger than list size)
Expected: No person deleted. Error details shown in the status message indicating no person exists at that index and tip to uselistcommand. -
Test case:
delete e/nonexistent@example.com
Expected: No person deleted. Error details shown in the status message indicating no person found with that email and tip to uselistorfindcommands.
-
Tagging a person
-
Adding tags to a person
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure the first and second person has no existing tags. -
Test case:
tag 1 tg/friends
Expected:friendsgeneral tag is added to the 1st person in the list. Status message shows the details of the new tags added. -
Test case:
tag 2 tg/groupmates tc/cs2103
Expected: Bothgroupmatesgeneral tag andcs2103course tag are added to the 2nd person in the list. Status message shows the details of the new tags added. -
Test case:
tag 2 tr/tutor tr/TUTOR(duplicate with different case)
Expected: Only onetutorrole tag is added to the 2nd person in the list. Status message shows the details of the new tags added. -
Test case:
tag 2 tr/mentor tg/mentor(same name, different types)
Expected: Bothmentortutor tag andmentorgeneral tag are added to the 2nd person in the list. Status message shows the details of the new tags added.
-
-
Adding tags to a person where some tags already exist
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure the first person only have existingfriendsgeneral tag andcs2103course tag. - Test case:
tag 1 tg/friends tg/groupmates(wherefriendsalready exists)
Expected: Onlygroupmatesgeneral tag is added to the 1st person in the list. Status message shows:New tags added: [GENERAL: groupmates] Tags already existing (no changes made): [GENERAL: friends] - Test case:
tag 1 tc/cs2109s tc/cs2100 tc/cs2103(wherecs2103already exists)
Expected:cs2109sandcs2100course tags are added to the 1st person in the list. Status message shows:New tags added: [COURSE: cs2109s, COURSE: cs2100] Tags already existing (no changes made): [COURSE: cs2103]
-
-
Adding tags to a person where all tags already exist
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure the first person have existingfriendsgeneral tag andcs2103course tag. -
Test case:
tag 1 tg/friends(wherefriendsalready exists)
Expected: No changes made. Error details shown in the status message indicating that all tags already exist for this person and no changes made. -
Test case:
tag 1 tg/friends tc/cs2103(where both tags already exists)
Expected: No changes made. Error details shown in the status message indicating that all tags already exist for this person and no changes made.
-
-
Invalid tag commands
-
Test case:
tag
Expected: No tag added. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
tag 0
Expected: No tag added. Error details shown in the status message indicating index must be a positive integer (1, 2, 3…). -
Test case:
tag 1 test(missing prefix)
Expected: No tag added. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
tag 1 n/alice(invalid prefixes)
Expected: No tag added. Error details shown in the status message indicating invalid command format and unexpected extra input. -
Test case:
tag 1 tr/(missing value)
Expected: No tag added. Error details shown in the status message indicating invalid command format and empty value provided for prefix. -
Test case:
tag 100 tg/friends(where 100 is larger than list size)
Expected: No tag added. Error details shown in the status message indicating no person exists at that index and tip to uselistcommand. -
Test case:
tag 1 tr/tutor space
Expected: No tag added. Error details shown in the status message indicating tags names should be alphanumeric only (no spaces or special characters).
-
Untagging a person
-
Removing tags from a person
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure the first person have existingtutorrole tag,cs2103course tag,friendsandgroupmatesgeneral tags. -
Test case:
untag 1 tg/friends
Expected:friendsgeneral tag is removed from the 1st person in the list. Status message shows the details of the tags removed. -
Test case:
untag 1 tg/groupmates tc/cs2103
Expected: Bothgroupmatesgeneral tag andcs2103course tag are removed from the 1st person in the list. Status message shows the details of the tags removed. -
Test case:
untag 1 tr/tutor tr/TUTOR(duplicate with different case)
Expected: Only onetutorrole tag is removed from the 1st person in the list. Status message shows the details of the tags removed.
-
-
Removing tags from a person where some tags don’t exist
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure the first person only have existingcs2103course tag andfriendsgeneral tags. - Test case:
untag 1 tg/friends tr/tutor(wherefriendsexists buttutordoesn’t)
Expected: Onlyfriendsgeneral tag is removed from the 1st person in the list. Status message shows:Tags removed: [GENERAL: friends] Tags not found: [ROLE: tutor] - Test case:
untag 1 tc/cs2109s tc/cs2100 tc/cs2103(wherecs2103exists butcs2109sandcs2100doesn’t)
Expected: Onlycs2103course tag is removed from the 1st person in the list. Status message shows:Tags removed: [COURSE: cs2103] Tags not found: [COURSE: cs2109s, COURSE: cs2100]
-
-
Removing tags from a person where all tags don’t exist
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure the first person has no existing tags. -
Test case:
untag 1 tg/nonexistent
Expected: No changes made. Error details shown in the status message indicating that none of the specified tags were found. -
Test case:
untag 1 tr/notfound tg/missing
Expected: No changes made. Error details shown in the status message indicating that none of the specified tags were found.
-
-
Invalid untag commands
-
Test case:
untag
Expected: No tag removed. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
untag 0
Expected: No tag removed. Error details shown in the status message indicating index must be a positive integer (1, 2, 3…). -
Test case:
untag 1 test(missing prefix)
Expected: No tag removed. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
untag 1 n/alice(invalid prefixes)
Expected: No tag removed. Error details shown in the status message indicating invalid command format and unexpected extra input. -
Test case:
untag 1 tr/(missing value)
Expected: No tag removed. Error details shown in the status message indicating invalid command format and empty value provided for prefix. -
Test case:
untag 100 tg/friends(where 100 is larger than list size)
Expected: No tag removed. Error details shown in the status message indicating no person exists at that index and tip to uselistcommand. -
Test case:
untag 1 tr/tutor space
Expected: No tag removed. Error details shown in the status message indicating tags names should be alphanumeric (no spaces or special characters).
-
Clearing all tags of a specific type
-
Clearing all tags from a person
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure both first and second person have existing general and role tags. -
Test case:
cleartag 1 tg/
Expected: All the general tags are cleared from the 1st person in the list. Status message shows the details of the general tags cleared. -
Test case:
cleartag 2 tr/
Expected: All the role tags are cleared from the 2nd person in the list. Status message shows the details of the role tags cleared.
-
-
Clearing all tags from a person where no tags of specified type exist
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. Ensure both first and second person has no existing tags. -
Test case:
cleartag 1 tc/
Expected: No changes made. Error details shown in the status message indicating that no course tags found to clear. -
Test case:
cleartag 2 tr/
Expected: No changes made. Error details shown in the status message indicating that no role tags found to clear.
-
-
Invalid cleartag commands
-
Test case:
cleartag
Expected: No tag cleared. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
cleartag 0
Expected: No tag cleared. Error details shown in the status message indicating index must be a positive integer (1, 2, 3…). -
Test case:
cleartag 1(missing prefix)
Expected: No tag cleared. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
cleartag 1 n/alice(invalid prefixes)
Expected: No tag cleared. Error details shown in the status message indicating invalid command format and unexpected extra input. -
Test case:
cleartag 1 tr/ tr/(multiple same prefixes)
Expected: No tag cleared. Error details shown in the status message indicating multiple values specified for the following single-valued field(s):i/. -
Test case:
cleartag 1 tr/ tg/(multiple prefixes)
Expected: No tag cleared. Error details shown in the status message indicating invalid command format and command usage. -
Test case:
cleartag 100 tg/(where 100 is larger than list size)
Expected: No tag cleared. Error details shown in the status message indicating no person exists at that index and tip to uselistcommand. -
Test case:
cleartag 1 tr/tutor
Expected: No tag cleared. Error details shown in the status message indicating invalid command format and prefix should not contain any value.
-
Sorting persons
-
Sorting by a valid field
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. -
Test case:
sort o/name
Expected: Contact list is sorted alphabetically by name (ascending). Status message showsSorted by name (ascending). -
Test case:
sort o/name r/
Expected: Contact list is sorted alphabetically by name (descending). Status message showsSorted by name (descending). -
Test case:
sort o/email
Expected: Contact list is sorted by email address (ascending). Status message showsSorted by email (ascending). -
Test case:
sort o/phone
Expected: Contact list is sorted by phone number (ascending). Contacts with no phone number appear at the end of the list. Status message showsSorted by phone (ascending). -
Test case:
sort o/email r/
Expected: Contact list is sorted by email address (descending). Status message showsSorted by email (descending).
-
-
Resetting sort order
-
Test case:
sort o/none
Expected: Contact list reverts to the default (insertion) order. Status message showsSort order reset to default. -
Test case:
sort o/none r/
Expected: Sort order is not reset. Error details shown in the status message indicating thatr/cannot be used witho/none.
-
-
Invalid sort commands
-
Test case:
sort
Expected: List is not sorted. Error details shown in the status message. -
Test case:
sort o/INVALID
Expected: List is not sorted. Error details shown in the status message indicating the unsupported order value. -
Test case:
sort o/NAME(uppercase)
Expected: List is sorted by name. Order values are case-insensitive. -
Test case:
sort o/name r/value
Expected: List is not sorted. Error details shown in the status message indicating thatr/does not accept a value. -
Test case:
sort o/name o/email
Expected: List is not sorted. Error details shown in the status message indicating duplicateo/prefix.
-
Locating persons by name/email/tag
-
Searching by single field
-
Prerequisites: List all persons using the
listcommand. At least one person should be in the list. -
Test case:
find n/Alex
Expected: Contacts whose names matchAlex(case-insensitive; supports substring and fuzzy matching) are shown. -
Test case:
find e/nus.edu
Expected: Contacts with email addresses containingnus.edu(case-insensitive substring) are shown. -
Test case:
find t/friends
Expected: Contacts with the tagfriends(case-insensitive exact match) are shown.
-
-
Searching by multiple keywords/fields
-
Prerequisites: List all persons using the
listcommand. At least two persons should be in the list. -
Test case:
find n/Alex David
Expected: Contacts whose names matchAlexORDavidare shown (i.e. matches at least one keyword). -
Test case:
find n/Alex e/nus.edu
Expected: Contacts whose names matchAlexAND whose email containsnus.eduare shown. -
Test case:
find n/Alex e/nus.edu t/friends
Expected: Contacts matching all three criteria (Name AND Email AND Tag) are shown.
-
-
Fuzzy search for names (slight typo tolerance)
-
Prerequisites: A contact with name
Alice Tanexists. -
Test case:
find n/alce
Expected:Alice Tanis shown in the results. -
Test case:
find n/aliec
Expected:Alice Tanis shown in the results. -
Test case:
find n/Tan
Expected:Alice Tanis shown in the results.
-
-
Invalid search commands
-
Test case:
find(no parameters)
Expected: Error message indicating invalid command format and showing usage. -
Test case:
find n/
Expected: Error message indicating empty value provided for prefixn/. -
Test case:
find n/!@#
Expected: Error message indicating that the keyword!@#contains only special characters and must contain at least one alphanumeric character. -
Test case:
find p/91234567(unsupported prefix for find)
Expected: Error message indicating unexpected extra inputp/91234567.
-
Undoing the last action
-
Undoing the most recent undoable command
-
Prerequisites: List all persons using the
listcommand. At least one person exists in the list. -
Test case:
add n/John Doe e/johndoe@example.comfollowed byundo
Expected: The previously added contact is removed from the list. Status message indicates that the last add action has been undone. -
Test case:
delete i/1followed byundo
Expected: The deleted contact is restored to the list. Status message indicates that the last delete action has been undone.
-
-
Undoing multiple commands consecutively
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. -
Test case: Execute
add n/A e/a@example.com, thenadd n/B e/b@example.com, thenundo, thenundo
Expected: Both added contacts are removed one by one in reverse order. Status message reflects each undo operation.
-
-
Undo when no undoable commands are available
-
Prerequisites: Start the application fresh, or ensure all previous undoable commands have already been undone.
-
Test case:
undo
Expected: No changes to the contact list. Error details shown in the status message indicating that there are no actions to undo.
-
-
Undo after non-undoable commands
-
Prerequisites: List all persons using the
listcommand. -
Test case:
add n/John Doe e/johndoe@example.com, thenlist, thenundo
Expected: The previously added contact is removed. Thelistcommand does not affect undo history. -
Test case:
help, thenundo
Expected: No changes to the contact list. Error details shown in the status message if there are no undoable commands.
-
-
Undo after a mix of commands
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. -
Test case:
add n/A e/a@example.com,list,delete i/1, thenundo
Expected: The deleted contact is restored. Thelistcommand is ignored by undo.
-
-
Invalid undo command
- Test case:
undo extra
Expected: No changes to the contact list. Error details shown in the status message indicating that the command does not accept parameters.
- Test case:
-
Persistence after undo
-
Prerequisites: List all persons using the
listcommand. -
Test case:
add n/John Doe e/johndoe@example.com, thenundo, then restart the application
Expected: The contact list reflects the undone state (i.e., the added contact does not appear).
-
Navigating command history
-
Cycling through past commands
-
Prerequisites: Enter at least three commands in sequence, e.g.
list,sort o/name,help. -
Press the Up arrow key in the command box.
Expected: The command box fills with the most recently entered command (help). -
Press Up again.
Expected: The command box shows the previous command (sort o/name). -
Press Down.
Expected: The command box shows the next command in history (help).
-
-
Navigating beyond history bounds
-
Press Up repeatedly past the oldest command in history.
Expected: The command box stays at the oldest command; it does not wrap around. -
Press Down past the most recent command.
Expected: The command box clears (returns to empty input).
-
-
History is not affected by invalid commands
-
Enter a valid command (e.g.
list), then an invalid command (e.g.badcommand). -
Press Up once.
Expected: The invalid commandbadcommandis shown (all submitted input, valid or not, is recorded).
-
Using keyboard shortcuts
-
Clearing the input box
-
Prerequisites: Application is running. Some text is present in the input box.
-
Test case (Windows/Linux): Press Delete
Expected: The input box is cleared. -
Test case (macOS): Press fn + Delete
Expected: The input box is cleared.
-
-
Exiting the application
-
Prerequisites: Application is running.
-
Test case (Windows/Linux): Press F3
Expected: The application closes. -
Test case (macOS): Press fn + F3
Expected: The application closes.
-
-
Opening help
-
Prerequisites: Application is running.
-
Test case (Windows/Linux): Press F1
Expected: The User Guide opens in the system default browser. -
Test case (macOS): Press fn + F1
Expected: Same as above.
-
-
Listing all contacts
-
Prerequisites: Application is running.
-
Test case (Windows/Linux): Press F2
Expected: All contacts are displayed in the list. -
Test case (macOS): Press fn + F2
Expected: Same as above.
-
-
Invalid or unsupported key combinations
- Test case: Press unrelated keys (e.g., F4, Ctrl + F1)
Expected: No action is triggered. Application remains unchanged.
- Test case: Press unrelated keys (e.g., F4, Ctrl + F1)
Saving data
-
Dealing with a missing data file
-
Prerequisites: Locate the data file at
data/addressbook.json. Delete it. -
Relaunch the application. Expected: The application starts with the sample contact list. A new data file is created automatically.
-
-
Dealing with a corrupted data file
-
Prerequisites: Locate the data file at
data/addressbook.json. Open it in a text editor and introduce invalid content (e.g., delete a closing brace}or replace a field value with gibberish). -
Relaunch the application. Expected: The application starts with an empty contact list. The corrupted file is not loaded to prevent data loss from bad state.
-
-
Auto-saving after changes
-
Prerequisites: Application is running.
-
Test case: Add a new contact, then close the application using the close button. Relaunch. Expected: The newly added contact is present.
-