{ list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well }
Refer to the guide Setting up and getting started.
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.
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 1. (Note: The delete command also supports multiple indexes, e.g., delete 1 3 5, which follows the same interaction pattern.)
Each of the four main components (also shown in the diagram above),
interface with the same name as the Component.{Component Name}Manager class (which follows the corresponding API interface mentioned 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.
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,
Logic component.Model data so that the UI can be updated with the modified data.Logic component, because the UI relies on the Logic to execute commands.Model component, as it displays Person object residing in the Model.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 1") API call as an example. Note that the delete command supports multiple indexes (e.g., delete 1 3 5), which follows the same parsing and execution pattern shown below, iterating through each index to delete multiple employees.
Note: The lifeline for 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:
Logic is called upon to execute a command, it is passed to an AddressBookParser object which in turn creates a parser that matches the command (e.g., DeleteCommandParser) and uses it to parse the command.Command object (more precisely, an object of one of its subclasses e.g., DeleteCommand) which is executed by the LogicManager. The command can communicate with the Model when it is executed (e.g. to delete an employee).ConfirmableCommand (such as edit, delete, clear, or exit), LogicManager does not execute it immediately. Instead, it temporarily saves the command as a pending confirmation and prompts the user for a y/n input.y), the command can communicate with the Model when it is executed (e.g. to delete an employee).Model) to achieve.CommandResult object which is returned back from Logic.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:
AddressBookParser class creates an XYZCommandParser (XYZ is a placeholder for the specific command name e.g., AddCommandParser) which uses the other classes shown above to parse the user command and create a XYZCommand object (e.g., AddCommand) which the AddressBookParser returns back as a Command object.XYZCommandParser classes (e.g., AddCommandParser, DeleteCommandParser, ...) inherit from the Parser interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model component,
Person objects (which are contained in a UniquePersonList object).Person stores Name, Phone, Email, Role, Department, and optional Tag values.Person objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Person> that can be observed. The UI can be bound to this list so that it updates automatically when the data changes.UserPref object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref objects.Model represents data entities of the domain, they should make sense on their own without depending on other components)Note: An alternative (arguably, a more OOP) model is given below. It has a 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.

API : Storage.java
The Storage component,
AddressBookStorage and UserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed).Model component (because the Storage component's job is to save/retrieve objects that belong to the Model)Classes used by multiple components are in the seedu.address.commons package.
This section describes some noteworthy details on how certain features are implemented.
The proposed undo/redo mechanism is facilitated by VersionedAddressBook. It extends AddressBook with an undo/redo history, stored internally as an addressBookStateList and currentStatePointer. Additionally, it implements the following operations:
VersionedAddressBook#commit() — Saves the current HRmanager state in its history.VersionedAddressBook#undo() — Restores the previous HRmanager state from its history.VersionedAddressBook#redo() — Restores a previously undone HRmanager state from its history.These operations are exposed in the Model interface as Model#commitAddressBook(), Model#undoAddressBook() and Model#redoAddressBook() respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The VersionedAddressBook will be initialized with the initial HRmanager state, and the currentStatePointer pointing to that single HRmanager state.
Step 2. The user executes delete 5 command to delete the 5th employee in the HRmanager. The delete command calls Model#commitAddressBook(), causing the modified state of the HRmanager after the delete 5 command executes to be saved in the addressBookStateList, and the currentStatePointer is shifted to the newly inserted HRmanager state.
Step 3. The user executes add n/David … to add a new employee. The add command also calls Model#commitAddressBook(), causing another modified HRmanager state to be saved into the addressBookStateList.
Note: If a command fails its execution, it will not call Model#commitAddressBook(), so the HRmanager state will not be saved into the addressBookStateList.
Step 4. The user now decides that adding an employee was a mistake, and decides to undo that action by executing the undo command. The undo command will call Model#undoAddressBook(), which will shift the currentStatePointer once to the left, pointing it to the previous HRmanager state, and restores the HRmanager to that state.
Note: If the currentStatePointer is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The undo command uses Model#canUndoAddressBook() to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following sequence diagram shows how an undo operation goes through the Logic component:
Note: The lifeline for UndoCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Similarly, how an undo operation goes through the Model component is shown below:
The redo command does the opposite — it calls Model#redoAddressBook(), which shifts the currentStatePointer once to the right, pointing to the previously undone state, and restores the HRmanager to that state.
Note: If the currentStatePointer is at index addressBookStateList.size() - 1, pointing to the latest HRmanager state, then there are no undone AddressBook states to restore. The redo command uses Model#canRedoAddressBook() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
Step 5. The user then decides to execute the command list. Commands that do not modify the HRmanager, such as list, will usually not call Model#commitAddressBook(), Model#undoAddressBook() or Model#redoAddressBook(). Thus, the addressBookStateList remains unchanged.
Step 6. The user executes clear, which calls Model#commitAddressBook(). Since the currentStatePointer is not pointing at the end of the addressBookStateList, all HRmanager states after the currentStatePointer will be purged. Reason: It no longer makes sense to redo the add n/David … command. This is the behavior that most modern desktop applications follow.
The following activity diagram summarizes what happens when a user executes a new command:
Aspect: How undo & redo executes:
Alternative 1 (current choice): Saves the entire HRmanager.
Alternative 2: Individual command knows how to undo/redo by itself.
delete, just save an employee being deleted).{more aspects and alternatives to be added}
{Explain here how the data archiving feature will be implemented}
The search command is implemented by SearchCommand, SearchCommandParser, and PersonMatchesKeywordPredicate.
The flow is as follows:
search KEYWORD [MORE_KEYWORDS]....AddressBookParser routes the input to SearchCommandParser.SearchCommandParser trims the arguments, rejects blank input, rejects searches with more than 5 keywords, rejects any keyword longer than 20 characters, and rejects non-alphanumeric keywords.SearchCommand is created with a PersonMatchesKeywordPredicate.SearchCommand#execute updates the model's filtered employee list and returns feedback in the form X employees listed!.The sequence diagram below illustrates the interactions within the Logic and Model components when a user executes a search command (e.g. search ali hr).
Note: The lifeline for SearchCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
Matching behavior:
AND semanticsThis means a command such as search ali hr returns employees whose fields contain both ali and hr, regardless of case (for instance, an employee named "Alice" in the "HR" department).
The statistics panel provides real-time workforce metrics displayed permanently on the right side of the application. This feature follows the Separation of Concerns (SoC) principle by separating data calculation from UI display.
The statistics feature consists of three main components:
Statistics (Model layer): A pure data container that calculates statistics from a list of employees. It has no UI dependencies and is easily testable.StatisticsService (Service layer): Orchestrates the retrieval of statistics by accessing the filtered employee list from Logic and creating a Statistics object.StatsPanel (UI layer): A JavaFX component that displays statistics and listens for changes to the employee list to auto-refresh.
Statistics Class:
List<Person> as inputfindMostCommonTag() and createTagDistribution() for clean separationStatisticsService Class:
Logic and StatisticsgetCurrentStatistics() which converts ObservableList<Person> to List<Person>StatsPanel Class:
UiPart<Region> with FXML layoutlogic.getFilteredPersonList() for changesThe sequence diagram below shows how the statistics panel updates when an employee is added:
add commandLogicManager executes the command and updates the modelObservableList change triggers the listener in StatsPanelStatsPanel calls refresh() → statisticsService.getCurrentStatistics()StatisticsService creates a new Statistics object from the employee listStatsPanel updates its labels with the new statisticsAspect: Where to place statistics calculation logic
Alternative 1 (current): Separate Statistics class for calculation
Alternative 2: Calculate statistics directly in StatsPanel
Aspect: Auto-refresh mechanism
Current choice: Listener on ObservableList<Person>
Alternative: User must type stats command
StatisticsTest: Unit tests for calculation logic with various employee listsStatisticsServiceTest: Tests service layer with temporary storageStatisticsServiceIntegrationTest: Integration tests with actual commandsTarget user profile: Human Resource Manager
Value proposition:
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * | new user | have a guided tutorial | understand the layout and get started quickly |
* * * | user | add an employee | keep track of new employees |
* * * | user | delete an employee | clear up data when it is no longer needed |
* * * | user | view all employees | gain a brief overview of everyone in the company |
* * * | user | store phone numbers and email addresses | contact employees easily |
* * * | busy user | search for employees by name | quickly find a specific staff member |
* * * | busy user | add contacts with only name and phone | track someone now and update details later |
* * | organised user | modify employee details | keep info up to date |
* * | organised user | sort employees by variables | find the most relevant employees for my needs |
* * | organised user | tag employees by department | categorise them |
* * | cautious user | get confirmation of my work | not worry that my changes haven't been saved |
* * | clumsy user | undo my last action | avoid making mistakes or losing data |
* * | clueless user | see error messages | correct my mistakes |
* | expert user | import employee data | manage pre-existing details without hand-typing everything |
* | expert user | export employee data | back up data, support audits and planning |
* | expert user | repeat previous command or similar | enter commands quickly |
* | expert user | bulk archive or tag multiple applicants | clean up after a role is filled more efficiently |
* | user responsible for reporting | use a centralized dashboard | maintain visibility over workforce and talent pipeline |
* | safe user | access the app via login authentication | ensure employee data is secure |
{More to be added}
(For all use cases below, the System is the HRmanager and the Actor is the user, unless specified otherwise)
MSS
User requests to add an employee by adding employee details (name, phone, email, role, department, optional tags).
System adds an employee to the records.
System displays confirmation message.
Use case ends.
Extensions
1a. System detects an error (e.g. format/syntax/duplicates error) in the entered data.
Use case resumes from step 2.
MSS
User requests to remove one or more employees by specifying their index numbers in the displayed list.
System validates the provided index numbers.
System removes the corresponding employee records from the system.
System displays a confirmation message indicating the number of employees deleted.
Use case ends.
Extensions
1a. System detects an error (e.g. format/syntax error) in the entered data.
Use case resumes from step 2.
2a. One or more indexes are invalid (e.g., index exceeds list size).
Use case ends.
MSS
User requests to view the list of employees.
System retrieves the employee records and displays employee list.
Use case ends.
Extensions
2a. There are no employees stored in the system.
Use case ends
MSS
User enters the search command with one or more keywords.
System validates the search input.
System processes the search query against the existing employee records.
System displays a list of all employees that match the search. Matching is case-insensitive, supports partial substring matching across all fields, and returns employees whose fields contain all of the supplied keywords.
Use case ends.
Extensions
1a. The user executes search with blank input.
search usage.Use case resumes at step 1.
1b. The user provides more than 5 keywords, at least one keyword longer than 20 characters, or non-alphanumeric keywords.
search usage.Use case resumes at step 1.
3a. No employees match the provided search query.
0 employees listed!.Use case ends.
MSS
User searches for employee. (UC4)
System shows list of employees.
User requests to tag a specific employee in the list.
System requests for the tag name.
User provides tag name.
System adds the tag to an employee and updates the list
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given index is invalid.
Use case resumes at step 1.
5a. The tag name provided is already associated with this employee.
Use case resumes at step 2.
5b. The tag name provided is invalid (e.g., blank, exceeds 30 characters, or contains non-alphanumeric characters).
Use case resumes at step 4.
a. At any time, the User chooses to cancel the tagging operation.
Use case ends.
MSS
name, phone, email, role, department, tags).Extensions
1a. The user enters the command in the incorrect format.
Use case resumes at step 1.
2a. The user entered an invalid index.
Use case resumes at step 1.
3a. User's given details are invalid.
Use case resumes at step 3.
3b. User enters empty details.
Use case resumes at step 3.
MSS
User requests to edit an employee's phone number.
System edits the employee's phone number in the records.
System displays confirmation message.
User suddenly recalls that they have forgotten to also edit the employee's email address.
User presses the up arrow (PgUp) key in the CLI.
System prefills the CLI with the command used in step 1.
User deletes the phone field and types the email details, then enters the command. (The command "edit" and the relevant employee index is already prepared)
System edits the employee's email address in the records.
Use case ends.
Extensions
1a. There are no previous successfully executed commands.
Use case ends.
2a. There are up to 5 previous successfully executed commands.
Use case ends.
2a1. User enters more than 5 commands.
Use case ends.
MSS
User requests to export current employee data into destination of choice.
System resolves path and checks validity.
System converts app data into csv format.
System saves csv file into target destination.
Use case ends.
Extensions
2a. User input filepath is invalid.
2a1. System displays an error message.
Use case resumes at Step 1.
2b. File already exists at target destination.
2b1. System displays an error message.
Use case resumes at step 1.
17 or above installed.Engineering, Finance, Human Resources).Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
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 double-clicking the jar file.
Expected: The most recent window size and location is retained.
{ more test cases … }
Adding an employee, along with their details.
Prerequisites: List all employees using the list command. There are no existing employees in the list.
Test case: add n/Bob Choo p/22222222 e/bob@example.com r/Head of Office d/Operations t/friend (Valid entry)
Expected: The employee is added. The success message is shown, along with the added details.
Test case: add n/Amy Choo p/22222222 e/amy@example.com r/Head of Office d/Operations t/friend (Preamble is a space)
Expected: The employee is added. The success message is shown, along with the added details.
Test case: add k n/Amy Choo p/22222222 e/amy@example.com r/Head of Office d/Operations t/friend (Preamble is not a space)
Expected: The employee is not added. Error message for invalid command format,along with an example of the correct format, shown.
Test case: add n/Bob Choo p/11111111 e/bob@meme.com r/Head of Operations d/Operations t/friend (Same exact name with existing entry, despite different details)
Expected: The employee is not added. Duplicate error message is shown, indicating an employee with same name already exists.
Test case: add n/Lance Choo p/33333333 e/lance@example.com r/Head of HR d/Human Resources t/friend t/friend t/husband (Multiple tags)
Expected: The employee is added. The success message is shown, along with the added details. Note that duplicate tags are accepted as one tag.
Test case: add n/Amy Cho n/Bob Choo p/11111111 e/bob@meme.com r/Head of Operations d/Operations t/friend (Two names))
Expected: The employee is not added. Error messages for duplicated prefix shown.
Other incorrect commands with duplicated attributes for the same employee: add <other details> p/11111111 p/22222222, add <other details> e/amy@example.com e/bob@example.com, or similar
Expected: The employee is not added. Error messages for duplicated prefix shown.
Test case: add n/James& p/11111111 e/bob@meme.com r/Head of Operations d/Operations t/friend (Invalid name)
Expected: The employee is not added. The correct format for a valid name is shown.
Other incorrect commands with invalid data: add <other details> p/abc (Non-numeric phone number) or similar
Expected: The employee is not added. The correct format for the attribute for which the argument is invalid is shown.
Test case: add n/Pikachu p/11111111 e/bob@meme.com r/Head of Operations d/Operations (No optional Tag)
Expected: The employee is added. The success message is shown, along with the added details.
Test case: add n/Peppa Pig e/peppa@example.com r/Head of Media d/Media (No phone number) or similar absence of necessary attributes
Expected: The employee is not added. Error message is shown, along with the correct format and required parameters.
Other incorrect delete commands to try: add, add johndoe p/3333 (no prefix), and other commands which deviate from the command format
Expected: Similar to previous.
Deleting one or more employees while all employees are being shown
Prerequisites: List all employee using the list command. Multiple employees in the list.
Test case: delete 1
Expected: First employee is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
Test case: delete 0
Expected: No employee is deleted. Error details shown in the status message. Status bar remains the same.
Test case: delete 1 3 5
Expected: 1st, 3rd, and 5th employee are deleted from the list. Status message shows "Deleted employee(s): 3 employee(s)". Timestamp in the status bar is updated.
Test case: delete 1 1 2
Expected: Only 2 unique employees are deleted (duplicate index filtered out). Status message shows "Deleted employee(s): 2 employee(s)". Only the 1st and 2nd persons are removed.
Test case: delete 2 1 3
Expected: 1st, 2nd, and 3rd employees are deleted (regardless of order provided). Status message shows "Deleted employee(s): 3 employee(s)". Deletion performed from highest to lowest index to prevent index shifting errors.
Test case: delete 1 2 999
Expected: No employee is deleted. Error details shown for invalid index 999. Status bar remains the same.
Other incorrect delete commands to try: delete, delete x, ... (where x is larger than the list size)
Expected: Similar error handling to above.
Deleting a employee from a filtered list (search results)
Prerequisites: Execute search KEYWORD to filter the list (where KEYWORD returns one or more matching results based on searchable fields). Multiple search results shown.
Test case: delete 1
Expected: The 1st employee in the filtered search results is deleted. Confirmation message shown. Filtered list updates automatically.
Test case: search KEYWORD (where KEYWORD returns 2 or more matching results) followed by delete 1 2
Expected: The 1st and 2nd employees in the filtered results are deleted. Confirmation shows "Deleted employee(s): 2 employee(s)". Filtered list updates.
Test case: search KEYWORD (where KEYWORD returns no matches) followed by delete 1
Expected: Error message shown for invalid index since filtered list is empty.
Tagging an employee with valid tags
Prerequisites: List all employees using the list command. Multiple employees in the list.
Test case: tag 1 t/HR
Expected: First employees is tagged with "HR". Success message shown in the status message.
Test case: tag 1 t/HR t/Manager
Expected: First employee is tagged with both "HR" and "Manager". Success message shown.
Test case: tag 2 t/ (empty tag)
Expected: No tag is added. Error details shown: "Tags should only consist of alphanumeric characters, hyphens and spaces, and be between 1 and 30 characters long. The tag should not start or end with a space or hyphen, and it should not contain consecutive spaces or hyphens."
Test case: tag 2 t/HR_Department (contains underscore)
Expected: No tag is added. Error details shown due to non-alphanumeric character.
Test case: tag 2 t/[a string of 31 characters]
Expected: No tag is added. Error details shown due to exceeding 30-character limit.
Test case: tag 2 t/HR (when employee already has "HR" tag)
Expected: No duplicate tag is added. Error details shown indicating duplicate tag.
Other incorrect tag commands to try: tag, tag x t/HR (where x is larger than list size), tag 1 (no tag specified)
Expected: Similar error messages shown.
Searching for employees using a keyword
Prerequisites: List all employees using the list command. Multiple employees in the list with various names, phones, emails, roles, departments, and tags.
Test case: search John
Expected: All employees whose fields contain "John" (case-insensitive) are listed. Status message shows the number of employees listed.
Test case: search 91234567
Expected: All employees whose fields contain "91234567" are listed. Status message shows the number of employees listed.
Test case: search example
Expected: All employees whose fields contain "example" are listed. Status message shows the number of employees listed.
Test case: search HR
Expected: All employees whose fields contain "HR" are listed. Status message shows the number of employees listed.
Test case: search (no keyword)
Expected: No search is performed. Error details shown in the status message indicating invalid command format and displays the correct usage format.
Test case: search (blank keyword with spaces)
Expected: No search is performed. Error details shown in the status message indicating invalid command format and displays the correct usage format.
Test case: search John_123 (contains underscore)
Expected: No search is performed. Error details shown due to non-alphanumeric characters in keyword.
Test case: search [a string of 21 characters]
Expected: No search is performed. Error details shown due to exceeding 20-character limit.
Test case: search keyword1 keyword2 keyword3 keyword4 keyword5 keyword6 (more than 5 keywords)
Expected: No search is performed. Error details shown indicating invalid command format because maximum keywords is exceeded.
Test case: search keywordThatDoesNotMatchAnyEmployee
Expected: Empty list shown. Status message indicates "0 employees listed!".
Other incorrect search commands to try: search @lphabet, search 123!@#
Expected: Similar error messages shown due to non-alphanumeric characters.
Editing an employee's details
Prerequisites: List all employees using the list command. Employee to edit exists in the list.
Test case: edit 1 n/Bob Choo p/22222222 e/bob@example.com r/Head of Office d/Marketing t/friend (Valid entry)
Expected: After user enters "y" to a y/n confirmation prompt, The employee is edited. The success message is shown, along with the updated details.
Test case: edit 1 n/Amy Choo p/22222222 e/amy@example.com r/Head of Office d/Marketing t/friend (Preamble is a space)
Expected: After user enters "y" to a y/n confirmation prompt, The employee is edited. The success message is shown, along with the updated details.
Test case: edit 1 k n/Amy Choo p/22222222 e/amy@example.com r/Head of Office d/Marketing t/friend (Preamble is not a space)
Expected: The employee is not edited. An error message is shown, indicating invalid command format.
Test case: edit 1 p/!#$!*)**%{ (Invalid field)
Expected: The employee is not edited. An error message is shown, indicating invalid field value.
Test case: edit 1 t/friend t/husband (Multiple tags)
Expected: After user enters "y" to a y/n confirmation prompt, The employee is edited. The success message is shown, along with the updated details.
Test case: edit 1 n/Amy Cho n/Bob Choo p/11111111 e/bob@meme.com r/Head of Operations d/Marketing t/friend (Duplicate fields)
Expected: The employee is not edited. Error messages for duplicated prefix shown.
Test case: edit 0 n/Amy Cho (Invalid index)
Expected: The employee is not edited. An error message is shown, indicating invalid command format.
Test case: edit n/James& p/11111111 e/bob@meme.com (Invalid name)
Expected: The employee is not edited. The correct format for a valid name is shown.
Other incorrect commands with invalid data: edit 1 <other details> e/a (Invalid email) or similar
Expected: The employee is not edited. An error message is shown, indicating invalid field value.
Other incorrect delete commands to try: add, add johndoe p/3333 (no prefix), and other commands which deviate from the command format
Expected: Similar to previous.
Editing an employee's details
Prerequisites: Existing list is non-empty, target destination is non-empty
Test case: export C:\Users\username\Downloads\test.csv (Valid entry, assuming tester doesn't have existing test.csv in Downloads folder)
Expected: A file test.csv is created in the User's Downloads folder, containing the current employee data in csv format.
Test case: export asasearoj (Invalid path)
Expected: No csv file is created. An error message is shown, indicating invalid file path.
Test case: export C:\Users\username\Downloads\existingfile.csv (Invalid entry, existing file in destination)
Expected: No csv file is created. An error message is shown, indicating existing file.
Dealing with missing/corrupted data files
{ more test cases … }