`
+that has been set to true.
+
+**Step 4** `Model#updateFilteredDeveloperList` then updates the list in the UI to print all the existing developers.
+
+The following sequence diagram provides an overview of how the find operation is executed
+
+![sequence diagram](images/ListDeveloperSequenceDiagram.png)
+
+### Undo/redo feature
+
+#### Implementation - undo
+
+The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo
+history, stored internally as an `addressBookStateList` and `currentStatePointer`. Customised to the functions of CodeContact to
+have a more helpful message and automatic tab switch, the history for messages and tabs are also stored internally as
+`successfulCommandMessages` and `tabIndex`.
+Additionally, it implements the following operations:
* `VersionedAddressBook#commit()` — Saves the current address book state in its history.
* `VersionedAddressBook#undo()` — Restores the previous address book state from its history.
@@ -277,72 +354,206 @@ The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It ex
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.
+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 address book state, and the `currentStatePointer` pointing to that single address book state.
+**Step 1** The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
![UndoRedoState0](images/UndoRedoState0.png)
-Step 2. The user executes `delete 5` command to delete the 5th developer in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+**Step 2** The user executes `delete-developer 5` command to delete the 5th developer in the address book. The `delete`
+command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete-developer 5`
+command executes to be saved in the `addressBookStateList`. The successful command message and tab it switched to
+also saved into `successfulCommandMessages` and `tabIndex` respectively. The `currentStatePointer` is then shifted to the newly
+inserted address book state.
![UndoRedoState1](images/UndoRedoState1.png)
-Step 3. The user executes `add n/David …` to add a new developer. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+**Step 3** The user executes `add-developer n/David …` to add a new developer. The `add` command also calls
+`Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`,
+and another successful command message and tab switched saved into `successfulCommandMessages` and `tabIndex`.
![UndoRedoState2](images/UndoRedoState2.png)
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
-
-Step 4. The user now decides that adding the developer 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 address book state, and restores the address book to that state.
+**Step 4** The user now decides that adding the developer 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 address book state, and restores the address book to that state.
![UndoRedoState3](images/UndoRedoState3.png)
- @@ -353,17 +457,23 @@ The following sequence diagram shows how the undo operation works:
-
-
+The following sequence diagram shows how the undo operation works:
+![UndoRedoState3](images/UndoSequenceDiagram.png)
+#### Implementation - redo
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 address book to that state.
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book 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 address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
+**Step 5** The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
![UndoRedoState4](images/UndoRedoState4.png)
-Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book 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.
-
-![UndoRedoState5](images/UndoRedoState5.png)
- @@ -376,13 +486,13 @@ The following activity diagram summarizes what happens when a user executes a ne
**Aspect: How undo & redo executes:**
* **Alternative 1 (current choice):** Saves the entire address book.
* Pros: Easy to implement.
* Cons: May have performance issues in terms of memory usage.
-* **Alternative 2:** Individual command knows how to undo/redo by
- itself.
+* **Alternative 2 (part of current choice):** Individual command knows how to undo/redo by itself.
* Pros: Will use less memory (e.g. for `delete`, just save the developer being deleted).
* Cons: We must ensure that the implementation of each individual command are correct.
+ * Due to a special parameter `role` having its own add and delete functions which are separated from the
+ model and not stored in address book, it uses alternative 2 whereby `undo` an `add-developer-role` will just
+ execute the `delete-developer-role function`. The process of this implementation had to be very careful just like
+ what the cons mentioned, a slight validation error can change the whole `undo` and `redo` feature.
+
+### Add-role feature
+#### Implementation
+The add role command employs a structured approach where specific commands, such as `add-developer-role` or
+`add-client-role`are associated with corresponding functionalities. This allows users to efficiently add
+information about developers and clients. One of the validation checks when adding a developer or client is that this role
+added must exist. This is where users will need this command to add in the respective roles. This feature is facilitated
+with the `DeveloperRoles` and `ClientRoles` class which implements the following operations:
+
+* `DeveloperRoles#addDeveloperRole()` — Adds a developer role into the list of roles stored
+* `DeveloperRoles#saveDeveloperRoles()` — Saves the updated list of developer roles
+* `DeveloperRoles#loadDeveloperRoles()` — Loads the existing list of developer roles from file
+* `DeveloperRoles#isValidRole()` — Checks if this role being added exists already
+
+The classes are similar for `ClientRoles` but just that they are associated with the clients.
+
+Given below is an example usage scenario and how the `add-developer-role` mechanism behaves at each step:
+
+**Step 1** The user launches the application. The list roles for developers and clients are loaded into a list or roles.
+
+**Step 2** The user executes the command `add-developer-role Tester`. The application recognizes the `add-developer-role`
+and calls `AddDeveloperRoleCommandParser#parse()`.
+
+**Step 3** The parser checks if the argument is an empty blank space and trims the input given, in this case ` Tester` is
+trimmed to `Tester` and calls `AddDeveloperRoleCommand`.
+
+**Step 4** `AddDeveloperRoleCommand#execute()` checks if there is an existing role with the same name and creates
+a new developer role if there is no such role.
+
+ :exclamation: **Note:**
+Although no changes is made to the address book, this stage is still committed so that the success command
+message and tab index switched to can be changed, the currentPointer can also note that there is an action done here.
+
+ :exclamation: **Note:**
+This is not a case-sensitive feature. The command allows users to add `developer` even if `Developer` exists.
+
+The following sequence diagram shows how the Add-role operation works:
+![SequenceDiagram](images/AddDeveloperRoleSequenceDiagram.png)
+
+**Aspect: How add-role executes:**
+* **Alternative 1 (current choice):** Treat role as a variable, has a separate load and unload list
+ * Pros: Role can just be treated as an attributed that needs more validation checks
+ * Cons: Have to load and unload each time system relaunches, quite time and memory consuming
+
+* **Alternative 2:** Treating role like another person or project, adding roles are like adding projects
+ * Pros: Easy to implement.
+ * Cons: Roles would have to be implemented on the same level as developers, clients and projects which should not be case.
+
+
+### Delete-role feature
+#### Implementation
+The add role command employs a structured approach where specific commands, such as `delete-developer-role` or
+`delete-client-role`are associated with corresponding functionalities. This allows users to efficiently delete
+information about developers and clients that they no longer need.The system helps you to check if there are any
+developers or clients in the list using this feature. If there is, the command will not be successfully executed.
+This feature is facilitated with the `DeveloperRoles` and `ClientRoles` class which implements the following operations:
+
+* `DeveloperRoles#deleteDeveloperRole()` — Deletes a developer role into the list of roles stored
+* `DeveloperRoles#saveDeveloperRoles()` — Saves the updated list of developer roles
+* `DeveloperRoles#loadDeveloperRoles()` — Loads the existing list of developer roles from file
+* `DeveloperRoles#isRemovableRole()` — Checks if this role can be deleted; It should not be a pre-determined role,
+it should not be a non-existing role, it should not be a role that is in use.
+
+The classes are similar for `ClientRoles` but just that they are associated with the clients.
+
+Given below is an example usage scenario and how the `delete-developer-role` mechanism behaves at each step:
+
+**Step 1** The user launches the application. The list roles for developers and clients are loaded into a list or roles.
+
+**Step 2** The user executes the command `delete-developer-role Tester`. The application recognizes the `delete-developer-role`
+and calls `DeleteDeveloperRoleCommandParser#parse()`.
+
+**Step 3** The parser checks if the argument is an empty blank space and trims the input given, in this case ` Tester` is
+trimmed to `Tester` and calls `DeleteDeveloperRoleCommand`.
+
+**Step 4** `DeleteDeveloperRoleCommand#execute()` checks if this is a removable role and removes it from the list of roles
+if `DeveloperRoles#isRemovableRole()` returns true.
+
+ :exclamation: **Note:**
+Although no changes is made to the address book, this stage is still committed so that the success command
+message and tab index switched to can be changed, the currentPointer can also note that there is an action done here.
-_{more aspects and alternatives to be added}_
+The following sequence diagram shows how the Delete-role operation works:
+![SequenceDiagram](images/DeleteDeveloperRoleSequenceDiagram.png)
- @@ -416,8 +526,9 @@ _{Explain here how the data archiving feature will be implemented}_
+The following activity diagram shows how the validation check in `DeveloperRoles#isRemovableRole()` works:
+![ActivityDiagram](images/isRemovableRole.png)
+
+* _{more aspects and alternatives to be added}_
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+## **Documentation, logging, testing, configuration, dev-ops**
+* [Documentation guide](https://ay2324s1-cs2103t-t09-2.github.io/tp/Documentation.html)
+* [Testing guide](https://ay2324s1-cs2103t-t09-2.github.io/tp/Testing.html)
+* [Logging guide](https://ay2324s1-cs2103t-t09-2.github.io/tp/Logging.html)
+* [Configuration guide](https://ay2324s1-cs2103t-t09-2.github.io/tp/Configuration.html)
+* [DevOps guide](https://ay2324s1-cs2103t-t09-2.github.io/tp/DevOps.html)
+
+--------------------------------------------------------------------------------------------------------------------
+## **Appendix: Requirements**
+
+### Project Scope
+**Target user profile**:
+
+* has a need to manage a significant number of colleague contacts internally
+* prefer desktop apps over other types
+* can type fast
+* prefers typing to mouse interactions
* is reasonably comfortable using CLI apps
* a project manager or someone with similar needs working within a software company
-**Value proposition**: CodeContact aims to seamlessly integrate contact, client, and project management, simplifying access to coding-related contacts, facilitating collaboration, and offering command-line efficiency for project managers.
-
+**Value proposition**: CodeContact aims to seamlessly integrate contact, client, and project management, simplifying
+access to coding-related contacts, facilitating collaboration, and offering command-line efficiency for project
+managers.
### User stories
-
- @@ -440,12 +551,12 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
-| `* *` | project manager | | |
-| `* *` | project manager | | |
+Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely) - `*`
+
+| Priority | As a … | I want to … | So that I can… |
+|----------|-----------------|------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|
+| `* * *` | project manager | add a list of Developers and their contact information | access contact details easily and quickly assemble teams for new projects |
+| `* * *` | project manager | add a list of Clients and their contact information | access client details easily and know who is related to what project. |
+| `* * *` | project manager | add a list of Projects and their details | access project details easily and see who is related to the project |
+| `* * *` | project manager | delete information about a Client or Developer and the project details will update accordingly | don't repeat deleting several time |
+| `* * *` | project manager | edit the the details of the Developers added in | constantly update the contact book |
+| `* * *` | project manager | edit the the details of the Clients added in | constantly update the contact book |
+| `* * *` | project manager | edit the the details of the Projects added in | constantly update any changes to the project |
+| `* * *` | project manager | find the the Developers according to any details they have | source for information related to developers easily |
+| `* * *` | project manager | find the the Clients according to any details they have | source for information related to clients easily |
+| `* * *` | project manager | find the the Projects according to any details they have | source for information related to projects easily |
+| `* * *` | project manager | list different groups of people according to the different commands | view projects, clients and developers can be as different lists |
+| `* * *` | project manager | switch between tabs for Developers, Clients and Projects | intuitively view the different data lists |
+| `* * *` | project manager | import data from a csv | transfer data from what i am using right now |
+| `* *` | project manager | add roles | only add people to existing roles in the system so that i do not assign people to random roles |
+| `* *` | project manager | delete roles | remove roles that i think are not useful anymore |
+| `* *` | project manager | undo actions | undo any mistakes i made |
+| `* *` | project manager | redo actions | redo anything i accidentally undid |
+| `* *` | project manager | lock all the data | keep all these data safe |
+| `* *` | project manager | unlock all the data | see all these data after locking it |
+| `* *` | project manager | change password | access these data without worrying data might be stolen |
+| `* *` | project manager | find by deadline | sort out information by deadline due |
+| `* ` | project manager | send reminder emails to the developers when deadlines are nearing | it can remind them that work is due soon |
+| `* ` | project manager | give developers feedback directly from CodeContact | reviews can be autogenerated trough my ratings and i need to write a new review each time |
*{More to be added}*
@@ -351,114 +562,175 @@ _{more aspects and alternatives to be added}_
(For all use cases below, the **System** is the `AddressBook`, and the **Actor** is the `user`, unless specified otherwise)unless specified otherwise)
-#### **Use case:** UC1 - Add a single employee
- @@ -454,27 +565,28 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
-**Preconditions:** User is logged in as an HR staff
+#### **Use case:** UC1 - Add a developer
+
+ :exclamation: **Note:**
+Adding developers and clients works the same way, but with different parameters, hence it will not be repeated
+
+**Preconditions:** User is logged in
**Guarantees:**
-1. A new profile will be added to the company's system after every successful addition
-2. A login credential for the added user will be created
+1. A new developer will be added to the system after every successful addition
**MSS**
-1. User requests to add an employee.
-2. System requests the details of the employee.
+1. User requests to add a developer.
+2. System requests the details of the developer.
3. User enters the requested details in the required format.
-4. System requests for confirmation.
-5. User confirms.
-6. System adds the new employee to the company database.
+4. System validates if user's inputs are valid.
+6. System adds the developer to the data.
Use case ends.
**Extensions**
-* 1a. The request is done by a non-HR staff.
+* 3a. The given details are invalid or in an invalid format.
+ * 3a1. System requests for the correct data
+ * 3a2. User enters new data
+
Steps 3a1-3a2 are repeated until the data entered are correct.
+
Use case resumes from step 4.
- * 1a1. System informs user that user does not have the access rights to add a new employee.
+#### **Use case:** UC2 - Delete a developer
+ :exclamation: **Note:**
+Deleting developers and clients works the same way, but with different parameters, hence it will not be repeated
- Use case ends.
+**Preconditions:** User is logged in
-* 3a. The given details are invalid or in an invalid format.
+**Guarantees:**
+1. A developer deleted from the system after every successful delete
- @@ -486,24 +598,27 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
- Use case resumes at step 4.
+**MSS**
-* *a. At any time, User chooses to cancel the action.
- * *a1. System requests to confirm the cancellation.
- * *a2. User confirms the cancellation.
+1. User requests to delete a developer.
+2. System requests the index of the developer.
+3. User enters the index of the developer.
+4. System validates index is valid.
+5. System deletes the developer to the data.
Use case ends.
-#### **Use case:** UC2 - Logging in as a specific user
+**Extensions**
+
+* 3a. The index entered is an invalid number or is not a number.
+ * 3a1. System requests for the correct index
+ * 3a2. User enters new index
+
Steps 3a1-3a2 are repeated until the data entered are correct.
+
Use case resumes from step 4.
-**Actor:** Any Employee
+#### **Use case:** UCX - Undo
-**Preconditions:**
-1. The employee has valid login credentials provided by the HR.
+**Preconditions:** User is logged in
**Guarantees:**
-1. User is logged into their account system.
-2. They only have the access rights to the user-specific features (eg. developers can only modify their personal
-particulars and no other information).
+1. The previous command will be undone.
**MSS**
-1. User accesses the login page of the system.
-2. System presents the login page to the user.
-3. User enters their own login credentials and submits to the system.
- @@ -513,80 +628,92 @@ particulars and no other information).
- Use case ends.
+
+1. User requests undo.
+2. System checks if there were any changes before.
+3. System reverts the change.
+
Use case ends.
**Extensions**
-* 4a. The login credentials are invalid (no record it is created).
- * 4a1. System informs user there is an erro and directs user to seek HR for help.
- Use case ends.
+* 3a. There are no changes before
+ * 3a1. System informs users they have reached the first step
+
Use case ends
+
+#### **Use case:** UCX - Redo
+
+**Preconditions:** User is logged in
+
+**Guarantees:**
+1. The previous command undone will be redone.
-* 4b. The login credentials has an invalid format.
- * 4b1. System informs user there is an error and requests for correct input.
- * 4b2. User enters requested details again.
+**MSS**
- Step 4b1-4b2 are repeated until details entered are valid.
+1. User requests redo.
+2. System checks if there were anything undone changes before.
+3. System redoes the change.
+
Use case ends.
- Use case resumed at step 5.
+**Extensions**
-#### **Use case:** UC3 - Search for other employee's contacts
+* 3a. There are no undone changes before
+ * 3a1. System inform users they have reached the last step
+
Use case ends
-**Actor:** Any Employee
+#### **Use case:** UCX - Add developer role
+ :exclamation: **Note:**
+Adding developer roles and client roles works the same way, hence add client role use case will not be repeated
-**Precondition:**
-1. User is logged in.
-2. System identifies what role the user is (so that no irrelevant information is shown).
+**Preconditions:** User is logged in
**Guarantees:**
-1. User can view the contact information and details of other users based on the
-search keyword.
-2. User can only view relevant information their roles have access rights to.
+1. A new developer role will be added.
**MSS**
-1. User requests to search an employee
-2. System requests the keywords for the search.
-3. User enters the requested details in the required format.
-4. System processes the search request and retrieves a list of employees matching the provided criteria.
-5. System displays search results, which include the names of employees who match the search criteria along
-with information that user's role has access rights to.
- Use case ends.
+1. User requests to add a developer role.
+2. User enters the role they want to add.
+3. System validates if user's inputs are valid.
+4. System validates if user's inputs can be added.
+5. System adds the developer to the data.
**Extensions**
-* 3a. The search has an invalid type or format.
- * 3a1. System informs user there is an error and requests for correct input.
- * 3a2. User enters requested details again.
- Steps 3a1-3a2 are repeated until details entered are valid.
+* 3a. User enters an empty role
+ * 3a1. System requests for the correct role
+ * 3a2. User enters new role
+
Steps 3a1-3a2 are repeated until the data entered is not empty
+
Use case resumes from step 4.
- Use case resumes at step 4.
+* 4a. User enters an existing role
+ * 4a1. System informs users this role exists
+ * 4a2. User enters new role
+
Steps 4a1-4a2 are repeated until the data entered is not empty
+
Use case resumes from step 5.
-* 4a. There is no matching list of employees.
- * 4a1. System informs user that no relevant information is found
+#### **Use case:** UCX - Delete developer role
+ :exclamation: **Note:**
+Deleting developer roles and client roles works the same way, hence deleting client role use case will not be repeated
- Use case ends.
+**Preconditions:** User is logged in
+
+**Guarantees:**
+1. A developer role will be deleted.
+
+**MSS**
+
+1. User requests to delete a developer role.
+2. User enters the role they want to delete.
+3. System validates if user's inputs are valid.
+4. System validates if user's input can be deleted.
+5. System adds the developer to the data.
+
+**Extensions**
+
+* 3a. User enters an empty role
+ * 3a1. System requests for the correct role
+ * 3a2. User enters correct role
+
Steps 3a1-3a2 are repeated until the data entered is not empty
+
Use case resumes from step 4.
+
+* 4a. User enters a role that some developer is still using
+ * 4a1. System informs users this role cannot be deleted as there are developers using
+ * 4a2. User enters correct role
+
Steps 4a1-4a2 are repeated until the data entered is can be deleted
+
Use case resumes from step 5.
+
+* 4b. User enters a role that doesn't exist
+ * 4b1. System informs users this role don't exist
+ * 4b2. User enters correct role
+
Steps 4a1-4a2 are repeated until the data entered is can be deleted
+
Use case resumes from step 5.
+
+* 4b. User enters a role that cannot be deleted
+ * 4b1. System informs users this role cannot be deleted as it is a pre-defined role
+ * 4b2. User enters correct role
+
Steps 4a1-4a2 are repeated until the data entered can be deleted
+
Use case resumes from step 5.
### Non-Functional Requirements
@@ -478,47 +750,50 @@ in a clear and user-friendly manner.
* A comprehensive user manual or online documentation shall be provided to explain how to use the application.
#### Process Requirements
* The project is expected to adhere to a schedule that completes a milestone set every two weeks.
-* The projsct shall follow a iterative breadth-first development methodology
+* The project shall follow an iterative breadth-first development methodology
* Automated testing suits shall be maintained and run for each build
-* Code review shall be conducted for all new code contrivution, with at least one team member
+* Code review shall be conducted for all new code contribution, with at least one team member
reviewing each piece of code before it is merged
* All project source code shall be stored in a version control system (e.g., Git),
and commits should follow a consistent naming convention.
* Coding standards and style guidelines shall be defined and followed consistently by all development team members.
-*{More to be added}*
- @@ -611,15 +738,16 @@ testers are expected to do more *exploratory* testing.
+### Glossary
+
+--------------------------------------------------------------------------------------------------------------------
+## **Appendix: Manual Testing**
+testers are expected to do more *exploratory* testing.
1. Initial launch
1. Download the jar file and copy into an empty folder
- 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
+ 2. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-1. Saving window preferences
+2. Saving window preferences
1. Resize the window to an optimum size. Move the window to a different location. Close the window.
- 1. Re-launch the app by double-clicking the jar file.
+ 2. Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-1. _{ more test cases … }_
- @@ -628,23 +756,24 @@ testers are expected to do more *exploratory* testing.
+3. _{ more test cases … }_
+ @@ -628,23 +756,24 @@ testers are expected to do more *exploratory* testing.
-1. Deleting a developer while all developers are being shown
+4. Deleting a developer while all developers are being shown
1. Prerequisites: List all developers using the `list` command. Multiple developers in the list.
- 1. Test case: `delete 1`
+ 2. Test case: `delete 1`
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
- 1. Test case: `delete 0`
+ 3. Test case: `delete 0`
Expected: No developer is deleted. Error details shown in the status message. Status bar remains the same.
- 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
+ 4. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
Expected: Similar to previous.
-1. _{ more test cases … }_
+5. _{ more test cases … }_
### Saving data
@@ -526,4 +801,30 @@ and commits should follow a consistent naming convention.
1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
-1. _{ more test cases … }_
+2. _{ more test cases … }_
+
+--------------------------------------------------------------------------------------------------------------------
+
+## **Appendix: Planned Enhancement**
+
+### Validation checks for edit
+**Current Behavior:** Two developers can have the same address, contact number etc. As long as they don't have the same name
+they can both be added.
+**Enhanced Behavior:** Validation checks should be added for email, contact number and address to make sure there are no 2
+people with repeated the details.
+
+### Case-sensitive validation checks for adding roles
+**Current Behavior:** Two similar roles with different cases can both be added. `Developer` and `developer` can exist at the
+same time.
+**Enhanced Behavior:** Two same words that are only differentiated by case should not be able to be added in as a role.
+
+### Deadlines cannot be any date
+**Current Behavior:** Deadlines for projects can be any date such at year 0001.
+**Enhanced Behavior:** There should be a limit to the deadline line dates like 10-20 years before and after the current date.
+
+### Password Recovery
+**Current Behavior:** If you forgot your password, there is no way to retrieve it
+**Enhanced Behavior:** Links the system to email or have verifications that allows users to reset their password.
+
+--------------------------------------------------------------------------------------------------------------------
+## **Appendix: Effort**
diff --git a/docs/Documentation.md b/docs/Documentation.md
index 3e68ea364e7..0e33867d565 100644
--- a/docs/Documentation.md
+++ b/docs/Documentation.md
@@ -18,7 +18,7 @@ title: Documentation guide
* Follow the [**_Google developer documentation style guide_**](https://developers.google.com/style).
-* Also relevant is the [_[se-edu/guides] **Markdown coding standard**_](https://se-education.org/guides/conventions/markdown.html)
+* Also, relevant is the [_[se-edu/guides] **Markdown coding standard**_](https://se-education.org/guides/conventions/markdown.html)
**Diagrams:**
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index b312c1bd87a..4cc6f34635c 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -3,58 +3,62 @@ layout: page
title: User Guide
---
-Seamlessly integrate contact, client, and project management, simplifying access to coding-related contacts,
-facilitating collaboration, and offering command-line efficiency for project managers
-
-CodeContact is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still
-having the benefits of a Graphical User Interface (GUI). If you can type fast, CodeContact can get your contact
-management tasks done faster than traditional GUI apps.
-
## Table of Contents
+* [Introduction](#introduction)
* How can this guide help me?
* Navigating this guide
- * Glossary
- * Definitions
- * Parameter Information
- * Common parameters
- * Developer parameters
- * Client parameters
- * Project parameters
- * Format
- * General Formatting
- * Command Format
-* Navigating the Graphical User Interface (GUI)
+ * [Glossary](#glossary)
+ * [Definitions](#definitions)
+ * [Parameter Information](#parameter-information)
+ * [Common parameters](#common-parameters)
+ * [Developer parameters](#developer-parameters)
+ * [Client parameters](#client-parameters)
+ * [Project parameters](#project-parameters)
+ * [Format](#format)
+ * [General Formatting](#general-formatting)
+ * [Command Format](#command-format)
+* [Navigating the Graphical User Interface (GUI)](#navigating-the-graphical-user-interface--gui-)
* [Quick Start](#quick-start)
* [CodeContact Tutorial](#codecontact-tutorial--for-new-users-)
* [Features](#features)
-
-| Description | Developer | Client | Project |
-|:-------------------------------|:-------------------------------------------------------------------------:|:----------------------------------------------------------------:|:----------------:|
-| Adding new information | `add-developer` | `add-client` | `add-project` |
-| Editing information | `edit-developer` | `edit-client` | `edit-project` |
-| Importing information | `import-developer` | `import-client` | - |
-| Deleting information | `delete-developer` | `delete-client` | `delete-project` |
-| Finding information | `find-developer` | `find-client` | `find-project` |
-| Listing information | `list-developer` | `list-client` | `list-project` |
-| [Adding new role](#add-roles) | [`add-developer-role`](#add-developer-roles--add-developer-role) | [`add-client-role`](#add-client-roles--add-client-role) | - |
-| [Deleting role](#delete-roles) | [`delete-developer-role`](#delete-developer-roles--delete-developer-role) | [`delete-client-role`](#delete-client-roles--delete-client-role) | - |
-
-* [Lock `lock`](#lock-lock)
-* [Unlock `unlock`](#unlock-unlock)
-* [Change password `change-password`](#change-password-change-password)
-* [Mark deadline as done `mark-deadline`](#mark-deadline-as-done--mark-deadline)
-* [Mark deadline as undone `unmark-deadline`](#mark-deadline-as-undone--unmark-deadline)
-* [Find Deadline `find-deadline`](#find-deadlines-find-deadline)
-* [Undo `undo`](#undo--undo)
-* [Redo `redo`](#redo--redo)
-* [Help `help`](#viewing-help--help)
-* [Clear entries `clear`](#clearing-all-entries--clear)
-* [Exit program `exit`](#exiting-the-program--exit)
+ * [Lock `lock`](#lock-lock)
+ * [Unlock `unlock`](#unlock-unlock)
+ * [Change password `change-password`](#change-password-change-password)
+
+| Description | Developer | Client | Project |
+|:--------------------------------------------------|:-------------------------------------------------------------------------:|:----------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------:|
+| [Adding new information](#add) | [`add-developer`](#add-developer--add-developer) | [`add-client`](#add-client--add-client) | [`add-project`](#add-project--add-project) |
+| [Deleting information](#delete) | [`delete-developer`](#delete-developer--delete-developer) | [`delete-client`](#delete-client--delete-client) | [`delete-project`](#delete-project--delete-project) |
+| [Editing information](#edit) | [`edit-developer`](#edit-developer-details--edit-developer) | [`edit-client`](#edit-client-details--edit-client) | [`edit-project`](#edit-project-details--edit-project) |
+| [Importing information](#import-information) | [`import-developer` ](#import-developers-import-developer) | [`import-client`](#import-clients-import-client) | - |
+| [Finding information](#find) | [`find-developer`](#find-developer-details) | [`find-client`](#find-client-details) | [`find-project`](#find-project-details), [`find-deadline`](#find-deadlines-find-deadline) |
+| [Listing information](#listing-information--list) | `list-developer` | `list-client` | `list-project` |
+| [Adding new role](#add-roles) | [`add-developer-role`](#add-developer-roles--add-developer-role) | [`add-client-role`](#add-client-roles--add-client-role) | - |
+| [Deleting role](#delete-roles) | [`delete-developer-role`](#delete-developer-roles--delete-developer-role) | [`delete-client-role`](#delete-client-roles--delete-client-role) | - |
+
+*
+ * [Mark deadline as done `mark-deadline`](#mark-deadline-as-done--mark-deadline)
+ * [Mark deadline as undone `unmark-deadline`](#mark-deadline-as-undone--unmark-deadline)
+ * [Undo `undo`](#undo--undo)
+ * [Redo `redo`](#redo--redo)
+ * [Help `help`](#viewing-help--help)
+ * [Clear entries `clear`](#clearing-all-entries--clear)
+ * [Exit program `exit`](#exiting-the-program--exit)
* [FAQ](#faq)
* [Known Issues](#known-issues)
* [Command Summary](#command-summary)
+-------------------------------------------------------------------------------------
+## Introduction
+
+Seamlessly integrate contact, client, and project management, simplifying access to coding-related contacts,
+facilitating collaboration, and offering command-line efficiency for project managers
+
+CodeContact is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still
+having the benefits of a Graphical User Interface (GUI). If you can type fast, CodeContact can get your contact
+management tasks done faster than traditional GUI apps.
+
-------------------------------------------------------------------------------------
## How can this guide help me?
@@ -72,6 +76,7 @@ Confused about the terms or formatting used in this guide? Learn how to **naviga
Confused about the visual display of CodeContact? Learn how to **navigate the user interface** of CodeContact
[here](#navigating-the-graphical-user-interface--gui-).
+
------------------------------------------------------------------------------------------
## Navigating this guide
@@ -141,6 +146,7 @@ Here are some notes about these parameters.
| `dr/` | description of project | alphanumeric characters and spaces, and it should not be blank | App to allow for different juices to be ordered | |
| `dl/` | deadline of project | alphanumeric characters and spaces, and it should not be blank | 19-12-2023, Design backend, HIGH, 0 | |
+[Scroll back to Table of Contents](#table-of-contents)
-----------------------------------------------------------------------------------------------
@@ -165,6 +171,8 @@ Here are some notes about these parameters.
6. Refer to the [Features](#features) below for details of each command.
+[Scroll back to Table of Contents](#table-of-contents)
+
--------------------------------------------------------------------------------------------------------------------
## CodeContact Tutorial (for new users)
@@ -181,8 +189,8 @@ This is a tutorial for **first-time** CodeContact users.
1. You can **change the password** to unlock CodeContact.
* Enter the command `change-password pw/Password123! npw/` in the command box
- * ❗Note: You can always lock and unlock CodeContact using the `lock` and `unlock` commands
-
+ :exclamation: **Note:**
+You can always lock and unlock CodeContact using the `lock` and `unlock` commands
1. Let us try **adding a project** to our CodeContact.
* Enter the
@@ -235,6 +243,7 @@ Congratulations! You are now ready to use CodeContact!
To view all our features, you may visit our [Features](#features) section
+[Scroll back to Table of Contents](#table-of-contents)
--------------------------------------------------------------------------------------------------------------------
## Features
@@ -262,7 +271,6 @@ To view all our features, you may visit our [Features](#features) section
* If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines
as space characters surrounding line-breaks may be omitted when copied over to the application.
-
### Lock `lock`
@@ -277,6 +285,8 @@ When command succeeds, CLI shows:
Locked all data
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Unlock `unlock`
Unlocks the system by making all the information visible and allows all commands to be parsed.
@@ -292,6 +302,8 @@ When command succeeds, CLI shows:
Unlocked all data
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Change password `change-password`
Allows for password to be changed, given the current password and new password matches criteria
@@ -309,11 +321,13 @@ When command succeeds, CLI shows:
Password changed successfully.
```
-## Add
+[Scroll back to Table of Contents](#table-of-contents)
+
+### Add
-Project Managers can add developers, clients and projects.
+Project Manager can add developers, clients and projects.
-### Add Developer: `add-developer`
+#### Add Developer: `add-developer`
* Type in:
* `add-developer`
@@ -357,25 +371,23 @@ Example:
* Missing particular's error (when prefixes are missing)
* `Invalid command format!`
-### Add Client: `add-client`
-
-Type in:
- `add-client`
-
-And populate his/her details with prefixes and fields by typing in
-* `n/NAME` for the client's name
-* `p/PHONE_NUMBER` for the client's phone number
-* `e/EMAIL` for the client's email
-* `a/ADDRESS` for the client's address
-* `r/ROLE` for the client's role in their organisation
-* `pr/{PROJECT1, PROJECT2…}` for client's assigned projects
-* `o/ORGANISATION` for the organisation the client is representing
-* `do/DOCUMENT` for the document associated with the client
-
+[Scroll back to Table of Contents](#table-of-contents)
-In the following overall format
+#### Add Client: `add-client`
-`add-client n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS r/ROLE pr/PROJECT1 pr/PROJECT2 o/ORGANISATION do/document`
+* Type in:
+ * `add-client`
+* And populate his/her details with prefixes and fields by typing in
+ * `n/NAME` for the client's name
+ * `p/PHONE_NUMBER` for the client's phone number
+ * `e/EMAIL` for the client's email
+ * `a/ADDRESS` for the client's address
+ * `r/ROLE` for the client's role in their organisation
+ * `pr/{PROJECT1, PROJECT2…}` for client's assigned projects
+ * `o/ORGANISATION` for the organisation the client is representing
+ * `do/DOCUMENT` for the document associated with the client
+* In the following overall format
+ * `add-client n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS r/ROLE pr/PROJECT1 pr/PROJECT2 o/ORGANISATION do/document`
Example:
@@ -402,17 +414,18 @@ Example:
* Missing particular's error (when prefixes are missing)
* `Invalid command format!`
-### Add Project: `add-project`
-
-Type in: `add-project`
-And populate its details with prefixes and fields by typing in
-* `n/NAME` for the project's name
-* `dr/DESCRIPTION` for the project's description
-* `dl/{DEADLINE1, DEADLINE2...}` for deadlines associated with the project
+[Scroll back to Table of Contents](#table-of-contents)
-In the following overall format
+#### Add Project: `add-project`
-`add-project n/NAME dr/DESCRIPTION dl/DEADLINE1 dl/DEADLINE2 ...`
+* Type in:
+ * `add-project`
+* And populate its details with prefixes and fields by typing in
+ * `n/NAME` for the project's name
+ * `dr/DESCRIPTION` for the project's description
+ * `dl/{DEADLINE1, DEADLINE2...}` for deadlines associated with the project
+* In the following overall format
+ * `add-project n/NAME dr/DESCRIPTION dl/DEADLINE1 dl/DEADLINE2`
Example:
@@ -436,9 +449,11 @@ Example:
* Missing particular's error (when prefixes are missing)
* `Invalid command format!`
-## Delete
+[Scroll back to Table of Contents](#table-of-contents)
+
+### Delete
-### Delete developer: `delete-developer`
+#### Delete developer : `delete-developer`
Deletes developer in the address book.
@@ -448,7 +463,7 @@ Example of usage: `delete-developer 2`
* Deletes second developer from the list
-### Delete client: `delete-client`
+#### Delete client : `delete-client`
Deletes client in the address book.
@@ -458,7 +473,7 @@ Example of usage: `delete-client 3`
* Deletes third client in list.
-### Delete project: `delete-project`
+#### Delete project : `delete-project`
Deletes the details of an existing project in the address book.
@@ -468,6 +483,9 @@ Example of usage: `delete-project 2`
* Deletes second project from the list and updates developers and client details accordingly
+[Scroll back to Table of Contents](#table-of-contents)
+
+
### Edit
#### Edit developer details : `edit-developer`
@@ -503,6 +521,8 @@ Salary: 6999
Projects: Project1, Project2
```
+[Scroll back to Table of Contents](#table-of-contents)
+
#### Edit client details : `edit-client`
Edits the details of an existing client in the address book.
@@ -535,6 +555,8 @@ Document: google.com
Projects: ProjectA
```
+[Scroll back to Table of Contents](#table-of-contents)
+
#### Edit project details : `edit-project`
Edits the details of an existing project in the address book.
@@ -561,6 +583,8 @@ Deadlines:
1. Design backend by: 19-12-2023, priority: HIGH (undone)
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Import information
#### Import developers `import-developer`
@@ -603,6 +627,8 @@ Projects: ProjectBAndroidApp
for each developer successfully added
+[Scroll back to Table of Contents](#table-of-contents)
+
#### Import clients `import-client`
Takes in a CSV file and populates the internal list of clients if the file is formatted correctly
@@ -643,6 +669,8 @@ Projects: ProjectBAndroidApp
for each client successfully added
+[Scroll back to Table of Contents](#table-of-contents)
+
### Find
#### Find developer details
@@ -669,6 +697,8 @@ This is the one developer with matching information
```
followed by the matching developer's details in the GUI.
+[Scroll back to Table of Contents](#table-of-contents)
+
#### Find client details
Finds the details of an existing client in the address book.
@@ -693,6 +723,8 @@ These are the 2 clients with matching information
```
followed by the matching clients' details in the GUI.
+[Scroll back to Table of Contents](#table-of-contents)
+
#### Find project details
Finds the details of an existing project in the address book.
@@ -717,6 +749,8 @@ This is the one project with matching information
```
followed by the matching project's details in the GUI.
+[Scroll back to Table of Contents](#table-of-contents)
+
### Find deadlines `find-deadline`
Finds deadlines in project tab based on date and/or priority
@@ -736,6 +770,8 @@ When command succeeds, CLI shows:
These are the 3 projects with matching information.
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Listing information : `list`
Shows a list of all developers in the address book.
@@ -760,6 +796,8 @@ When command succeeds, CLI shows:
Listed all developers
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Add roles
#### Add developer roles : `add-developer-role`
@@ -786,6 +824,8 @@ When command succeeds, CLI shows:
New role for developer added: UIDesigner
```
+[Scroll back to Table of Contents](#table-of-contents)
+
#### Add client roles : `add-client-role`
Adds new client roles into the system.
@@ -810,6 +850,8 @@ When command succeeds, CLI shows:
New role for client added: Boss
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Delete roles
#### Delete developer roles : `delete-developer-role`
@@ -834,6 +876,7 @@ When command succeeds, CLI shows:
Role for developers deleted: UIDesigner
```
+[Scroll back to Table of Contents](#table-of-contents)
#### Delete client roles : `delete-client-role`
@@ -859,6 +902,7 @@ Role for clients deleted: Boss
the client tab will be cleared or only showing the clients with role you are deleting.
Use `list-client` to see all the data again
+[Scroll back to Table of Contents](#table-of-contents)
### Mark deadline as done : `mark-deadline`
@@ -878,6 +922,8 @@ When command succeeds, CLI shows:
The deadline has been marked as completed!
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Mark deadline as undone : `unmark-deadline`
Marks the indicated deadline for the project as undone.
@@ -896,6 +942,8 @@ When command succeeds, CLI shows:
The deadline has been marked as undone!
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Undo : `undo`
Undo the previous command you entered.
@@ -925,6 +973,8 @@ Salary: 5000;
Projects: CustomWebsiteAndroidApp
```
+[Scroll back to Table of Contents](#table-of-contents)
+
### Redo : `redo`
Redo the previous command you undid.
@@ -954,6 +1004,7 @@ Salary: 5000;
Projects: CustomWebsiteAndroidApp
```
+[Scroll back to Table of Contents](#table-of-contents)
### Viewing help : `help`
@@ -961,18 +1012,24 @@ Shows a message explaining how to access the help page.
Format: `help`
+[Scroll back to Table of Contents](#table-of-contents)
+
### Clearing all entries : `clear`
Clears all entries from the address book.
Format: `clear`
+[Scroll back to Table of Contents](#table-of-contents)
+
### Exiting the program : `exit`
Exits the program.
Format: `exit`
+[Scroll back to Table of Contents](#table-of-contents)
+
### Feedback System `[coming in v2.0]`
--------------------------------------------------------------------------------------------------------------------
@@ -1014,6 +1071,8 @@ the data of your previous AddressBook home folder.
**A**: Open a command prompt and type `java -version` . If you do not have Java installed, you
can download it [here](https://www.oracle.com/java/technologies/downloads/#java11)
+[Scroll back to Table of Contents](#table-of-contents)
+
--------------------------------------------------------------------------------------------------------------------
## Known issues
@@ -1022,6 +1081,8 @@ can download it [here](https://www.oracle.com/java/technologies/downloads/#java1
the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the
application before running the application again.
+[Scroll back to Table of Contents](#table-of-contents)
+
--------------------------------------------------------------------------------------------------------------------
## Command summary
@@ -1040,3 +1101,5 @@ can download it [here](https://www.oracle.com/java/technologies/downloads/#java1
| **delete** | Format:
Example:
|
| **list** | Format:
`list-developers`
`list-projects`
`list-clients` |
| **help** | `help` |
+
+[Scroll back to Table of Contents](#table-of-contents)
diff --git a/docs/diagrams/AddDeveloperRoleSequenceDiagram.puml b/docs/diagrams/AddDeveloperRoleSequenceDiagram.puml
new file mode 100644
index 00000000000..861294bf0c8
--- /dev/null
+++ b/docs/diagrams/AddDeveloperRoleSequenceDiagram.puml
@@ -0,0 +1,87 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+
+ !include style.puml
+ skinparam ArrowFontStyle plain
+
+ box Logic LOGIC_COLOR_T1
+ participant ":LogicManager" as LogicManager LOGIC_COLOR
+ participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+ participant "d :AddDeveloperRoleCommandParser" as AddDeveloperRoleCommandParser LOGIC_COLOR
+ participant "d :AddDeveloperRoleCommand" as AddDeveloperRoleCommand LOGIC_COLOR
+ participant ":CommandResult" as CommandResult LOGIC_COLOR
+ end box
+
+ box Model MODEL_COLOR_T1
+ participant ":Model" as Model MODEL_COLOR
+ participant ":VersionedAddressBook" as VersionedAddressBook MODEL_COLOR
+ participant ":DeveloperRoles" as DeveloperRoles MODEL_COLOR
+ end box
+
+ [-> LogicManager : execute("add-developer-role Tester")
+ activate LogicManager
+
+ LogicManager -> AddressBookParser : parseCommand("add-developer-role Tester")
+ activate AddressBookParser
+
+ create AddDeveloperRoleCommandParser
+ AddressBookParser -> AddDeveloperRoleCommandParser
+ activate AddDeveloperRoleCommandParser
+
+ AddDeveloperRoleCommandParser --> AddressBookParser
+ deactivate AddDeveloperRoleCommandParser
+
+ AddressBookParser -> AddDeveloperRoleCommandParser : parse("Tester")
+ activate AddDeveloperRoleCommandParser
+
+ create AddDeveloperRoleCommand
+ AddDeveloperRoleCommandParser -> AddDeveloperRoleCommand
+ activate AddDeveloperRoleCommand
+
+ AddDeveloperRoleCommand --> AddDeveloperRoleCommandParser
+ deactivate AddDeveloperRoleCommand
+
+ AddDeveloperRoleCommandParser --> AddressBookParser
+ deactivate AddDeveloperRoleCommandParser
+
+ AddressBookParser --> LogicManager
+ deactivate AddressBookParser
+
+ LogicManager -> AddDeveloperRoleCommand : execute()
+ activate AddDeveloperRoleCommand
+
+ AddDeveloperRoleCommand -> DeveloperRoles : isValidRole("Tester")
+ activate DeveloperRoles
+
+ DeveloperRoles --> AddDeveloperRoleCommand : boolean true
+ deactivate DeveloperRoles
+
+ AddDeveloperRoleCommand -> DeveloperRoles : addDeveloperRole(new DeveloperRoles("Tester))
+ activate DeveloperRoles
+
+ DeveloperRoles -> DeveloperRoles : saveDeveloperRoles()
+ DeveloperRoles --> AddDeveloperRoleCommand
+
+ AddDeveloperRoleCommand -> Model : commitAddressBook(model, successMessage, TabIndex)
+ activate Model
+
+ Model -> VersionedAddressBook : commit()
+ activate VersionedAddressBook
+
+ VersionedAddressBook --> Model
+ deactivate VersionedAddressBook
+
+ Model --> AddDeveloperRoleCommand
+ deactivate Model
+
+ create CommandResult
+ AddDeveloperRoleCommand -> CommandResult
+ activate CommandResult
+
+ CommandResult --> AddDeveloperRoleCommand
+ deactivate CommandResult
+
+ AddDeveloperRoleCommand --> LogicManager : result
+ deactivate AddDeveloperRoleCommand
+
+@enduml
diff --git a/docs/diagrams/DeleteDeveloperRoleSequenceDiagram.puml b/docs/diagrams/DeleteDeveloperRoleSequenceDiagram.puml
new file mode 100644
index 00000000000..0319e46d543
--- /dev/null
+++ b/docs/diagrams/DeleteDeveloperRoleSequenceDiagram.puml
@@ -0,0 +1,87 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+
+ !include style.puml
+ skinparam ArrowFontStyle plain
+
+ box Logic LOGIC_COLOR_T1
+ participant ":LogicManager" as LogicManager LOGIC_COLOR
+ participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+ participant "d :DeleteDeveloperRoleCommandParser" as DeleteDeveloperRoleCommandParser LOGIC_COLOR
+ participant "d :DeleteDeveloperRoleCommand" as DeleteDeveloperRoleCommand LOGIC_COLOR
+ participant ":CommandResult" as CommandResult LOGIC_COLOR
+ end box
+
+ box Model MODEL_COLOR_T1
+ participant ":Model" as Model MODEL_COLOR
+ participant ":VersionedAddressBook" as VersionedAddressBook MODEL_COLOR
+ participant ":DeveloperRoles" as DeveloperRoles MODEL_COLOR
+ end box
+
+ [-> LogicManager : execute("delete-developer-role Tester")
+ activate LogicManager
+
+ LogicManager -> AddressBookParser : parseCommand("delete-developer-role Tester")
+ activate AddressBookParser
+
+ create DeleteDeveloperRoleCommandParser
+ AddressBookParser -> DeleteDeveloperRoleCommandParser
+ activate DeleteDeveloperRoleCommandParser
+
+ DeleteDeveloperRoleCommandParser --> AddressBookParser
+ deactivate DeleteDeveloperRoleCommandParser
+
+ AddressBookParser -> DeleteDeveloperRoleCommandParser : parse("Tester")
+ activate DeleteDeveloperRoleCommandParser
+
+ create DeleteDeveloperRoleCommand
+ DeleteDeveloperRoleCommandParser -> DeleteDeveloperRoleCommand
+ activate DeleteDeveloperRoleCommand
+
+ DeleteDeveloperRoleCommand --> DeleteDeveloperRoleCommandParser
+ deactivate DeleteDeveloperRoleCommand
+
+ DeleteDeveloperRoleCommandParser --> AddressBookParser
+ deactivate DeleteDeveloperRoleCommandParser
+
+ AddressBookParser --> LogicManager
+ deactivate AddressBookParser
+
+ LogicManager -> DeleteDeveloperRoleCommand : execute()
+ activate DeleteDeveloperRoleCommand
+
+ DeleteDeveloperRoleCommand -> DeveloperRoles : isRemovableRole("Tester")
+ activate DeveloperRoles
+
+ DeveloperRoles --> DeleteDeveloperRoleCommand : boolean true
+ deactivate DeveloperRoles
+
+ DeleteDeveloperRoleCommand -> DeveloperRoles : deleteDeveloperRole(new DeveloperRoles("Tester))
+ activate DeveloperRoles
+
+ DeveloperRoles -> DeveloperRoles : saveDeveloperRoles()
+ DeveloperRoles --> DeleteDeveloperRoleCommand
+
+ DeleteDeveloperRoleCommand -> Model : commitAddressBook(model, successMessage, TabIndex)
+ activate Model
+
+ Model -> VersionedAddressBook : commit()
+ activate VersionedAddressBook
+
+ VersionedAddressBook --> Model
+ deactivate VersionedAddressBook
+
+ Model --> DeleteDeveloperRoleCommand
+ deactivate Model
+
+ create CommandResult
+ DeleteDeveloperRoleCommand -> CommandResult
+ activate CommandResult
+
+ CommandResult --> DeleteDeveloperRoleCommand
+ deactivate CommandResult
+
+ DeleteDeveloperRoleCommand --> LogicManager : result
+ deactivate DeleteDeveloperRoleCommand
+
+@enduml
diff --git a/docs/diagrams/FindDeveloperSequenceDiagram.puml b/docs/diagrams/FindDeveloperSequenceDiagram.puml
new file mode 100644
index 00000000000..f5e9dcd8735
--- /dev/null
+++ b/docs/diagrams/FindDeveloperSequenceDiagram.puml
@@ -0,0 +1,70 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":FindCommandParser" as FindCommandParser LOGIC_COLOR
+participant "d:FindCommand" as FindCommand LOGIC_COLOR
+participant ":CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant ":Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("find-developer n/Alice")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("find-developer n/Alice")
+activate AddressBookParser
+
+create FindCommandParser
+AddressBookParser -> FindCommandParser
+activate FindCommandParser
+
+FindCommandParser --> AddressBookParser
+deactivate FindCommandParser
+
+AddressBookParser -> FindCommandParser : parse("Alice")
+activate FindCommandParser
+
+create FindCommand
+FindCommandParser -> FindCommand
+activate FindCommand
+
+FindCommand --> FindCommandParser : d
+deactivate FindCommand
+
+FindCommandParser --> AddressBookParser : d
+deactivate FindCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+FindCommandParser -[hidden]-> AddressBookParser
+destroy FindCommandParser
+
+AddressBookParser --> LogicManager : d
+deactivate AddressBookParser
+
+LogicManager -> FindCommand : execute()
+activate FindCommand
+
+FindCommand -> Model : FindDeveloper(1)
+activate Model
+
+Model --> FindCommand
+deactivate Model
+
+create CommandResult
+FindCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> FindCommand
+deactivate CommandResult
+
+FindCommand --> LogicManager : result
+deactivate FindCommand
+
+[<--LogicManager
+deactivate LogicManager
+@enduml
diff --git a/docs/diagrams/ListDeveloperCommand.puml b/docs/diagrams/ListDeveloperCommand.puml
new file mode 100644
index 00000000000..3c32aec9cd1
--- /dev/null
+++ b/docs/diagrams/ListDeveloperCommand.puml
@@ -0,0 +1,56 @@
+
+ @startuml
+ !include style.puml
+ skinparam ArrowFontStyle plain
+
+ box Logic LOGIC_COLOR_T1
+ participant ":LogicManager" as LogicManager LOGIC_COLOR
+ participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+ participant "d :ListDeveloperCommand" as ListDeveloperCommand LOGIC_COLOR
+ participant ":CommandResult" as CommandResult LOGIC_COLOR
+ end box
+
+ box Model MODEL_COLOR_T1
+ participant ":Model" as Model MODEL_COLOR
+ end box
+
+ [-> LogicManager : execute("list-developer")
+ activate LogicManager
+
+ LogicManager -> AddressBookParser : parseCommand("list-developer")
+ activate AddressBookParser
+
+ create ListDeveloperCommand
+ AddressBookParser -> ListDeveloperCommand
+ activate ListDeveloperCommand
+
+ ListDeveloperCommand --> AddressBookParser : d
+ deactivate ListDeveloperCommand
+
+ AddressBookParser --> LogicManager : d
+ deactivate AddressBookParser
+
+ LogicManager -> ListDeveloperCommand : execute()
+ activate ListDeveloperCommand
+
+ ListDeveloperCommand -> Model : updateFilteredDeveloperList(PREDICATE_SHOW_ALL_DEVELOPERS)
+ activate Model
+
+ Model --> ListDeveloperCommand
+ deactivate Model
+
+ create CommandResult
+ ListDeveloperCommand -> CommandResult
+ activate CommandResult
+
+ CommandResult --> ListDeveloperCommand
+ deactivate CommandResult
+
+ ListDeveloperCommand --> LogicManager : result
+ deactivate ListDeveloperCommand
+
+ [<--LogicManager
+ deactivate LogicManager
+
+ @enduml
+
diff --git a/docs/diagrams/UndoRedoActivityDiagram.puml b/docs/diagrams/UndoRedoActivityDiagram.puml
new file mode 100644
index 00000000000..3ec83d497b3
--- /dev/null
+++ b/docs/diagrams/UndoRedoActivityDiagram.puml
@@ -0,0 +1,37 @@
+@startuml
+'https://plantuml.com/activity-diagram-beta
+
+start
+:undo
+:new page;
+if (Page.onSecurityCheck) then (true)
+ :Page.onInit();
+ if (isForward?) then (no)
+ :Process controls;
+ if (continue processing?) then (no)
+ stop
+ endif
+
+ if (isPost?) then (yes)
+ :Page.onPost();
+ else (no)
+ :Page.onGet();
+ endif
+ :Page.onRender();
+ endif
+else (false)
+endif
+
+if (do redirect?) then (yes)
+ :redirect process;
+else
+ if (do forward?) then (yes)
+ :Forward request;
+ else (no)
+ :Render page template;
+ endif
+endif
+
+stop
+
+@enduml
diff --git a/docs/diagrams/UndoSequenceDiagram.puml b/docs/diagrams/UndoSequenceDiagram.puml
index 87ff3e9237e..2f8a4cd0d56 100644
--- a/docs/diagrams/UndoSequenceDiagram.puml
+++ b/docs/diagrams/UndoSequenceDiagram.puml
@@ -37,7 +37,7 @@ activate Model
Model -> VersionedAddressBook : undo()
activate VersionedAddressBook
-VersionedAddressBook -> VersionedAddressBook :resetData(ReadOnlyAddressBook)
+VersionedAddressBook -> VersionedAddressBook :changeAddressBook(model)
VersionedAddressBook --> Model :
deactivate VersionedAddressBook
diff --git a/docs/diagrams/isRemovableRole.puml b/docs/diagrams/isRemovableRole.puml
new file mode 100644
index 00000000000..042c49335fc
--- /dev/null
+++ b/docs/diagrams/isRemovableRole.puml
@@ -0,0 +1,23 @@
+@startuml
+'https://plantuml.com/activity-diagram-beta
+
+start
+:get the full developer list;
+
+if (check is any developer using this role) then (there are developers using this role)
+ :throw developer still using error;
+ stop
+ endif
+ if (check is this role one of the pre-defined roles) then (is pre-defined role)
+ :throw cannot be deleted error;
+ stop
+ endif
+ if (check is this role in the list of existing roles) then (role does not exist)
+ :throw role does not exist error;
+ stop
+ endif
+ :delete role from existing list;
+ stop
+
+
+@enduml
diff --git a/docs/images/AddDeveloperRoleSequenceDiagram.png b/docs/images/AddDeveloperRoleSequenceDiagram.png
new file mode 100644
index 00000000000..b984caf89bd
Binary files /dev/null and b/docs/images/AddDeveloperRoleSequenceDiagram.png differ
diff --git a/docs/images/DeleteDeveloperRoleSequenceDiagram.png b/docs/images/DeleteDeveloperRoleSequenceDiagram.png
new file mode 100644
index 00000000000..0b2209fc66a
Binary files /dev/null and b/docs/images/DeleteDeveloperRoleSequenceDiagram.png differ
diff --git a/docs/images/FindDeveloperSequenceDiagram.png b/docs/images/FindDeveloperSequenceDiagram.png
new file mode 100644
index 00000000000..41b2db7d865
Binary files /dev/null and b/docs/images/FindDeveloperSequenceDiagram.png differ
diff --git a/docs/images/ListDeveloperSequenceDiagram.png b/docs/images/ListDeveloperSequenceDiagram.png
new file mode 100644
index 00000000000..2fea1533c48
Binary files /dev/null and b/docs/images/ListDeveloperSequenceDiagram.png differ
diff --git a/docs/images/UndoSequenceDiagram.png b/docs/images/UndoSequenceDiagram.png
index c7a7e637266..4e23d7f95d6 100644
Binary files a/docs/images/UndoSequenceDiagram.png and b/docs/images/UndoSequenceDiagram.png differ
diff --git a/docs/images/isRemovableRole.png b/docs/images/isRemovableRole.png
new file mode 100644
index 00000000000..03640755a81
Binary files /dev/null and b/docs/images/isRemovableRole.png differ
diff --git a/docs/index.md b/docs/index.md
index 6d2c93a65bb..9e15e89b118 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -4,7 +4,7 @@ title: CodeContact
---
[![CI Status](https://github.com/AY2324S1-CS2103T-T09-2/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2324S1-CS2103T-T09-2/tp/actions)
-[![codecov](https://app.codecov.io/gh/AY2324S1-CS2103T-T09-2/branch/master/graph/badge.svg)](https://app.codecov.io/gh/AY2324S1-CS2103T-T09-2)
+[![codecov](https://app.codecov.io/gh/AY2324S1-CS2103T-T09-2/branch/master/graph/badge.svg)](https://codecov.io/gh/AY2324S1-CS2103T-T09-2/tp/tree/master)
![Ui](images/Ui.png)
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e708b1c023e..41d9927a4d4 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/pword.txt b/pword.txt
deleted file mode 100644
index 81de59c5b55..00000000000
--- a/pword.txt
+++ /dev/null
@@ -1 +0,0 @@
-730288490
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java
index dc8fc90801c..d4bbbdb85cd 100644
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ b/src/main/java/seedu/address/logic/commands/CommandResult.java
@@ -69,12 +69,13 @@ public boolean equals(Object other) {
CommandResult otherCommandResult = (CommandResult) other;
return feedbackToUser.equals(otherCommandResult.feedbackToUser)
&& showHelp == otherCommandResult.showHelp
- && exit == otherCommandResult.exit;
+ && exit == otherCommandResult.exit
+ && index == otherCommandResult.index;
}
@Override
public int hashCode() {
- return Objects.hash(feedbackToUser, showHelp, exit);
+ return Objects.hash(feedbackToUser, showHelp, exit, index);
}
@Override
@@ -83,6 +84,7 @@ public String toString() {
.add("feedbackToUser", feedbackToUser)
.add("showHelp", showHelp)
.add("exit", exit)
+ .add("index", index.toString())
.toString();
}
diff --git a/src/main/java/seedu/address/logic/commands/ImportCommand.java b/src/main/java/seedu/address/logic/commands/ImportCommand.java
deleted file mode 100644
index 7a7f2e509ad..00000000000
--- a/src/main/java/seedu/address/logic/commands/ImportCommand.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.ArrayList;
-
-import seedu.address.commons.util.ToStringBuilder;
-import seedu.address.logic.Messages;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.developer.Developer;
-
-/**
- * Imports a list of developers from a CSV file into the application.
- */
-public class ImportCommand extends Command {
- public static final String COMMAND_WORD = "import";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Imports employees from csv file.\n"
- + "Column titles should follow this format strictly:\n"
- + "Name, Contact Number, Email, Address, Date Joined, Role, Salary, Username, Password, Projects";
- public static final String MESSAGE_SUCCESS = "New developer added: %1$s";
- public static final String MESSAGE_DUPLICATE_PERSON = " already exists in the address book\n";
-
- private final ArrayList toAddList;
-
- /**
- * Creates an AddDeveloperCommand to add the specified {@code Developer}
- */
- public ImportCommand(ArrayList developerList) {
- requireNonNull(developerList);
- for (Developer i : developerList) {
- requireNonNull(i);
- }
- toAddList = developerList;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- String output = "";
- for (Developer toAdd : toAddList) {
- if (model.hasDeveloper(toAdd)) {
- output += toAdd.getName().fullName + MESSAGE_DUPLICATE_PERSON;
- }
-
- model.addDeveloper(toAdd);
- output += String.format(MESSAGE_SUCCESS, Messages.format(toAdd));
- output += "\n";
- }
- return new CommandResult(output, TabIndex.Developer);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof ImportCommand)) {
- return false;
- }
-
- ImportCommand otherImportCommand = (ImportCommand) other;
- return toAddList.equals(otherImportCommand.toAddList);
- }
-
- @Override
- public String toString() {
- return new ToStringBuilder(this)
- .add("toAddList", toAddList)
- .toString();
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/RedoCommand.java b/src/main/java/seedu/address/logic/commands/RedoCommand.java
index d512ffeae36..17efa4b90e6 100644
--- a/src/main/java/seedu/address/logic/commands/RedoCommand.java
+++ b/src/main/java/seedu/address/logic/commands/RedoCommand.java
@@ -21,7 +21,11 @@ public CommandResult execute(Model model) throws CommandException {
model.redoAddressBook(model);
String previousCommand = model.getPreviousCommandForRedo();
TabIndex index = model.getPreviousTabIndexForRedo();
+ handleRoleRedo(previousCommand);
+ return new CommandResult(MESSAGE_SUCCESS + "\n" + previousCommand, index);
+ }
+ private void handleRoleRedo(String previousCommand) {
if (previousCommand.contains("New role for client added: ")) {
ClientRoles.addClientRole(new ClientRoles(previousCommand.substring(27)));
} else if (previousCommand.contains("New role for developer added: ")) {
@@ -31,6 +35,5 @@ public CommandResult execute(Model model) throws CommandException {
} else if (previousCommand.contains("Role for developers deleted: ")) {
DeveloperRoles.deleteDeveloperRole(new DeveloperRoles(previousCommand.substring(29)));
}
- return new CommandResult(MESSAGE_SUCCESS + "\n" + previousCommand, index);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/TabIndex.java b/src/main/java/seedu/address/logic/commands/TabIndex.java
index 01b4ce9b125..444c6167e71 100644
--- a/src/main/java/seedu/address/logic/commands/TabIndex.java
+++ b/src/main/java/seedu/address/logic/commands/TabIndex.java
@@ -15,11 +15,6 @@ public enum TabIndex {
*/
Client,
- /**
- * Represents the "developers" tab, which may have a different purpose or behavior.
- */
- developers,
-
/**
* Represents the "Project" tab, which is used to display and manage projects.
*/
diff --git a/src/main/java/seedu/address/logic/commands/UndoCommand.java b/src/main/java/seedu/address/logic/commands/UndoCommand.java
index 3cfb932d7eb..faffb39a91a 100644
--- a/src/main/java/seedu/address/logic/commands/UndoCommand.java
+++ b/src/main/java/seedu/address/logic/commands/UndoCommand.java
@@ -31,6 +31,11 @@ public CommandResult execute(Model model) throws CommandException {
String previousCommand = model.getPreviousCommandForUndo();
TabIndex index = model.getPreviousTabIndex();
// check if it is any of the role commands
+ handleRoleUndo(previousCommand);
+ return new CommandResult(MESSAGE_SUCCESS + "\n" + previousCommand, index);
+ }
+
+ private void handleRoleUndo(String previousCommand) {
if (previousCommand.contains("New role for client added: ")) {
ClientRoles.deleteClientRole(new ClientRoles(previousCommand.substring(27)));
} else if (previousCommand.contains("New role for developer added: ")) {
@@ -40,6 +45,5 @@ public CommandResult execute(Model model) throws CommandException {
} else if (previousCommand.contains("Role for developers deleted: ")) {
DeveloperRoles.addDeveloperRole(new DeveloperRoles(previousCommand.substring(29)));
}
- return new CommandResult(MESSAGE_SUCCESS + "\n" + previousCommand, index);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/addroles/AddClientRoleCommand.java b/src/main/java/seedu/address/logic/commands/addroles/AddClientRoleCommand.java
index 2c69a62f41b..8ed119d0467 100644
--- a/src/main/java/seedu/address/logic/commands/addroles/AddClientRoleCommand.java
+++ b/src/main/java/seedu/address/logic/commands/addroles/AddClientRoleCommand.java
@@ -24,7 +24,7 @@ public class AddClientRoleCommand extends Command {
+ "Example: " + PREFIX_ROLE + "Developer ";
public static final String MESSAGE_SUCCESS = "New role for client added: %1$s";
- public static final String MESSAGE_DUPLICATE_DEVELOPER = "This client role already exists in the address book!";
+ public static final String MESSAGE_DUPLICATE_ROLE = "This client role already exists in the address book!";
private final String toAdd;
/**
@@ -49,7 +49,7 @@ public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
if (ClientRoles.isValidRole(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_DEVELOPER);
+ throw new CommandException(MESSAGE_DUPLICATE_ROLE);
}
String successMessage = String.format(MESSAGE_SUCCESS, Messages.format(toAdd));
diff --git a/src/main/java/seedu/address/logic/commands/addroles/AddDeveloperRoleCommand.java b/src/main/java/seedu/address/logic/commands/addroles/AddDeveloperRoleCommand.java
index d733bf1ede2..a0e6d2b1a98 100644
--- a/src/main/java/seedu/address/logic/commands/addroles/AddDeveloperRoleCommand.java
+++ b/src/main/java/seedu/address/logic/commands/addroles/AddDeveloperRoleCommand.java
@@ -25,7 +25,7 @@ public class AddDeveloperRoleCommand extends Command {
+ "Example: " + PREFIX_ROLE + "Developer ";
public static final String MESSAGE_SUCCESS = "New role for developer added: %1$s";
- public static final String MESSAGE_DUPLICATE_DEVELOPER = "This developer role already exists in the address book!";
+ public static final String MESSAGE_DUPLICATE_ROLE = "This developer role already exists in the address book!";
private final String toAdd;
/**
@@ -50,7 +50,7 @@ public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
if (DeveloperRoles.isValidRole(toAdd)) {
- throw new CommandException(MESSAGE_DUPLICATE_DEVELOPER);
+ throw new CommandException(MESSAGE_DUPLICATE_ROLE);
}
String successMessage = String.format(MESSAGE_SUCCESS, Messages.format(toAdd));
diff --git a/src/main/java/seedu/address/logic/commands/deleteroles/DeleteClientRoleCommand.java b/src/main/java/seedu/address/logic/commands/deleteroles/DeleteClientRoleCommand.java
index 30c7e221444..08bee5ea90f 100644
--- a/src/main/java/seedu/address/logic/commands/deleteroles/DeleteClientRoleCommand.java
+++ b/src/main/java/seedu/address/logic/commands/deleteroles/DeleteClientRoleCommand.java
@@ -60,7 +60,7 @@ public CommandResult execute(Model model) throws CommandException {
+ ClientRoles.printRoles());
} else if (!ClientRoles.isNotDefault()) {
throw new CommandException(MESSAGE_CANNOT_DELETE_PREXISTS);
- } else if (!ClientRoles.isNoRepeat() ) {
+ } else if (!ClientRoles.isNoRepeat()) {
throw new CommandException(MESSAGE_CANNOT_DELETE_REPEAT);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/deleteroles/DeleteDeveloperRoleCommand.java b/src/main/java/seedu/address/logic/commands/deleteroles/DeleteDeveloperRoleCommand.java
index 5fbff7e3bc1..782ff350312 100644
--- a/src/main/java/seedu/address/logic/commands/deleteroles/DeleteDeveloperRoleCommand.java
+++ b/src/main/java/seedu/address/logic/commands/deleteroles/DeleteDeveloperRoleCommand.java
@@ -60,7 +60,7 @@ public CommandResult execute(Model model) throws CommandException {
+ DeveloperRoles.printRoles());
} else if (!DeveloperRoles.isNotDefault()) {
throw new CommandException(MESSAGE_CANNOT_DELETE_PREXISTS);
- } else if (!DeveloperRoles.isNoRepeat() ) {
+ } else if (!DeveloperRoles.isNoRepeat()) {
throw new CommandException(MESSAGE_CANNOT_DELETE_REPEAT);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/edit/EditProjectCommand.java b/src/main/java/seedu/address/logic/commands/edit/EditProjectCommand.java
index 87cb9b8504d..f05dd605ba8 100644
--- a/src/main/java/seedu/address/logic/commands/edit/EditProjectCommand.java
+++ b/src/main/java/seedu/address/logic/commands/edit/EditProjectCommand.java
@@ -98,7 +98,7 @@ public CommandResult execute(Model model) throws CommandException {
}
String successMessage = String.format(MESSAGE_EDIT_PROJECT_SUCCESS, Messages.format(editedProject));
- TabIndex index = TabIndex.developers;
+ TabIndex index = TabIndex.Project;
model.setProject(projectToEdit, editedProject);
model.updateFilteredProjectList(Model.PREDICATE_SHOW_ALL_PROJECTS);
diff --git a/src/main/java/seedu/address/logic/commands/imports/ImportClientCommand.java b/src/main/java/seedu/address/logic/commands/imports/ImportClientCommand.java
index 233292ad078..8892e82eaff 100644
--- a/src/main/java/seedu/address/logic/commands/imports/ImportClientCommand.java
+++ b/src/main/java/seedu/address/logic/commands/imports/ImportClientCommand.java
@@ -5,10 +5,10 @@
import java.util.ArrayList;
import seedu.address.commons.util.ToStringBuilder;
-import seedu.address.logic.Messages;
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.CommandResult;
import seedu.address.logic.commands.TabIndex;
+import seedu.address.logic.commands.add.AddClientCommand;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.client.Client;
@@ -23,7 +23,6 @@ public class ImportClientCommand extends Command {
+ "Column titles should follow this format strictly:\n"
+ "Name, Contact Number, Email, Address, Role, Organisation, Document, Projects";
public static final String MESSAGE_SUCCESS = "New client added: %1$s";
- public static final String MESSAGE_DUPLICATE_CLIENT = " is a client that already exists in the address book\n";
private final ArrayList toAddList;
@@ -52,13 +51,8 @@ public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
String output = "";
for (Client toAdd : toAddList) {
- if (model.hasClient(toAdd)) {
- output += toAdd.getName().fullName + MESSAGE_DUPLICATE_CLIENT;
- } else {
- model.addClient(toAdd);
- output += String.format(MESSAGE_SUCCESS, Messages.format(toAdd));
- }
- output += "\n";
+ CommandResult result = new AddClientCommand(toAdd).execute(model);
+ output += result.getFeedbackToUser() + "\n";
}
return new CommandResult(output, TabIndex.Client);
}
diff --git a/src/main/java/seedu/address/logic/commands/imports/ImportDeveloperCommand.java b/src/main/java/seedu/address/logic/commands/imports/ImportDeveloperCommand.java
index d7f926f6f8a..378503e76ba 100644
--- a/src/main/java/seedu/address/logic/commands/imports/ImportDeveloperCommand.java
+++ b/src/main/java/seedu/address/logic/commands/imports/ImportDeveloperCommand.java
@@ -5,10 +5,10 @@
import java.util.ArrayList;
import seedu.address.commons.util.ToStringBuilder;
-import seedu.address.logic.Messages;
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.CommandResult;
import seedu.address.logic.commands.TabIndex;
+import seedu.address.logic.commands.add.AddDeveloperCommand;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.developer.Developer;
@@ -22,8 +22,6 @@ public class ImportDeveloperCommand extends Command {
+ "Column titles should follow this format strictly:\n"
+ "Name, Contact Number, Email, Address, Date Joined, Role, Salary, GithubId, Rating, Projects";
public static final String MESSAGE_SUCCESS = "New developer added: %1$s";
- public static final String MESSAGE_DUPLICATE_DEVELOPER =
- " is a developer that already exists in the address book\n";
private final ArrayList toAddList;
@@ -52,13 +50,8 @@ public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
String output = "";
for (Developer toAdd : toAddList) {
- if (model.hasDeveloper(toAdd)) {
- output += toAdd.getName().fullName + MESSAGE_DUPLICATE_DEVELOPER;
- } else {
- model.addDeveloper(toAdd);
- output += String.format(MESSAGE_SUCCESS, Messages.format(toAdd));
- }
- output += "\n";
+ CommandResult result = new AddDeveloperCommand(toAdd).execute(model);
+ output += result.getFeedbackToUser() + "\n";
}
return new CommandResult(output, TabIndex.Developer);
}
diff --git a/src/main/java/seedu/address/logic/commands/list/ListProjectCommand.java b/src/main/java/seedu/address/logic/commands/list/ListProjectCommand.java
index a6d43b9294b..8b8346371b4 100644
--- a/src/main/java/seedu/address/logic/commands/list/ListProjectCommand.java
+++ b/src/main/java/seedu/address/logic/commands/list/ListProjectCommand.java
@@ -24,6 +24,6 @@ public CommandResult execute(Model model) {
requireNonNull(model);
model.updateFilteredProjectList(PREDICATE_SHOW_ALL_PROJECTS);
model.updateFilteredProjectDeadlineList(unused -> true);
- return new CommandResult(MESSAGE_SUCCESS, TabIndex.developers);
+ return new CommandResult(MESSAGE_SUCCESS, TabIndex.Project);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/mark/UnmarkDeadlineCommand.java b/src/main/java/seedu/address/logic/commands/mark/UnmarkDeadlineCommand.java
index 47b63569251..c384e689625 100644
--- a/src/main/java/seedu/address/logic/commands/mark/UnmarkDeadlineCommand.java
+++ b/src/main/java/seedu/address/logic/commands/mark/UnmarkDeadlineCommand.java
@@ -105,7 +105,7 @@ public boolean equals(Object other) {
}
// instanceof handles nulls
- if (!(other instanceof MarkDeadlineCommand)) {
+ if (!(other instanceof UnmarkDeadlineCommand)) {
return false;
}
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
index 7e49a25ab1f..a7561a06a8c 100644
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
@@ -15,7 +15,6 @@
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.ExitCommand;
import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ImportCommand;
import seedu.address.logic.commands.LockCommand;
import seedu.address.logic.commands.RedoCommand;
import seedu.address.logic.commands.UndoCommand;
@@ -132,9 +131,6 @@ public Command parseCommand(String userInput) throws ParseException {
case FindDeadlineCommand.COMMAND_WORD:
return new FindDeadlineCommandParser().parse(arguments);
- case ImportCommand.COMMAND_WORD:
- return new ImportDeveloperCommandParser().parse(arguments);
-
case EditDeveloperCommand.COMMAND_WORD:
return new EditDeveloperCommandParser().parse(arguments);
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
index 5eb665bea6d..723ef907d9b 100644
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java
@@ -26,6 +26,7 @@
import seedu.address.model.person.Phone;
import seedu.address.model.project.Deadline;
import seedu.address.model.project.Description;
+import seedu.address.model.project.Priority;
import seedu.address.model.project.Project;
/**
@@ -188,6 +189,21 @@ public static Date parseDateJoined(String dateJoined) throws ParseException {
return new Date(trimmedDateJoined, false);
}
+ /**
+ * Parses a {@code String dateDeadline} into a {@code DateDeadline}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code DateDeadline} is invalid.
+ */
+ public static Date parseDateDeadline(String dateJoined) throws ParseException {
+ requireNonNull(dateJoined);
+ String trimmedDateJoined = dateJoined.trim();
+ if (!Date.isValidDate(trimmedDateJoined, true)) {
+ throw new ParseException(Date.MESSAGE_CONSTRAINTS);
+ }
+ return new Date(trimmedDateJoined, true);
+ }
+
/**
* Parses a {@code String role} into a {@code Role}.
@@ -314,4 +330,18 @@ public static String parsePassword(String pw) throws ParseException {
}
return trimmedPw;
}
+
+ /**
+ * Parses a priority string and returns the corresponding Priority enum.
+ *
+ * @param priorityKeywords The priority string to be parsed.
+ * @return The corresponding Priority enum.
+ * @throws ParseException If the input string is not a valid priority.
+ */
+ public static Priority parsePriority(String priorityKeywords) throws ParseException {
+ if (!(priorityKeywords.equals("HIGH") || priorityKeywords.equals("MEDIUM") || priorityKeywords.equals("LOW"))) {
+ throw new ParseException("Priority has to be HIGH, MEDIUM or LOW");
+ }
+ return Priority.valueOf(priorityKeywords);
+ }
}
diff --git a/src/main/java/seedu/address/logic/parser/find/FindDeadlineCommandParser.java b/src/main/java/seedu/address/logic/parser/find/FindDeadlineCommandParser.java
index 7eb5abb39fb..c54ff932e0a 100644
--- a/src/main/java/seedu/address/logic/parser/find/FindDeadlineCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/find/FindDeadlineCommandParser.java
@@ -11,6 +11,7 @@
import seedu.address.logic.parser.ArgumentMultimap;
import seedu.address.logic.parser.ArgumentTokenizer;
import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
import seedu.address.logic.parser.Prefix;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.commons.Date;
@@ -61,12 +62,12 @@ public FindDeadlineCommand parse(String args) throws ParseException {
* @param argMultimap Argument multimap containing user input arguments.
* @return A predicate for filtering deadlines.
*/
- private Predicate buildPredicate(ArgumentMultimap argMultimap) {
+ private Predicate buildPredicate(ArgumentMultimap argMultimap) throws ParseException {
Predicate finalPredicate = deadline -> true;
if (argMultimap.getValue(PREFIX_DATEJOINED).isPresent()) {
String dateKeywords = argMultimap.getValue(PREFIX_DATEJOINED).get();
- Date input = new Date(dateKeywords, true);
+ Date input = ParserUtil.parseDateDeadline(dateKeywords);
finalPredicate =
finalPredicate.and(d -> !d.getDate().value.after(input.value));
// Replace with your DateJoinedPredicate
@@ -74,7 +75,7 @@ private Predicate buildPredicate(ArgumentMultimap argMultimap) {
if (argMultimap.getValue(PREFIX_PRIORITY).isPresent()) {
String priorityKeywords = argMultimap.getValue(PREFIX_PRIORITY).get();
- Priority input = Priority.valueOf(priorityKeywords);
+ Priority input = ParserUtil.parsePriority(priorityKeywords);
finalPredicate = finalPredicate.and(d -> d.getPriority().equals(input));
// Replace with your PriorityPredicate
}
diff --git a/src/main/java/seedu/address/logic/parser/imports/ImportDeveloperCommandParser.java b/src/main/java/seedu/address/logic/parser/imports/ImportDeveloperCommandParser.java
index 11a5210e90a..6704b89ffdc 100644
--- a/src/main/java/seedu/address/logic/parser/imports/ImportDeveloperCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/imports/ImportDeveloperCommandParser.java
@@ -6,7 +6,6 @@
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
-import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;
@@ -43,9 +42,6 @@ public class ImportDeveloperCommandParser implements Parser {
private ProjectListPanel projectListPanel;
private ResultDisplay resultDisplay;
private HelpWindow helpWindow;
+ private int resultTabIndex;
@FXML
private StackPane commandBoxPlaceholder;
@@ -132,7 +133,7 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) {
* Fills up all the placeholders of this window.
*/
void fillInnerParts() {
- tabPane = new TabPane();
+ //tabPane = new TabPane();
// Create tabs
/*developerTab = new Tab("Developer");
clientTab = new Tab("Client");
@@ -155,7 +156,21 @@ void fillInnerParts() {
// Add tabs to the TabPane
tabPane.getTabs().addAll(developerTab, clientTab, projectTab);
- //tabPane.getSelectionModel().select(1);
+ tabPane.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> {
+ if (newValue.intValue() != resultTabIndex) {
+ try {
+ if (newValue.intValue() == 0) {
+ executeCommand("list-developer");
+ } else if (newValue.intValue() == 1) {
+ executeCommand("list-client");
+ } else if (newValue.intValue() == 2) {
+ executeCommand("list-project");
+ }
+ } catch (CommandException | ParseException e) {
+ e.printStackTrace();
+ }
+ }
+ });
resultDisplay = new ResultDisplay();
resultDisplay.setFeedbackToUser("Welcome to CodeContact!\nUnlock to continue.");
@@ -230,7 +245,9 @@ private CommandResult executeCommand(String commandText) throws CommandException
CommandResult commandResult = logic.execute(commandText);
logger.info("Result: " + commandResult.getFeedbackToUser());
resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());
- tabPane.getSelectionModel().select(commandResult.getIndex());
+ resultTabIndex = commandResult.getIndex();
+ System.out.println("resultTabIndex: " + resultTabIndex);
+ tabPane.getSelectionModel().select(resultTabIndex);
if (commandResult.isShowHelp()) {
handleHelp();
}
diff --git a/src/main/java/seedu/address/ui/ProjectCard.java b/src/main/java/seedu/address/ui/ProjectCard.java
index e8e40d4a262..d71a7d54a58 100644
--- a/src/main/java/seedu/address/ui/ProjectCard.java
+++ b/src/main/java/seedu/address/ui/ProjectCard.java
@@ -76,7 +76,7 @@ public ProjectCard(Project project, int displayedIndex) {
new PropertyValueFactory<>("date"));
TableColumn descriptionCol = new TableColumn("Description");
- descriptionCol.setMinWidth(260);
+ descriptionCol.setMinWidth(100);
descriptionCol.setCellValueFactory(
new PropertyValueFactory<>("description"));
diff --git a/src/test/java/seedu/address/logic/commands/ChangePasswordCommandTest.java b/src/test/java/seedu/address/logic/commands/ChangePasswordCommandTest.java
new file mode 100644
index 00000000000..fccc3c7fc84
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/ChangePasswordCommandTest.java
@@ -0,0 +1,49 @@
+package seedu.address.logic.commands;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.model.Password.MESSAGE_CONSTRAINTS;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+public class ChangePasswordCommandTest {
+
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager();
+ expectedModel = new ModelManager();
+ }
+
+ @Test
+ public void execute_changePassword_success() {
+ //Works only for default password
+ assertCommandSuccess(new ChangePasswordCommand("Password123!", "Password1243!"), model,
+ "Password changed successfully.", expectedModel);
+ //Change back to default password
+ assertCommandSuccess(new ChangePasswordCommand("Password1243!", "Password123!"), model,
+ "Password changed successfully.", expectedModel);
+ }
+
+ @Test
+ public void execute_changePassword_same() {
+ assertCommandSuccess(new ChangePasswordCommand("Password123!", "Password123!"), model,
+ "New password cannot be the same as the current password.",
+ expectedModel);
+ }
+ @Test
+ public void execute_changePassword_wrong() {
+ assertCommandSuccess(new ChangePasswordCommand("Password13!", "Password123!"), model,
+ "Current password is incorrect.\n" + MESSAGE_CONSTRAINTS,
+ expectedModel);
+ }
+ @Test
+ public void execute_changePassword_invalid() {
+ assertCommandSuccess(new ChangePasswordCommand("Password123!", "Password123"), model,
+ "New password doesn't meet the constraints.\n" + MESSAGE_CONSTRAINTS,
+ expectedModel);
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/seedu/address/logic/commands/CommandResultTest.java
index 0fe345a0c83..40e3d3b82f6 100644
--- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java
+++ b/src/test/java/seedu/address/logic/commands/CommandResultTest.java
@@ -57,7 +57,7 @@ public void toStringMethod() {
CommandResult commandResult = new CommandResult("feedback", TabIndex.Developer);
String expected = CommandResult.class.getCanonicalName() + "{feedbackToUser="
+ commandResult.getFeedbackToUser() + ", showHelp=" + commandResult.isShowHelp()
- + ", exit=" + commandResult.isExit() + "}";
+ + ", exit=" + commandResult.isExit() + ", index=Developer}";
assertEquals(expected, commandResult.toString());
}
}
diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
index bffb42ed4b5..b97537af52f 100644
--- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
+++ b/src/test/java/seedu/address/logic/commands/CommandTestUtil.java
@@ -24,6 +24,7 @@
import seedu.address.commons.core.index.Index;
import seedu.address.logic.commands.edit.EditClientCommand;
import seedu.address.logic.commands.edit.EditDeveloperCommand;
+import seedu.address.logic.commands.edit.EditProjectCommand;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.AddressBook;
import seedu.address.model.Model;
@@ -31,8 +32,11 @@
import seedu.address.model.client.NameClientContainsKeywordsPredicate;
import seedu.address.model.developer.Developer;
import seedu.address.model.developer.NameDeveloperContainsKeywordsPredicate;
+import seedu.address.model.project.Project;
+import seedu.address.model.project.ProjectNameContainsKeywordsPredicate;
import seedu.address.testutil.EditClientDescriptorBuilder;
import seedu.address.testutil.EditDeveloperDescriptorBuilder;
+import seedu.address.testutil.EditProjectDescriptorBuilder;
/**
* Contains helper methods for testing commands.
@@ -71,6 +75,7 @@ public class CommandTestUtil {
public static final String VALID_PROJECT_2_AMY = "ProjectB";
public static final String VALID_PROJECT_1_BOB = "ProjectC";
public static final String VALID_PROJECT_2_BOB = "ProjectD";
+ public static final String VALID_PROJECT_3_BOB = "Project C";
public static final String VALID_PROJECT_1_CALEB = "ProjectC";
public static final String VALID_PROJECT_2_CALEB = "ProjectD";
public static final String VALID_PROJECT_1_DAN = "ProjectA";
@@ -129,6 +134,26 @@ public class CommandTestUtil {
public static final String DOCUMENT_DESC_CALEB = " " + PREFIX_DOCUMENT + VALID_DOCUMENT_CALEB;
public static final String DOCUMENT_DESC_DAN = " " + PREFIX_DOCUMENT + VALID_DOCUMENT_DAN;
+ public static final String VALID_PROJECT_DESCRIPTION_APPLEAPP = "Developing the AppleApp";
+ public static final String VALID_PROJECT_DESCRIPTION_GOOGLEAPP = "Working on the GoogleApp";
+ public static final String VALID_PROJECT_DESCRIPTION_ANDROIDAPP = "AndroidApp development";
+ public static final String VALID_FULL_PROJECT_DEADLINE_1 = "31-12-2019,Develop front end interface,HIGH,0";
+ public static final String VALID_FULL_PROJECT_DEADLINE_2 = "01-02-2020,Develop back end,HIGH,0";
+ public static final String INVALID_FULL_PROJECT_DEADLINE_1 = "30-02-2020,Develop back end,HIGH,0";
+ public static final String VALID_PROJECT_DEADLINE_APPLEAPP = "2023-12-31";
+ public static final String VALID_PROJECT_DEADLINE_GOOGLEAPP = "2023-11-30";
+ public static final String VALID_PROJECT_DEADLINE_ANDROIDAPP = "2023-10-31";
+
+ public static final String VALID_PROJECT_PRIORITY_APPLEAPP = "High";
+ public static final String VALID_PROJECT_PRIORITY_GOOGLEAPP = "Medium";
+ public static final String VALID_PROJECT_PRIORITY_ANDROIDAPP = "Low";
+
+ public static final String VALID_PROJECT_NAME_APPLEAPP = "AppleApp";
+ public static final String VALID_PROJECT_NAME_GOOGLEAPP = "GoogleApp";
+ public static final String VALID_PROJECT_NAME_ANDROIDAPP = "AndroidApp";
+
+ public static final String VALID_PROJECT_TAG_UI = "UI";
+ public static final String VALID_PROJECT_TAG_BACKEND = "Backend";
public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names
public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones
@@ -141,6 +166,8 @@ public class CommandTestUtil {
public static final String INVALID_RATING_DESC = "abc" + PREFIX_RATING; //
public static final String INVALID_PROJECT_DESC = " " + PREFIX_PROJECT; //
+
+
public static final String PREAMBLE_WHITESPACE = "\t \r \n";
public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble";
@@ -148,6 +175,8 @@ public class CommandTestUtil {
public static final EditDeveloperCommand.EditDeveloperDescriptor DESC_BOB;
public static final EditClientCommand.EditClientDescriptor DESC_CALEB;
public static final EditClientCommand.EditClientDescriptor DESC_DAN;
+ public static final EditProjectCommand.EditProjectDescriptor DESC_PROJECT1;
+ public static final EditProjectCommand.EditProjectDescriptor DESC_PROJECT2;
static {
@@ -167,6 +196,10 @@ public class CommandTestUtil {
.withAddress(VALID_ADDRESS_DAN).withEmail(VALID_EMAIL_DAN).withProjects(VALID_PROJECT_1_DAN)
.withDocument(VALID_DOCUMENT_DAN).build();
+ DESC_PROJECT1 = new EditProjectDescriptorBuilder().withDescription(VALID_PROJECT_DESCRIPTION_ANDROIDAPP)
+ .withDeadlines(VALID_FULL_PROJECT_DEADLINE_1).build();
+ DESC_PROJECT2 = new EditProjectDescriptorBuilder().withDescription(VALID_PROJECT_DESCRIPTION_APPLEAPP)
+ .withDeadlines(VALID_FULL_PROJECT_DEADLINE_2).build();
}
/**
@@ -195,6 +228,39 @@ public static void assertCommandSuccess(Command command, Model actualModel, Stri
false, TabIndex.Developer);
assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
}
+ /**
+ * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
+ * that takes a string {@code expectedMessage}.
+ */
+ public static void assertProjectCommandSuccess(Command command, Model actualModel, String expectedMessage,
+ Model expectedModel) {
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage, false,
+ false, TabIndex.Project);
+ assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
+ }
+
+ /**
+ * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
+ * that takes a string {@code expectedMessage}.
+ */
+ public static void assertClientCommandSuccess(Command command, Model actualModel, String expectedMessage,
+ Model expectedModel) {
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage, false,
+ false, TabIndex.Client);
+ assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
+ }
+
+ /**
+ * Convenience wrapper to {@link #assertCommandSuccess(Command, Model, CommandResult, Model)}
+ * that takes a string {@code expectedMessage}.
+ */
+ public static void assertDeveloperCommandSuccess(Command command, Model actualModel, String expectedMessage,
+ Model expectedModel) {
+ CommandResult expectedCommandResult = new CommandResult(expectedMessage, false,
+ false, TabIndex.Developer);
+ assertCommandSuccess(command, actualModel, expectedCommandResult, expectedModel);
+ }
+
/**
* Executes the given {@code command}, confirms that
@@ -242,4 +308,17 @@ public static void showClientAtIndex(Model model, Index targetIndex) {
assertEquals(1, model.getFilteredClientList().size());
}
+ /**
+ * Updates {@code model}'s filtered list to show only the client at the given {@code targetIndex} in the
+ * {@code model}'s address book.
+ */
+ public static void showProjectAtIndex(Model model, Index targetIndex) {
+ assertTrue(targetIndex.getZeroBased() < model.getFilteredProjectList().size());
+
+ Project project = model.getFilteredProjectList().get(targetIndex.getZeroBased());
+ final String[] splitName = project.getName().split("\\s+");
+ model.updateFilteredProjectList(new ProjectNameContainsKeywordsPredicate(Arrays.asList(splitName[0])));
+ assertEquals(4, model.getFilteredProjectList().size());
+ }
+
}
diff --git a/src/test/java/seedu/address/logic/commands/LockCommandTest.java b/src/test/java/seedu/address/logic/commands/LockCommandTest.java
new file mode 100644
index 00000000000..116661a5541
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/LockCommandTest.java
@@ -0,0 +1,25 @@
+package seedu.address.logic.commands;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+
+public class LockCommandTest {
+
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager();
+ expectedModel = new ModelManager();
+ }
+
+ @Test
+ public void execute_lock_success() {
+ assertCommandSuccess(new LockCommand(), model, LockCommand.MESSAGE_SUCCESS, model);
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/add/ModelStub.java b/src/test/java/seedu/address/logic/commands/ModelStub.java
similarity index 98%
rename from src/test/java/seedu/address/logic/commands/add/ModelStub.java
rename to src/test/java/seedu/address/logic/commands/ModelStub.java
index 7479dd9a921..c01c9f6d9c1 100644
--- a/src/test/java/seedu/address/logic/commands/add/ModelStub.java
+++ b/src/test/java/seedu/address/logic/commands/ModelStub.java
@@ -1,11 +1,10 @@
-package seedu.address.logic.commands.add;
+package seedu.address.logic.commands;
import java.nio.file.Path;
import java.util.function.Predicate;
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
-import seedu.address.logic.commands.TabIndex;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
diff --git a/src/test/java/seedu/address/logic/commands/RedoCommandTest.java b/src/test/java/seedu/address/logic/commands/RedoCommandTest.java
new file mode 100644
index 00000000000..4b62b132fc6
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/RedoCommandTest.java
@@ -0,0 +1,103 @@
+package seedu.address.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.address.testutil.TypicalClients.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.client.ClientRoles;
+import seedu.address.model.developer.DeveloperRoles;
+import seedu.address.testutil.ClientBuilder;
+
+public class RedoCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model modelAfterChange = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private RedoCommand redoCommand = new RedoCommand();
+ private UndoCommand undoCommand = new UndoCommand();
+
+ @Test
+ public void execute_validRedo_success() throws CommandException {
+ ClientBuilder clientBuilder = new ClientBuilder();
+ model.addClient(clientBuilder.build());
+ model.commitAddressBook(model, "Add Benson", TabIndex.Client);
+ model.undoAddressBook(model);
+
+ modelAfterChange = model;
+
+ redoCommand.execute(model);
+
+ assertEquals(model, modelAfterChange); // Ensure that the redo was successful
+ }
+
+ @Test
+ public void execute_noRedoAvailable_throwsCommandException() {
+ assertThrows(CommandException.class, () -> redoCommand.execute(model));
+ }
+
+ @Test
+ public void execute_redoRoleCommand_success() throws CommandException {
+ // Undo a command that added a new role for a client
+ ClientRoles.addClientRole(new ClientRoles("NewRole"));
+ model.commitAddressBook(model, "New role for client added: NewRole", TabIndex.Client);
+ undoCommand.execute(model);
+
+ // Redo the role addition
+ redoCommand.execute(model);
+
+ assertTrue(ClientRoles.isValidRole("NewRole"));
+ ClientRoles.deleteClientRole(new ClientRoles("NewRole"));
+ }
+
+ @Test
+ public void execute_redoDeveloperRoleCommand_success() throws CommandException {
+ // Undo a command that added a new role for a developer
+ DeveloperRoles.addDeveloperRole(new DeveloperRoles("NewRole"));
+ model.commitAddressBook(model, "New role for developer added: NewRole", TabIndex.Developer);
+ undoCommand.execute(model);
+
+ // Redo the role addition
+ redoCommand.execute(model);
+ assertTrue(DeveloperRoles.isValidRole("NewRole"));
+ DeveloperRoles.deleteDeveloperRole(new DeveloperRoles("NewRole"));
+ }
+
+ @Test
+ public void execute_redoDeleteClientRoleCommand_success() throws CommandException {
+ ClientRoles.addClientRole(new ClientRoles("RoleToDelete"));
+ model.commitAddressBook(model, "New role for client added: RoleToDelete", TabIndex.Client);
+
+ // Undo a command that deleted a role for a client
+ ClientRoles.deleteClientRole(new ClientRoles("RoleToDelete"));
+ model.commitAddressBook(model, "Role for clients deleted: RoleToDelete", TabIndex.Client);
+ undoCommand.execute(model);
+
+ // Redo the role deletion
+ redoCommand.execute(model);
+
+ assertFalse(ClientRoles.isValidRole("RoleToDelete"));
+ }
+
+ @Test
+ public void execute_redoDeleteDeveloperRoleCommand_success() throws CommandException {
+ DeveloperRoles.addDeveloperRole(new DeveloperRoles("RoleToDelete"));
+ model.commitAddressBook(model, "New role for developer added: NewRole", TabIndex.Developer);
+
+ // Undo a command that deleted a role for a developer
+ DeveloperRoles.deleteDeveloperRole(new DeveloperRoles("RoleToDelete"));
+ model.commitAddressBook(model, "Role for developers deleted: RoleToDelete", TabIndex.Developer);
+ undoCommand.execute(model);
+
+ // Redo the role deletion
+ redoCommand.execute(model);
+
+ assertFalse(DeveloperRoles.isValidRole("RoleToDelete"));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/UndoCommandTest.java b/src/test/java/seedu/address/logic/commands/UndoCommandTest.java
new file mode 100644
index 00000000000..6fa32d885b2
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/UndoCommandTest.java
@@ -0,0 +1,121 @@
+package seedu.address.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.address.testutil.TypicalClients.BOB;
+import static seedu.address.testutil.TypicalClients.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.client.ClientRoles;
+import seedu.address.model.developer.DeveloperRoles;
+import seedu.address.testutil.ClientBuilder;
+import seedu.address.testutil.DeveloperBuilder;
+
+public class UndoCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model modelAfterChange = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private UndoCommand undoCommand = new UndoCommand();
+
+ @Test
+ public void execute_validUndo_success() throws CommandException {
+ model.addClient(BOB);
+ model.commitAddressBook(model, "Add Alice", TabIndex.Client);
+ undoCommand.execute(model);
+ assertEquals(model, modelAfterChange);
+ }
+
+ @Test
+ public void execute_noUndoAvailable_throwsCommandException() {
+ assertThrows(CommandException.class, () -> undoCommand.execute(model));
+ }
+
+ @Test
+ public void execute_undoNonRoleCommand_success() throws CommandException {
+ // Add a new role for a client
+ ClientBuilder clientBuilder = new ClientBuilder();
+ model.addClient(clientBuilder.build());
+ model.commitAddressBook(model, "New client added", TabIndex.Client);
+
+ // Undo the role addition
+ undoCommand.execute(model);
+
+ assertFalse(model.getFilteredClientList().contains(clientBuilder.build()));
+ }
+
+ @Test
+ public void execute_undoClientRoleCommand_success() throws CommandException {
+ // Add a new role for a client
+ ClientRoles.addClientRole(new ClientRoles("NewRole"));
+ model.commitAddressBook(model, "New role for client added: NewRole", TabIndex.Client);
+
+ // Undo the role addition
+ undoCommand.execute(model);
+
+ assertFalse(ClientRoles.isValidRole("NewRole"));
+ }
+
+ @Test
+ public void execute_undoNonDeveloperRoleCommand_success() throws CommandException {
+ // Add a new role for a client
+ DeveloperBuilder developerBuilder = new DeveloperBuilder();
+ model.addDeveloper(developerBuilder.build());
+ model.commitAddressBook(model, "New Developer Added", TabIndex.Developer);
+
+ // Undo the role addition
+ undoCommand.execute(model);
+
+ assertFalse(model.getFilteredClientList().contains(developerBuilder.build()));
+ }
+
+ @Test
+ public void execute_undoDeveloperRoleCommand_success() throws CommandException {
+ // Add a new role for a client
+ DeveloperRoles.addDeveloperRole(new DeveloperRoles("NewRole"));
+ model.commitAddressBook(model, "New role for developer added: NewRole", TabIndex.Developer);
+
+ // Undo the role addition
+ undoCommand.execute(model);
+
+ assertFalse(DeveloperRoles.isValidRole("NewRole"));
+ }
+
+ @Test
+ public void execute_undoDeleteClientRoleCommand_success() throws CommandException {
+ ClientRoles.addClientRole(new ClientRoles("NewRole"));
+ model.commitAddressBook(model, "New role for client added: NewRole", TabIndex.Client);
+
+ // Delete a role for a client
+ ClientRoles.deleteClientRole(new ClientRoles("NewRole"));
+ model.commitAddressBook(model, "Role for clients deleted: NewRole", TabIndex.Client);
+
+ // Undo the role deletion
+ undoCommand.execute(model);
+
+ assertTrue(ClientRoles.isValidRole("NewRole"));
+ ClientRoles.deleteClientRole(new ClientRoles("NewRole"));
+ }
+
+ @Test
+ public void execute_undoDeleteDeveloperRoleCommand_success() throws CommandException {
+ DeveloperRoles.addDeveloperRole(new DeveloperRoles("RoleToDelete"));
+ model.commitAddressBook(model, "New role for client added: NewRole", TabIndex.Developer);
+
+ // Delete a role for a developer
+ DeveloperRoles.deleteDeveloperRole(new DeveloperRoles("RoleToDelete"));
+ model.commitAddressBook(model, "Role for developers deleted: RoleToDelete", TabIndex.Developer);
+
+ // Undo the role deletion
+ undoCommand.execute(model);
+
+ assertTrue(DeveloperRoles.isValidRole("RoleToDelete"));
+ DeveloperRoles.deleteDeveloperRole(new DeveloperRoles("RoleToDelete"));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/UnlockCommandTest.java b/src/test/java/seedu/address/logic/commands/UnlockCommandTest.java
new file mode 100644
index 00000000000..6d85562cb27
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/UnlockCommandTest.java
@@ -0,0 +1,33 @@
+package seedu.address.logic.commands;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+public class UnlockCommandTest {
+
+ private Model model;
+ private Model expectedModel;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager();
+ expectedModel = new ModelManager();
+ }
+
+ @Test
+ public void execute_unlock_success() {
+ //Works only for default password
+ assertCommandSuccess(new UnlockCommand("Password123!"), model, UnlockCommand.MESSAGE_SUCCESS,
+ expectedModel);
+ }
+
+ @Test
+ public void execute_unlock_failure() {
+ assertCommandSuccess(new UnlockCommand("Password123"), model, UnlockCommand.MESSAGE_FAILURE,
+ expectedModel);
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/add/AddClientCommandTest.java b/src/test/java/seedu/address/logic/commands/add/AddClientCommandTest.java
index d8a84e37c62..63bf509ecbf 100644
--- a/src/test/java/seedu/address/logic/commands/add/AddClientCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/add/AddClientCommandTest.java
@@ -13,6 +13,7 @@
import seedu.address.logic.Messages;
import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.ModelStub;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
diff --git a/src/test/java/seedu/address/logic/commands/add/AddDeveloperCommandTest.java b/src/test/java/seedu/address/logic/commands/add/AddDeveloperCommandTest.java
index 84a7ffb0129..fafba5e24ea 100644
--- a/src/test/java/seedu/address/logic/commands/add/AddDeveloperCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/add/AddDeveloperCommandTest.java
@@ -13,6 +13,7 @@
import seedu.address.logic.Messages;
import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.ModelStub;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.AddressBook;
import seedu.address.model.ReadOnlyAddressBook;
diff --git a/src/test/java/seedu/address/logic/commands/addroles/AddClientRoleCommandTest.java b/src/test/java/seedu/address/logic/commands/addroles/AddClientRoleCommandTest.java
new file mode 100644
index 00000000000..30d5e67ff58
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/addroles/AddClientRoleCommandTest.java
@@ -0,0 +1,77 @@
+package seedu.address.logic.commands.addroles;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.testutil.TypicalClients.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.deleteroles.DeleteClientRoleCommand;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.testutil.Assert;
+
+public class AddClientRoleCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void constructor_nullRole_throwsNullPointerException() {
+ Assert.assertThrows(NullPointerException.class, () -> new AddClientRoleCommand(null));
+ }
+
+ @Test
+ public void execute_roleAcceptedByModel_addSuccessful() throws CommandException {
+ String validRole1 = "Tester";
+ AddClientRoleCommand addClientRoleCommand = new AddClientRoleCommand(validRole1);
+ String expectedMessage = String.format(AddClientRoleCommand.MESSAGE_SUCCESS, validRole1);
+
+ assertEquals(addClientRoleCommand.execute(model).getFeedbackToUser(), expectedMessage);
+
+ DeleteClientRoleCommand deleteClientRoleCommand = new DeleteClientRoleCommand(validRole1);
+ deleteClientRoleCommand.execute(model);
+ }
+
+ @Test
+ public void execute_duplicateRole_throwsCommandException() {
+ String duplicateRole = "Developer";
+ AddClientRoleCommand addClientRoleCommand = new AddClientRoleCommand(duplicateRole);
+
+ assertCommandFailure(addClientRoleCommand, model, AddClientRoleCommand.MESSAGE_DUPLICATE_ROLE);
+ }
+
+ @Test
+ public void equals() {
+ String firstRole = "Tester";
+ String secondRole = "Developer";
+ AddClientRoleCommand addFirstCommand = new AddClientRoleCommand(firstRole);
+ AddClientRoleCommand addSecondCommand = new AddClientRoleCommand(secondRole);
+
+ // same object -> returns true
+ assertTrue(addFirstCommand.equals(addFirstCommand));
+
+ // same values -> returns False because cannot add twice
+ AddClientRoleCommand addFirstCommandCopy = new AddClientRoleCommand(firstRole);
+ assertFalse(addFirstCommand.equals(addFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(addFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(addFirstCommand.equals(null));
+
+ // different developer role -> returns false
+ assertFalse(addFirstCommand.equals(addSecondCommand));
+ }
+
+ @Test
+ public void toStringTest() {
+ String roleName = "Tester";
+ AddClientRoleCommand addClientRoleCommand = new AddClientRoleCommand(roleName);
+ assertEquals(addClientRoleCommand.toString(), new AddClientRoleCommand(roleName).toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/addroles/AddDeveloperRoleCommandTest.java b/src/test/java/seedu/address/logic/commands/addroles/AddDeveloperRoleCommandTest.java
new file mode 100644
index 00000000000..655ea04bbdc
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/addroles/AddDeveloperRoleCommandTest.java
@@ -0,0 +1,79 @@
+package seedu.address.logic.commands.addroles;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalDevelopers.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.deleteroles.DeleteDeveloperRoleCommand;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.testutil.Assert;
+
+public class AddDeveloperRoleCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private final Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void constructor_nullRole_throwsNullPointerException() {
+ Assert.assertThrows(NullPointerException.class, () -> new AddDeveloperRoleCommand(null));
+ }
+
+ @Test
+ public void execute_roleAcceptedByModel_addSuccessful() throws CommandException {
+ String validRole1 = "Tester";
+ AddDeveloperRoleCommand addDeveloperRoleCommand = new AddDeveloperRoleCommand(validRole1);
+ String expectedMessage = String.format(AddDeveloperRoleCommand.MESSAGE_SUCCESS, validRole1);
+
+ assertCommandSuccess(addDeveloperRoleCommand, model, expectedMessage, expectedModel);
+
+ DeleteDeveloperRoleCommand deleteDeveloperRoleCommand = new DeleteDeveloperRoleCommand(validRole1);
+ deleteDeveloperRoleCommand.execute(model);
+ }
+
+ @Test
+ public void execute_duplicateRole_throwsCommandException() {
+ String duplicateRole = "Developer";
+ AddDeveloperRoleCommand addDeveloperRoleCommand = new AddDeveloperRoleCommand(duplicateRole);
+
+ assertCommandFailure(addDeveloperRoleCommand, model, AddDeveloperRoleCommand.MESSAGE_DUPLICATE_ROLE);
+ }
+
+ @Test
+ public void equals() {
+ String firstRole = "Tester";
+ String secondRole = "Developer";
+ AddDeveloperRoleCommand addFirstCommand = new AddDeveloperRoleCommand(firstRole);
+ AddDeveloperRoleCommand addSecondCommand = new AddDeveloperRoleCommand(secondRole);
+
+ // same object -> returns true
+ assertTrue(addFirstCommand.equals(addFirstCommand));
+
+ // same values -> returns False because cannot add twice
+ AddDeveloperRoleCommand addFirstCommandCopy = new AddDeveloperRoleCommand(firstRole);
+ assertFalse(addFirstCommand.equals(addFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(addFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(addFirstCommand.equals(null));
+
+ // different developer role -> returns false
+ assertFalse(addFirstCommand.equals(addSecondCommand));
+ }
+
+ @Test
+ public void toStringTest() {
+ String roleName = "Tester";
+ AddDeveloperRoleCommand addDeveloperRoleCommand = new AddDeveloperRoleCommand(roleName);
+ assertEquals(addDeveloperRoleCommand.toString(), new AddDeveloperRoleCommand(roleName).toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/deleteroles/DeleteClientRoleCommandTest.java b/src/test/java/seedu/address/logic/commands/deleteroles/DeleteClientRoleCommandTest.java
new file mode 100644
index 00000000000..913575056a8
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/deleteroles/DeleteClientRoleCommandTest.java
@@ -0,0 +1,114 @@
+package seedu.address.logic.commands.deleteroles;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.testutil.TypicalDevelopers.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.addroles.AddClientRoleCommand;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.client.ClientRoles;
+import seedu.address.testutil.Assert;
+import seedu.address.testutil.ClientBuilder;
+
+public class DeleteClientRoleCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void constructor_nullRole_throwsNullPointerException() {
+ Assert.assertThrows(NullPointerException.class, () -> new DeleteClientRoleCommand(null));
+ }
+
+ @Test
+ public void execute_roleAcceptedByModel_deleteSuccessful() throws CommandException {
+
+ String validRole = "NewRole";
+ AddClientRoleCommand addClientRoleCommand = new AddClientRoleCommand(validRole);
+ addClientRoleCommand.execute(model);
+
+ DeleteClientRoleCommand deleteClientRoleCommand = new DeleteClientRoleCommand(validRole);
+
+ String expectedMessage = String.format(DeleteClientRoleCommand.MESSAGE_SUCCESS, validRole);
+ assertEquals(deleteClientRoleCommand.execute(model).getFeedbackToUser(), expectedMessage);
+ }
+
+ @Test
+ public void execute_roleSomeoneUsing_throwsCommandException() throws CommandException {
+ // Assign a client with the specified role
+ String roleWithClient = "NewRole";
+ AddClientRoleCommand addClientRoleCommand = new AddClientRoleCommand(roleWithClient);
+ addClientRoleCommand.execute(model);
+ ClientBuilder clientBuilder = new ClientBuilder().withRole(roleWithClient);
+ model.addClient(clientBuilder.build());
+
+ // Attempt to delete the role
+ DeleteClientRoleCommand deleteClientRoleCommand = new DeleteClientRoleCommand(roleWithClient);
+ String expectedResult = String.format(DeleteClientRoleCommand.MESSAGE_CANNOT_DELETE_REPEAT,
+ Messages.format(roleWithClient));
+
+ // Assert that the command throws an exception
+ assertCommandFailure(deleteClientRoleCommand, model, expectedResult);
+
+ model.deleteClient(clientBuilder.build());
+ deleteClientRoleCommand.execute(model);
+ }
+
+
+ @Test
+ public void execute_roleNotInList_throwsCommandException() {
+ String nonExistingRole = "NonExistingRole";
+ DeleteClientRoleCommand deleteClientRoleCommand = new DeleteClientRoleCommand(nonExistingRole);
+
+ assertCommandFailure(deleteClientRoleCommand, model,
+ DeleteClientRoleCommand.MESSAGE_CANNOT_DELETE_NONEXISTING
+ + DeleteClientRoleCommand.MESSAGE_EXISTING_CLIENT_ROLES
+ + ClientRoles.printRoles());
+ }
+
+ @Test
+ public void execute_roleIsPredefined_throwsCommandException() {
+ String roleWithClient = "Client";
+ DeleteClientRoleCommand deleteClientRoleCommand = new DeleteClientRoleCommand(roleWithClient);
+ assertThrows(CommandException.class, () -> deleteClientRoleCommand.execute(model));
+ }
+
+ @Test
+ public void equals() {
+ String firstRole = "Tester";
+ String secondRole = "Client";
+ DeleteClientRoleCommand deleteFirstCommand = new DeleteClientRoleCommand(firstRole);
+ DeleteClientRoleCommand deleteSecondCommand = new DeleteClientRoleCommand(secondRole);
+
+ // same object -> returns true
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
+
+ // role will no longer exists-> returns false
+ DeleteClientRoleCommand deleteFirstCommandCopy = new DeleteClientRoleCommand(firstRole);
+ assertFalse(deleteFirstCommand.equals(deleteFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(deleteFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(deleteFirstCommand.equals(null));
+
+ // different client role -> returns false
+ assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
+ }
+
+ @Test
+ public void toStringTest() {
+ String roleName = "Tester";
+ DeleteClientRoleCommand deleteClientRoleCommand = new DeleteClientRoleCommand(roleName);
+ assertEquals(deleteClientRoleCommand.toString(), new DeleteClientRoleCommand(roleName).toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/deleteroles/DeleteDeveloperRoleCommandTest.java b/src/test/java/seedu/address/logic/commands/deleteroles/DeleteDeveloperRoleCommandTest.java
new file mode 100644
index 00000000000..da5a1161a41
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/deleteroles/DeleteDeveloperRoleCommandTest.java
@@ -0,0 +1,116 @@
+package seedu.address.logic.commands.deleteroles;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalDevelopers.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.addroles.AddDeveloperRoleCommand;
+import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.developer.DeveloperRoles;
+import seedu.address.testutil.Assert;
+import seedu.address.testutil.DeveloperBuilder;
+
+public class DeleteDeveloperRoleCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void constructor_nullRole_throwsNullPointerException() {
+ Assert.assertThrows(NullPointerException.class, () -> new DeleteDeveloperRoleCommand(null));
+ }
+
+ @Test
+ public void execute_roleAcceptedByModel_deleteSuccessful() throws CommandException {
+
+ String validRole = "NewRole";
+ AddDeveloperRoleCommand addDeveloperRoleCommand = new AddDeveloperRoleCommand(validRole);
+ addDeveloperRoleCommand.execute(model);
+
+ DeleteDeveloperRoleCommand deleteDeveloperRoleCommand = new DeleteDeveloperRoleCommand(validRole);
+
+ String expectedMessage = String.format(DeleteDeveloperRoleCommand.MESSAGE_SUCCESS, validRole);
+
+ assertCommandSuccess(deleteDeveloperRoleCommand, model, expectedMessage, model);
+ }
+
+ @Test
+ public void execute_roleSomeoneUsing_throwsCommandException() throws CommandException {
+ // Assign a developer with the specified role
+ String roleWithDevelopers = "NewRole";
+ AddDeveloperRoleCommand addDeveloperRoleCommand = new AddDeveloperRoleCommand(roleWithDevelopers);
+ addDeveloperRoleCommand.execute(model);
+ DeveloperBuilder developerBuilder = new DeveloperBuilder().withRole(roleWithDevelopers);
+ model.addDeveloper(developerBuilder.build());
+
+ // Attempt to delete the role
+ DeleteDeveloperRoleCommand deleteDeveloperRoleCommand = new DeleteDeveloperRoleCommand(roleWithDevelopers);
+ String expectedResult = String.format(DeleteDeveloperRoleCommand.MESSAGE_CANNOT_DELETE_REPEAT,
+ Messages.format(roleWithDevelopers));
+
+ // Assert that the command throws an exception
+ assertCommandFailure(deleteDeveloperRoleCommand, model, expectedResult);
+
+ model.deleteDeveloper(developerBuilder.build());
+ deleteDeveloperRoleCommand.execute(model);
+ }
+
+
+ @Test
+ public void execute_roleNotInList_throwsCommandException() {
+ String nonExistingRole = "NonExistingRole";
+ DeleteDeveloperRoleCommand deleteDeveloperRoleCommand = new DeleteDeveloperRoleCommand(nonExistingRole);
+
+ assertCommandFailure(deleteDeveloperRoleCommand, model,
+ DeleteDeveloperRoleCommand.MESSAGE_CANNOT_DELETE_NONEXISTING
+ + DeleteDeveloperRoleCommand.MESSAGE_EXISTING_DEVELOPERS_ROLES
+ + DeveloperRoles.printRoles());
+ }
+
+ @Test
+ public void execute_roleIsPredefined_throwsCommandException() {
+ String roleWithDevelopers = "Developer";
+ DeleteDeveloperRoleCommand deleteDeveloperRoleCommand = new DeleteDeveloperRoleCommand(roleWithDevelopers);
+ assertThrows(CommandException.class, () -> deleteDeveloperRoleCommand.execute(model));
+ }
+
+ @Test
+ public void equals() {
+ String firstRole = "Tester";
+ String secondRole = "Developer";
+ DeleteDeveloperRoleCommand deleteFirstCommand = new DeleteDeveloperRoleCommand(firstRole);
+ DeleteDeveloperRoleCommand deleteSecondCommand = new DeleteDeveloperRoleCommand(secondRole);
+
+ // same object -> returns true
+ assertTrue(deleteFirstCommand.equals(deleteFirstCommand));
+
+ // role will no longer exists-> returns false
+ DeleteDeveloperRoleCommand deleteFirstCommandCopy = new DeleteDeveloperRoleCommand(firstRole);
+ assertFalse(deleteFirstCommand.equals(deleteFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(deleteFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(deleteFirstCommand.equals(null));
+
+ // different developer role -> returns false
+ assertFalse(deleteFirstCommand.equals(deleteSecondCommand));
+ }
+
+ @Test
+ public void toStringTest() {
+ String roleName = "Tester";
+ DeleteDeveloperRoleCommand deleteDeveloperRoleCommand = new DeleteDeveloperRoleCommand(roleName);
+ assertEquals(deleteDeveloperRoleCommand.toString(), new DeleteDeveloperRoleCommand(roleName).toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/edit/EditClientCommandTest.java b/src/test/java/seedu/address/logic/commands/edit/EditClientCommandTest.java
index 8ff31ad66f0..fe8fc4bea20 100644
--- a/src/test/java/seedu/address/logic/commands/edit/EditClientCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/edit/EditClientCommandTest.java
@@ -7,10 +7,14 @@
import static seedu.address.logic.commands.CommandTestUtil.DESC_DAN;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_CALEB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_2_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_3_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.assertClientCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showClientAtIndex;
import static seedu.address.testutil.TypicalClients.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalClients.getTypicalAddressBookWithProjects;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
@@ -33,10 +37,11 @@
*/
public class EditClientCommandTest {
- private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private final Model modelNoProjects = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private final Model modelWithProjects = new ModelManager(getTypicalAddressBookWithProjects(), new UserPrefs());
@Test
- public void execute_allFieldsSpecifiedUnfilteredList_success() {
+ public void execute_allFieldsSpecifiedNoProjectEditUnfilteredListNoProjects_success() {
Client editedClient = new ClientBuilder().build();
EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder(editedClient)
.build();
@@ -45,101 +50,178 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() {
String expectedMessage = String.format(EditClientCommand.MESSAGE_EDIT_CLIENT_SUCCESS,
Messages.format(editedClient));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setClient(model.getFilteredClientList().get(0), editedClient);
+ Model expectedModel = new ModelManager(new AddressBook(modelNoProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setClient(modelNoProjects.getFilteredClientList().get(0), editedClient);
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
+ assertClientCommandSuccess(editCommand, modelNoProjects, expectedMessage, expectedModel);
}
- // Project needs to be created
- /*@Test
- public void execute_someFieldsSpecifiedUnfilteredList_success() {
- Index indexLastDeveloper = Index.fromOneBased(model.getFilteredDeveloperList().size());
- Developer lastDeveloper = model.getFilteredDeveloperList().get(indexLastDeveloper.getZeroBased());
+ @Test
+ public void execute_allFieldsSpecifiedNoProjectEditUnfilteredListWithProjects_success() {
+ Client editedClient = new ClientBuilder().build();
+ EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder(editedClient)
+ .build();
+ EditClientCommand editCommand = new EditClientCommand(INDEX_FIRST_PERSON, descriptor);
- DeveloperBuilder developerInList = new DeveloperBuilder(lastDeveloper);
- Developer editedDeveloper = developerInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withProjects(VALID_PROJECT_1_BOB).build();
+ String expectedMessage = String.format(EditClientCommand.MESSAGE_EDIT_CLIENT_SUCCESS,
+ Messages.format(editedClient));
+
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setClient(modelWithProjects.getFilteredClientList().get(0), editedClient);
+
+ assertClientCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
- EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder()
+ @Test
+ public void execute_someFieldsSpecifiedValidProjectEditUnfilteredListWithProjects_success() {
+ Index indexLastClient = Index.fromOneBased(modelWithProjects.getFilteredClientList().size());
+ Client lastClient = modelWithProjects.getFilteredClientList().get(indexLastClient.getZeroBased());
+
+ ClientBuilder clientInList = new ClientBuilder(lastClient);
+ Client editedClient = clientInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
+ .withProjects(VALID_PROJECT_3_BOB).build();
+
+ EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder()
.withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withProjects(VALID_PROJECT_1_BOB).build();
- EditDeveloperCommand editCommand = new EditDeveloperCommand(indexLastDeveloper, descriptor);
+ .withPhone(VALID_PHONE_BOB).withProjects(VALID_PROJECT_3_BOB).build();
+ EditClientCommand editCommand = new EditClientCommand(indexLastClient, descriptor);
- String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
- Messages.format(editedDeveloper));
+ String expectedMessage = String.format(EditClientCommand.MESSAGE_EDIT_CLIENT_SUCCESS,
+ Messages.format(editedClient));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setDeveloper(lastDeveloper, editedDeveloper);
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setClient(lastClient, editedClient);
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }*/
+ assertClientCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
- // Project needs to be created
- /*
@Test
- public void execute_noFieldSpecifiedUnfilteredList_success() {
- EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
- new EditDeveloperCommand.EditDeveloperDescriptor());
- Developer editedDeveloper = model.getFilteredDeveloperList().get(INDEX_FIRST_PERSON.getZeroBased());
+ public void execute_someFieldsSpecifiedInvalidProjectEditUnfilteredListWithProjects_failure() {
+ Index indexLastClient = Index.fromOneBased(modelWithProjects.getFilteredClientList().size());
+
+ EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder()
+ .withName(VALID_NAME_BOB)
+ .withPhone(VALID_PHONE_BOB).withProjects(VALID_PROJECT_2_BOB).build();
+ EditClientCommand editCommand = new EditClientCommand(indexLastClient, descriptor);
+
+ String expectedMessage = String.format(Messages.MESSAGE_NONEXISTENT_PROJECT, VALID_PROJECT_2_BOB);
+
+ assertCommandFailure(editCommand, modelWithProjects, expectedMessage);
+ }
+
+ @Test
+ public void execute_allFieldsSpecifiedValidProjectEditUnfilteredListWithProjects_success() {
+ Client editedClient = new ClientBuilder().withProjects(VALID_PROJECT_3_BOB).build();
+ EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder(editedClient)
+ .build();
+ EditClientCommand editCommand = new EditClientCommand(INDEX_FIRST_PERSON, descriptor);
+
+ String expectedMessage = String.format(EditClientCommand.MESSAGE_EDIT_CLIENT_SUCCESS,
+ Messages.format(editedClient));
+
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setClient(modelWithProjects.getFilteredClientList().get(0), editedClient);
+
+ assertClientCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_filteredListValidProjectEditWithProjects_success() {
+ showClientAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
+
+ Client clientInFilteredList = modelWithProjects.getFilteredClientList()
+ .get(INDEX_FIRST_PERSON.getZeroBased());
+ Client editedClient = new ClientBuilder(clientInFilteredList).withName(VALID_NAME_BOB)
+ .withProjects(VALID_PROJECT_3_BOB).build();
+ EditClientCommand editCommand = new EditClientCommand(INDEX_FIRST_PERSON,
+ new EditClientDescriptorBuilder().withName(VALID_NAME_BOB).withProjects(VALID_PROJECT_3_BOB)
+ .build());
- String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
- Messages.format(editedDeveloper));
+ String expectedMessage = String.format(EditClientCommand.MESSAGE_EDIT_CLIENT_SUCCESS,
+ Messages.format(editedClient));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setClient(modelWithProjects.getFilteredClientList().get(0), editedClient);
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }*/
+ assertClientCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
- // Project needs to be created
- /* @Test
- public void execute_filteredList_success() {
- showDeveloperAtIndex(model, INDEX_FIRST_PERSON);
+ @Test
+ public void execute_filteredListInvalidProjectEditWithProjects_failure() {
+ showClientAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
- Developer developerInFilteredList = model.getFilteredDeveloperList().get(INDEX_FIRST_PERSON.getZeroBased());
- Developer editedDeveloper = new DeveloperBuilder(developerInFilteredList).withName(VALID_NAME_BOB).build();
- EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
- new EditDeveloperDescriptorBuilder().withName(VALID_NAME_BOB).build());
+ EditClientCommand editCommand = new EditClientCommand(INDEX_FIRST_PERSON,
+ new EditClientDescriptorBuilder().withName(VALID_NAME_BOB).withProjects(VALID_PROJECT_2_BOB)
+ .build());
- String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
- Messages.format(editedDeveloper));
+ String expectedMessage = String.format(Messages.MESSAGE_NONEXISTENT_PROJECT, VALID_PROJECT_2_BOB);
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setDeveloper(model.getFilteredDeveloperList().get(0), editedDeveloper);
+ assertCommandFailure(editCommand, modelWithProjects, expectedMessage);
+ }
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- }*/
+ @Test
+ public void execute_duplicateClientUnfilteredListNoProjects_failure() {
+ Client firstClient = modelNoProjects.getFilteredClientList().get(INDEX_FIRST_PERSON.getZeroBased());
+ EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder(firstClient)
+ .build();
+ EditClientCommand editCommand = new EditClientCommand(INDEX_SECOND_PERSON, descriptor);
+
+ assertCommandFailure(editCommand, modelNoProjects, EditClientCommand.MESSAGE_DUPLICATE_CLIENT);
+ }
@Test
- public void execute_duplicateClientUnfilteredList_failure() {
- Client firstClient = model.getFilteredClientList().get(INDEX_FIRST_PERSON.getZeroBased());
+ public void execute_duplicateClientUnfilteredListWithProjects_failure() {
+ Client firstClient = modelWithProjects.getFilteredClientList().get(INDEX_FIRST_PERSON.getZeroBased());
EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder(firstClient)
.build();
EditClientCommand editCommand = new EditClientCommand(INDEX_SECOND_PERSON, descriptor);
- assertCommandFailure(editCommand, model, EditClientCommand.MESSAGE_DUPLICATE_CLIENT);
+ assertCommandFailure(editCommand, modelWithProjects, EditClientCommand.MESSAGE_DUPLICATE_CLIENT);
}
@Test
- public void execute_duplicateClientFilteredList_failure() {
- showClientAtIndex(model, INDEX_FIRST_PERSON);
+ public void execute_duplicateClientFilteredListNoProjects_failure() {
+ showClientAtIndex(modelNoProjects, INDEX_FIRST_PERSON);
// edit client in filtered list into a duplicate in address book
- Client clientInList = model.getAddressBook().getClientList().get(INDEX_SECOND_PERSON.getZeroBased());
+ Client clientInList = modelNoProjects.getAddressBook().getClientList().get(INDEX_SECOND_PERSON.getZeroBased());
EditClientCommand editCommand = new EditClientCommand(INDEX_FIRST_PERSON,
new EditClientDescriptorBuilder(clientInList).build());
- assertCommandFailure(editCommand, model, EditClientCommand.MESSAGE_DUPLICATE_CLIENT);
+ assertCommandFailure(editCommand, modelNoProjects, EditClientCommand.MESSAGE_DUPLICATE_CLIENT);
}
@Test
- public void execute_invalidClientIndexUnfilteredList_failure() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredClientList().size() + 1);
+ public void execute_duplicateClientFilteredListWithProjects_failure() {
+ showClientAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
+
+ // edit client in filtered list into a duplicate in address book
+ Client clientInList = modelWithProjects.getAddressBook().getClientList()
+ .get(INDEX_SECOND_PERSON.getZeroBased());
+ EditClientCommand editCommand = new EditClientCommand(INDEX_FIRST_PERSON,
+ new EditClientDescriptorBuilder(clientInList).build());
+
+ assertCommandFailure(editCommand, modelWithProjects, EditClientCommand.MESSAGE_DUPLICATE_CLIENT);
+ }
+
+ @Test
+ public void execute_invalidClientIndexUnfilteredListNoProjects_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(modelNoProjects.getFilteredClientList().size() + 1);
+ EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder()
+ .withName(VALID_NAME_CALEB).build();
+ EditClientCommand editCommand = new EditClientCommand(outOfBoundIndex, descriptor);
+
+ assertCommandFailure(editCommand, modelNoProjects, Messages.MESSAGE_INVALID_CLIENT_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_invalidClientIndexUnfilteredListWithProjects_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(modelWithProjects.getFilteredClientList().size() + 1);
EditClientCommand.EditClientDescriptor descriptor = new EditClientDescriptorBuilder()
.withName(VALID_NAME_CALEB).build();
EditClientCommand editCommand = new EditClientCommand(outOfBoundIndex, descriptor);
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_CLIENT_DISPLAYED_INDEX);
+ assertCommandFailure(editCommand, modelWithProjects, Messages.MESSAGE_INVALID_CLIENT_DISPLAYED_INDEX);
}
/**
@@ -147,16 +229,30 @@ public void execute_invalidClientIndexUnfilteredList_failure() {
* but smaller than size of address book
*/
@Test
- public void execute_invalidClientIndexFilteredList_failure() {
- showClientAtIndex(model, INDEX_FIRST_PERSON);
+ public void execute_invalidClientIndexFilteredListNoProjects_failure() {
+ showClientAtIndex(modelNoProjects, INDEX_FIRST_PERSON);
+ Index outOfBoundIndex = INDEX_SECOND_PERSON;
+ // ensures that outOfBoundIndex is still in bounds of address book list
+ assertTrue(outOfBoundIndex.getZeroBased() < modelNoProjects.getAddressBook().getClientList().size());
+
+ EditClientCommand editCommand = new EditClientCommand(outOfBoundIndex,
+ new EditClientDescriptorBuilder().withName(VALID_NAME_BOB).build());
+
+ assertCommandFailure(editCommand, modelNoProjects, Messages.MESSAGE_INVALID_CLIENT_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_invalidClientIndexFilteredListWithProjects_failure() {
+ showClientAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
Index outOfBoundIndex = INDEX_SECOND_PERSON;
// ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getClientList().size());
+ assertTrue(outOfBoundIndex.getZeroBased() < modelWithProjects.getAddressBook()
+ .getClientList().size());
EditClientCommand editCommand = new EditClientCommand(outOfBoundIndex,
new EditClientDescriptorBuilder().withName(VALID_NAME_BOB).build());
- assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_CLIENT_DISPLAYED_INDEX);
+ assertCommandFailure(editCommand, modelWithProjects, Messages.MESSAGE_INVALID_CLIENT_DISPLAYED_INDEX);
}
@Test
diff --git a/src/test/java/seedu/address/logic/commands/edit/EditClientDescriptorTest.java b/src/test/java/seedu/address/logic/commands/edit/EditClientDescriptorTest.java
new file mode 100644
index 00000000000..8ec3305b25f
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/edit/EditClientDescriptorTest.java
@@ -0,0 +1,76 @@
+package seedu.address.logic.commands.edit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_CALEB;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_DAN;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_DAN;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_DAN;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_DAN;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_DAN;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_1_DAN;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.testutil.EditClientDescriptorBuilder;
+
+public class EditClientDescriptorTest {
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ EditClientCommand.EditClientDescriptor descriptorWithSameValues =
+ new EditClientCommand.EditClientDescriptor(DESC_CALEB);
+ assertEquals(DESC_CALEB, descriptorWithSameValues);
+
+ // same object -> returns true
+ assertEquals(DESC_CALEB, DESC_CALEB);
+
+ // null -> returns false
+ assertNotEquals(null, DESC_CALEB);
+
+ // different types -> returns false
+ assertNotEquals(5, DESC_CALEB);
+
+ // different values -> returns false
+ assertNotEquals(DESC_CALEB, DESC_DAN);
+
+ // different name -> returns false
+ EditClientCommand.EditClientDescriptor editedCaleb = new EditClientDescriptorBuilder(DESC_CALEB)
+ .withName(VALID_NAME_DAN).build();
+ assertNotEquals(DESC_CALEB, editedCaleb);
+
+ // different phone -> returns false
+ editedCaleb = new EditClientDescriptorBuilder(DESC_CALEB).withPhone(VALID_PHONE_DAN).build();
+ assertNotEquals(DESC_CALEB, editedCaleb);
+
+ // different email -> returns false
+ editedCaleb = new EditClientDescriptorBuilder(DESC_CALEB).withEmail(VALID_EMAIL_DAN).build();
+ assertNotEquals(DESC_CALEB, editedCaleb);
+
+ // different address -> returns false
+ editedCaleb = new EditClientDescriptorBuilder(DESC_CALEB).withAddress(VALID_ADDRESS_DAN).build();
+ assertNotEquals(DESC_CALEB, editedCaleb);
+
+ // different tags -> returns false
+ editedCaleb = new EditClientDescriptorBuilder(DESC_CALEB).withProjects(VALID_PROJECT_1_DAN).build();
+ assertNotEquals(DESC_CALEB, editedCaleb);
+ }
+
+ @Test
+ public void toStringMethod() {
+ EditClientCommand.EditClientDescriptor editClientDescriptor =
+ new EditClientDescriptorBuilder().build();
+ String expected = EditClientCommand.EditClientDescriptor.class.getCanonicalName() + "{name="
+ + editClientDescriptor.getName().orElse(null) + ", phone="
+ + editClientDescriptor.getPhone().orElse(null) + ", email="
+ + editClientDescriptor.getEmail().orElse(null) + ", address="
+ + editClientDescriptor.getAddress().orElse(null) + ", projects="
+ + editClientDescriptor.getProjects().orElse(null) + ", role="
+ + editClientDescriptor.getRole().orElse(null) + ", organisation="
+ + editClientDescriptor.getOrganisation().orElse(null) + ", document="
+ + editClientDescriptor.getDocument().orElse(null) + "}";
+
+ assertEquals(expected, editClientDescriptor.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/edit/EditDeveloperCommandTest.java b/src/test/java/seedu/address/logic/commands/edit/EditDeveloperCommandTest.java
index b791ac15609..b7f687d2a5c 100644
--- a/src/test/java/seedu/address/logic/commands/edit/EditDeveloperCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/edit/EditDeveloperCommandTest.java
@@ -6,10 +6,15 @@
import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY;
import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_CALEB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_2_BOB;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_3_BOB;
import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.assertDeveloperCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showDeveloperAtIndex;
import static seedu.address.testutil.TypicalDevelopers.getTypicalAddressBook;
+import static seedu.address.testutil.TypicalDevelopers.getTypicalAddressBookWithProjects;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON;
@@ -28,14 +33,15 @@
import seedu.address.testutil.EditDeveloperDescriptorBuilder;
/**
- * Contains integration tests (interaction with the Model) and unit tests for EditCommand.
+ * Contains integration tests (interaction with the Model) and unit tests for EditDeveloperCommand.
*/
public class EditDeveloperCommandTest {
- private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private final Model modelNoProjects = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private final Model modelWithProjects = new ModelManager(getTypicalAddressBookWithProjects(), new UserPrefs());
@Test
- public void execute_allFieldsSpecifiedUnfilteredList_success() {
+ public void execute_allFieldsSpecifiedNoProjectEditUnfilteredListNoProjects_success() {
Developer editedDeveloper = new DeveloperBuilder().build();
EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder(editedDeveloper)
.build();
@@ -44,43 +50,86 @@ public void execute_allFieldsSpecifiedUnfilteredList_success() {
String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
Messages.format(editedDeveloper));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setDeveloper(model.getFilteredDeveloperList().get(0), editedDeveloper);
+ Model expectedModel = new ModelManager(new AddressBook(modelNoProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setDeveloper(modelNoProjects.getFilteredDeveloperList().get(0), editedDeveloper);
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
+ assertDeveloperCommandSuccess(editCommand, modelNoProjects, expectedMessage, expectedModel);
}
- // need to build a project first
- /*@Test
- public void execute_someFieldsSpecifiedUnfilteredList_success() {
- AddressBookParser.unlock();
- Index indexLastPerson = Index.fromOneBased(model.getFilteredDeveloperList().size());
- Developer lastDeveloper = model.getFilteredDeveloperList().get(indexLastPerson.getZeroBased());
+ @Test
+ public void execute_allFieldsSpecifiedNoProjectEditUnfilteredListWithProjects_success() {
+ Developer editedDeveloper = new DeveloperBuilder().build();
+ EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder(editedDeveloper)
+ .build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON, descriptor);
+
+ String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
+ Messages.format(editedDeveloper));
- DeveloperBuilder personInList = new DeveloperBuilder(lastDeveloper);
- Developer editedDeveloper = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
- .withProjects(VALID_PROJECT_1_BOB).build();
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setDeveloper(modelWithProjects.getFilteredDeveloperList().get(0), editedDeveloper);
+
+ assertDeveloperCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_someFieldsSpecifiedValidProjectEditUnfilteredListWithProjects_success() {
+ Index indexLastDeveloper = Index.fromOneBased(modelWithProjects.getFilteredDeveloperList().size());
+ Developer lastDeveloper = modelWithProjects.getFilteredDeveloperList().get(indexLastDeveloper.getZeroBased());
+
+ DeveloperBuilder developerInList = new DeveloperBuilder(lastDeveloper);
+ Developer editedDeveloper = developerInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB)
+ .withProjects(VALID_PROJECT_3_BOB).build();
EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder()
- .withName(VALID_NAME_BOB)
- .withPhone(VALID_PHONE_BOB).withProjects(VALID_PROJECT_1_BOB).build();
- EditDeveloperCommand editCommand = new EditDeveloperCommand(indexLastPerson, descriptor);
+ .withName(VALID_NAME_BOB)
+ .withPhone(VALID_PHONE_BOB).withProjects(VALID_PROJECT_3_BOB).build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(indexLastDeveloper, descriptor);
String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
- Messages.format(editedDeveloper));
+ Messages.format(editedDeveloper));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
expectedModel.setDeveloper(lastDeveloper, editedDeveloper);
- assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
- } */
+ assertDeveloperCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
- // need to build a prj first
+ @Test
+ public void execute_someFieldsSpecifiedInvalidProjectEditUnfilteredListWithProjects_failure() {
+ Index indexLastDeveloper = Index.fromOneBased(modelWithProjects.getFilteredDeveloperList().size());
+
+ EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder()
+ .withName(VALID_NAME_BOB)
+ .withPhone(VALID_PHONE_BOB).withProjects(VALID_PROJECT_2_BOB).build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(indexLastDeveloper, descriptor);
+
+ String expectedMessage = String.format(Messages.MESSAGE_NONEXISTENT_PROJECT, VALID_PROJECT_2_BOB);
+
+ assertCommandFailure(editCommand, modelWithProjects, expectedMessage);
+ }
+
+ @Test
+ public void execute_allFieldsSpecifiedValidProjectEditUnfilteredListWithProjects_success() {
+ Developer editedDeveloper = new DeveloperBuilder().withProjects(VALID_PROJECT_3_BOB).build();
+ EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder(editedDeveloper)
+ .build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON, descriptor);
+
+ String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
+ Messages.format(editedDeveloper));
+
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setDeveloper(modelWithProjects.getFilteredDeveloperList().get(0), editedDeveloper);
+
+ assertDeveloperCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
+
+ // Project needs to be created
/*
@Test
public void execute_noFieldSpecifiedUnfilteredList_success() {
- AddressBookParser.unlock();
- EditDeveloperCommand editDeveloperCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
new EditDeveloperCommand.EditDeveloperDescriptor());
Developer editedDeveloper = model.getFilteredDeveloperList().get(INDEX_FIRST_PERSON.getZeroBased());
@@ -89,59 +138,107 @@ public void execute_noFieldSpecifiedUnfilteredList_success() {
Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- assertCommandSuccess(editDeveloperCommand, model, expectedMessage, expectedModel);
+ assertCommandSuccess(editCommand, model, expectedMessage, expectedModel);
}*/
- // need to build a project first
- /* @Test
- public void execute_filteredList_success() {
- AddressBookParser.unlock();
- showDeveloperAtIndex(model, INDEX_FIRST_PERSON);
+ @Test
+ public void execute_filteredListValidProjectEditWithProjects_success() {
+ showDeveloperAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
- Developer developerInFilteredList = model.getFilteredDeveloperList().get(INDEX_FIRST_PERSON.getZeroBased());
- Developer editedDeveloper = new DeveloperBuilder(developerInFilteredList).withName(VALID_NAME_BOB).build();
- EditDeveloperCommand editDeveloperCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
- new EditDeveloperDescriptorBuilder().withName(VALID_NAME_BOB).build());
+ Developer developerInFilteredList = modelWithProjects.getFilteredDeveloperList()
+ .get(INDEX_FIRST_PERSON.getZeroBased());
+ Developer editedDeveloper = new DeveloperBuilder(developerInFilteredList).withName(VALID_NAME_BOB)
+ .withProjects(VALID_PROJECT_3_BOB).build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
+ new EditDeveloperDescriptorBuilder().withName(VALID_NAME_BOB).withProjects(VALID_PROJECT_3_BOB)
+ .build());
String expectedMessage = String.format(EditDeveloperCommand.MESSAGE_EDIT_DEVELOPER_SUCCESS,
Messages.format(editedDeveloper));
- Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
- expectedModel.setDeveloper(model.getFilteredDeveloperList().get(0), editedDeveloper);
+ Model expectedModel = new ModelManager(new AddressBook(modelWithProjects.getAddressBook()), new UserPrefs());
+ expectedModel.setDeveloper(modelWithProjects.getFilteredDeveloperList().get(0), editedDeveloper);
- assertCommandSuccess(editDeveloperCommand, model, expectedMessage, expectedModel);
- }*/
+ assertDeveloperCommandSuccess(editCommand, modelWithProjects, expectedMessage, expectedModel);
+ }
@Test
- public void execute_duplicatePersonUnfilteredList_failure() {
- Developer firstDeveloper = model.getFilteredDeveloperList().get(INDEX_FIRST_PERSON.getZeroBased());
+ public void execute_filteredListInvalidProjectEditWithProjects_failure() {
+ showDeveloperAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
+
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
+ new EditDeveloperDescriptorBuilder().withName(VALID_NAME_BOB).withProjects(VALID_PROJECT_2_BOB)
+ .build());
+
+ String expectedMessage = String.format(Messages.MESSAGE_NONEXISTENT_PROJECT, VALID_PROJECT_2_BOB);
+
+ assertCommandFailure(editCommand, modelWithProjects, expectedMessage);
+ }
+
+ @Test
+ public void execute_duplicateDeveloperUnfilteredListNoProjects_failure() {
+ Developer firstDeveloper = modelNoProjects.getFilteredDeveloperList().get(INDEX_FIRST_PERSON.getZeroBased());
EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder(firstDeveloper)
.build();
- EditDeveloperCommand editDeveloperCommand = new EditDeveloperCommand(INDEX_SECOND_PERSON, descriptor);
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_SECOND_PERSON, descriptor);
+
+ assertCommandFailure(editCommand, modelNoProjects, EditDeveloperCommand.MESSAGE_DUPLICATE_DEVELOPER);
+ }
+
+ @Test
+ public void execute_duplicateDeveloperUnfilteredListWithProjects_failure() {
+ Developer firstDeveloper = modelWithProjects.getFilteredDeveloperList().get(INDEX_FIRST_PERSON.getZeroBased());
+ EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder(firstDeveloper)
+ .build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_SECOND_PERSON, descriptor);
+
+ assertCommandFailure(editCommand, modelWithProjects, EditDeveloperCommand.MESSAGE_DUPLICATE_DEVELOPER);
+ }
- assertCommandFailure(editDeveloperCommand, model, EditDeveloperCommand.MESSAGE_DUPLICATE_DEVELOPER);
+ @Test
+ public void execute_duplicateDeveloperFilteredListNoProjects_failure() {
+ showDeveloperAtIndex(modelNoProjects, INDEX_FIRST_PERSON);
+
+ // edit developer in filtered list into a duplicate in address book
+ Developer developerInList = modelNoProjects.getAddressBook().getDeveloperList()
+ .get(INDEX_SECOND_PERSON.getZeroBased());
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
+ new EditDeveloperDescriptorBuilder(developerInList).build());
+
+ assertCommandFailure(editCommand, modelNoProjects, EditDeveloperCommand.MESSAGE_DUPLICATE_DEVELOPER);
}
@Test
- public void execute_duplicatePersonFilteredList_failure() {
- showDeveloperAtIndex(model, INDEX_FIRST_PERSON);
+ public void execute_duplicateDeveloperFilteredListWithProjects_failure() {
+ showDeveloperAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
// edit developer in filtered list into a duplicate in address book
- Developer developerInList = model.getAddressBook().getDeveloperList().get(INDEX_SECOND_PERSON.getZeroBased());
- EditDeveloperCommand editDeveloperCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
+ Developer developerInList = modelWithProjects.getAddressBook().getDeveloperList()
+ .get(INDEX_SECOND_PERSON.getZeroBased());
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(INDEX_FIRST_PERSON,
new EditDeveloperDescriptorBuilder(developerInList).build());
- assertCommandFailure(editDeveloperCommand, model, EditDeveloperCommand.MESSAGE_DUPLICATE_DEVELOPER);
+ assertCommandFailure(editCommand, modelWithProjects, EditDeveloperCommand.MESSAGE_DUPLICATE_DEVELOPER);
+ }
+
+ @Test
+ public void execute_invalidDeveloperIndexUnfilteredListNoProjects_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(modelNoProjects.getFilteredDeveloperList().size() + 1);
+ EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder()
+ .withName(VALID_NAME_CALEB).build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(outOfBoundIndex, descriptor);
+
+ assertCommandFailure(editCommand, modelNoProjects, Messages.MESSAGE_INVALID_DEVELOPER_DISPLAYED_INDEX);
}
@Test
- public void execute_invalidPersonIndexUnfilteredList_failure() {
- Index outOfBoundIndex = Index.fromOneBased(model.getFilteredDeveloperList().size() + 1);
+ public void execute_invalidDeveloperIndexUnfilteredListWithProjects_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(modelWithProjects.getFilteredDeveloperList().size() + 1);
EditDeveloperCommand.EditDeveloperDescriptor descriptor = new EditDeveloperDescriptorBuilder()
- .withName(VALID_NAME_BOB).build();
- EditDeveloperCommand editDeveloperCommand = new EditDeveloperCommand(outOfBoundIndex, descriptor);
+ .withName(VALID_NAME_CALEB).build();
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(outOfBoundIndex, descriptor);
- assertCommandFailure(editDeveloperCommand, model, Messages.MESSAGE_INVALID_DEVELOPER_DISPLAYED_INDEX);
+ assertCommandFailure(editCommand, modelWithProjects, Messages.MESSAGE_INVALID_DEVELOPER_DISPLAYED_INDEX);
}
/**
@@ -149,16 +246,30 @@ public void execute_invalidPersonIndexUnfilteredList_failure() {
* but smaller than size of address book
*/
@Test
- public void execute_invalidPersonIndexFilteredList_failure() {
- showDeveloperAtIndex(model, INDEX_FIRST_PERSON);
+ public void execute_invalidDeveloperIndexFilteredListNoProjects_failure() {
+ showDeveloperAtIndex(modelNoProjects, INDEX_FIRST_PERSON);
Index outOfBoundIndex = INDEX_SECOND_PERSON;
// ensures that outOfBoundIndex is still in bounds of address book list
- assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getDeveloperList().size());
+ assertTrue(outOfBoundIndex.getZeroBased() < modelNoProjects.getAddressBook().getDeveloperList().size());
- EditDeveloperCommand editDeveloperCommand = new EditDeveloperCommand(outOfBoundIndex,
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(outOfBoundIndex,
new EditDeveloperDescriptorBuilder().withName(VALID_NAME_BOB).build());
- assertCommandFailure(editDeveloperCommand, model, Messages.MESSAGE_INVALID_DEVELOPER_DISPLAYED_INDEX);
+ assertCommandFailure(editCommand, modelNoProjects, Messages.MESSAGE_INVALID_DEVELOPER_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_invalidDeveloperIndexFilteredListWithProjects_failure() {
+ showDeveloperAtIndex(modelWithProjects, INDEX_FIRST_PERSON);
+ Index outOfBoundIndex = INDEX_SECOND_PERSON;
+ // ensures that outOfBoundIndex is still in bounds of address book list
+ assertTrue(outOfBoundIndex.getZeroBased() < modelWithProjects.getAddressBook()
+ .getDeveloperList().size());
+
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(outOfBoundIndex,
+ new EditDeveloperDescriptorBuilder().withName(VALID_NAME_BOB).build());
+
+ assertCommandFailure(editCommand, modelWithProjects, Messages.MESSAGE_INVALID_DEVELOPER_DISPLAYED_INDEX);
}
@Test
@@ -192,11 +303,10 @@ public void toStringMethod() {
Index index = Index.fromOneBased(1);
EditDeveloperCommand.EditDeveloperDescriptor editDeveloperDescriptor = new EditDeveloperCommand
.EditDeveloperDescriptor();
- EditDeveloperCommand editDeveloperCommand = new EditDeveloperCommand(index, editDeveloperDescriptor);
+ EditDeveloperCommand editCommand = new EditDeveloperCommand(index, editDeveloperDescriptor);
String expected = EditDeveloperCommand.class.getCanonicalName() + "{index=" + index
+ ", editDeveloperDescriptor="
+ editDeveloperDescriptor + "}";
- assertEquals(expected, editDeveloperCommand.toString());
+ assertEquals(expected, editCommand.toString());
}
-
}
diff --git a/src/test/java/seedu/address/logic/commands/edit/EditDeveloperDescriptorTest.java b/src/test/java/seedu/address/logic/commands/edit/EditDeveloperDescriptorTest.java
index 1718f3c8185..efbdf6b06fb 100644
--- a/src/test/java/seedu/address/logic/commands/edit/EditDeveloperDescriptorTest.java
+++ b/src/test/java/seedu/address/logic/commands/edit/EditDeveloperDescriptorTest.java
@@ -70,8 +70,8 @@ public void toStringMethod() {
+ editDeveloperDescriptor.getDateJoined().orElse(null) + ", role="
+ editDeveloperDescriptor.getRole().orElse(null) + ", salary="
+ editDeveloperDescriptor.getSalary().orElse(null) + ", githubId="
- + editDeveloperDescriptor.getSalary().orElse(null) + ", rating="
- + editDeveloperDescriptor.getSalary().orElse(null) + "}";
+ + editDeveloperDescriptor.getGithubId().orElse(null) + ", rating="
+ + editDeveloperDescriptor.getRating().orElse(null) + "}";
assertEquals(expected, editDeveloperDescriptor.toString());
}
diff --git a/src/test/java/seedu/address/logic/commands/edit/EditProjectCommandTest.java b/src/test/java/seedu/address/logic/commands/edit/EditProjectCommandTest.java
new file mode 100644
index 00000000000..3ce9fa9f4ee
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/edit/EditProjectCommandTest.java
@@ -0,0 +1,170 @@
+package seedu.address.logic.commands.edit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_PROJECT1;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_PROJECT2;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_FULL_PROJECT_DEADLINE_1;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DESCRIPTION_APPLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertProjectCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.showProjectAtIndex;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PROJECT;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PROJECT;
+import static seedu.address.testutil.TypicalProjects.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.Messages;
+import seedu.address.logic.commands.ClearCommand;
+import seedu.address.model.AddressBook;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.project.Project;
+import seedu.address.testutil.EditProjectDescriptorBuilder;
+import seedu.address.testutil.ProjectBuilder;
+
+public class EditProjectCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_allFieldsSpecifiedUnfilteredList_success() {
+ Project editedProject = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ EditProjectCommand.EditProjectDescriptor descriptor = new EditProjectDescriptorBuilder(editedProject).build();
+ EditProjectCommand editProjectCommand = new EditProjectCommand(INDEX_FIRST_PROJECT, descriptor);
+
+ String expectedMessage = String.format(EditProjectCommand.MESSAGE_EDIT_PROJECT_SUCCESS,
+ Messages.format(editedProject));
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ expectedModel.setProject(model.getFilteredProjectList().get(0), editedProject);
+
+ assertProjectCommandSuccess(editProjectCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_someFieldsSpecifiedUnfilteredList_success() {
+ Index indexLastProject = Index.fromOneBased(model.getFilteredProjectList().size());
+ Project lastProject = model.getFilteredProjectList().get(indexLastProject.getZeroBased());
+
+ ProjectBuilder projectInList = new ProjectBuilder(lastProject);
+ Project editedProject = projectInList.withDescription(VALID_PROJECT_DESCRIPTION_APPLEAPP)
+ .withDeadline(VALID_FULL_PROJECT_DEADLINE_1).build();
+
+ EditProjectCommand.EditProjectDescriptor descriptor = new EditProjectDescriptorBuilder()
+ .withDescription(VALID_PROJECT_DESCRIPTION_APPLEAPP)
+ .withDeadlines(VALID_FULL_PROJECT_DEADLINE_1).build();
+ EditProjectCommand editProjectCommand = new EditProjectCommand(indexLastProject, descriptor);
+
+ String expectedMessage = String.format(EditProjectCommand.MESSAGE_EDIT_PROJECT_SUCCESS,
+ Messages.format(editedProject));
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ expectedModel.setProject(lastProject, editedProject);
+
+ assertProjectCommandSuccess(editProjectCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_noFieldSpecifiedUnfilteredList_success() {
+ EditProjectCommand editProjectCommand = new EditProjectCommand(INDEX_FIRST_PROJECT,
+ new EditProjectCommand.EditProjectDescriptor());
+ Project editedProject = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+
+ String expectedMessage = String.format(EditProjectCommand.MESSAGE_EDIT_PROJECT_SUCCESS,
+ Messages.format(editedProject));
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+
+ assertProjectCommandSuccess(editProjectCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_filteredList_success() {
+ showProjectAtIndex(model, INDEX_FIRST_PROJECT);
+
+ Project projectInFilteredList = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Project editedProject = new ProjectBuilder(projectInFilteredList)
+ .withDescription(VALID_PROJECT_DESCRIPTION_APPLEAPP).build();
+ EditProjectCommand editProjectCommand = new EditProjectCommand(INDEX_FIRST_PROJECT,
+ new EditProjectDescriptorBuilder().withDescription(VALID_PROJECT_DESCRIPTION_APPLEAPP).build());
+
+ String expectedMessage = String.format(EditProjectCommand.MESSAGE_EDIT_PROJECT_SUCCESS,
+ Messages.format(editedProject));
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ expectedModel.setProject(model.getFilteredProjectList().get(0), editedProject);
+
+ assertProjectCommandSuccess(editProjectCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_duplicateProjectDetailsUnfilteredList_success() {
+ Project firstProject = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Project secondProject = model.getFilteredProjectList().get(INDEX_SECOND_PROJECT.getZeroBased());
+ EditProjectCommand.EditProjectDescriptor descriptor = new EditProjectDescriptorBuilder(firstProject).build();
+ EditProjectCommand editProjectCommand = new EditProjectCommand(INDEX_SECOND_PROJECT, descriptor);
+
+ Project editedProject = new ProjectBuilder(secondProject)
+ .withDescription(firstProject.getProjectDescription().desc)
+ .withDeadlines(firstProject.getProjectDeadlines()).build();
+
+ String expectedMessage = String.format(EditProjectCommand.MESSAGE_EDIT_PROJECT_SUCCESS,
+ Messages.format(editedProject));
+
+ Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs());
+ expectedModel.setProject(model.getFilteredProjectList().get(1), editedProject);
+
+ assertProjectCommandSuccess(editProjectCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidProjectIndexUnfilteredList_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredProjectList().size() + 1);
+ EditProjectCommand.EditProjectDescriptor descriptor = new EditProjectDescriptorBuilder()
+ .withDescription(VALID_PROJECT_DESCRIPTION_APPLEAPP).build();
+ EditProjectCommand editProjectCommand = new EditProjectCommand(outOfBoundIndex, descriptor);
+
+ assertCommandFailure(editProjectCommand, model, Messages.MESSAGE_INVALID_PROJECT_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ final EditProjectCommand standardCommand = new EditProjectCommand(INDEX_FIRST_PROJECT, DESC_PROJECT1);
+
+ // same values -> returns true
+ EditProjectCommand.EditProjectDescriptor copyDescriptor = new EditProjectCommand.EditProjectDescriptor(
+ DESC_PROJECT1);
+ EditProjectCommand commandWithSameValues = new EditProjectCommand(INDEX_FIRST_PROJECT, copyDescriptor);
+ assertTrue(standardCommand.equals(commandWithSameValues));
+
+ // same object -> returns true
+ assertTrue(standardCommand.equals(standardCommand));
+
+ // null -> returns false
+ assertFalse(standardCommand.equals(null));
+
+ // different types -> returns false
+ assertFalse(standardCommand.equals(new ClearCommand()));
+
+ // different index -> returns false
+ assertFalse(standardCommand.equals(new EditProjectCommand(INDEX_SECOND_PROJECT, DESC_PROJECT1)));
+
+ // different descriptor -> returns false
+ assertFalse(standardCommand.equals(new EditProjectCommand(INDEX_FIRST_PROJECT, DESC_PROJECT2)));
+ }
+
+ @Test
+ public void toStringMethod() {
+ Index index = Index.fromOneBased(1);
+ EditProjectCommand.EditProjectDescriptor editProjectDescriptor = new EditProjectCommand.EditProjectDescriptor();
+ EditProjectCommand editProjectCommand = new EditProjectCommand(index, editProjectDescriptor);
+ String expected = EditProjectCommand.class.getCanonicalName() + "{index=" + index
+ + ", editProjectDescriptor=" + editProjectDescriptor + "}";
+ assertEquals(expected, editProjectCommand.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/edit/EditProjectDescriptorTest.java b/src/test/java/seedu/address/logic/commands/edit/EditProjectDescriptorTest.java
new file mode 100644
index 00000000000..2b6b0c65e05
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/edit/EditProjectDescriptorTest.java
@@ -0,0 +1,56 @@
+package seedu.address.logic.commands.edit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_PROJECT1;
+import static seedu.address.logic.commands.CommandTestUtil.DESC_PROJECT2;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_FULL_PROJECT_DEADLINE_2;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DESCRIPTION_APPLEAPP;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.testutil.EditProjectDescriptorBuilder;
+
+public class EditProjectDescriptorTest {
+
+ @Test
+ public void equals() {
+ // same values -> returns true
+ EditProjectCommand.EditProjectDescriptor descriptorWithSameValues =
+ new EditProjectCommand.EditProjectDescriptor(DESC_PROJECT1);
+ assertEquals(DESC_PROJECT1, descriptorWithSameValues);
+
+ // same object -> returns true
+ assertEquals(DESC_PROJECT1, DESC_PROJECT1);
+
+ // null -> returns false
+ assertNotEquals(null, DESC_PROJECT1);
+
+ // different types -> returns false
+ assertNotEquals(5, DESC_PROJECT1);
+
+ // different values -> returns false
+ assertNotEquals(DESC_PROJECT1, DESC_PROJECT2);
+
+ // different description -> returns false
+ EditProjectCommand.EditProjectDescriptor editedProj = new EditProjectDescriptorBuilder(DESC_PROJECT1)
+ .withDescription(VALID_PROJECT_DESCRIPTION_APPLEAPP).build();
+ assertNotEquals(DESC_PROJECT1, editedProj);
+
+ // different deadlines -> returns false
+ editedProj = new EditProjectDescriptorBuilder(DESC_PROJECT1)
+ .withDeadline(VALID_FULL_PROJECT_DEADLINE_2).build();
+ assertNotEquals(DESC_PROJECT1, editedProj);
+ }
+
+ @Test
+ public void toStringMethod() {
+ EditProjectCommand.EditProjectDescriptor editProjectDescriptor =
+ new EditProjectDescriptorBuilder().build();
+ String expected = EditProjectCommand.EditProjectDescriptor.class.getCanonicalName() + "{description="
+ + editProjectDescriptor.getDescription().orElse(null) + ", deadlines="
+ + editProjectDescriptor.getDeadlines().orElse(null) + "}";
+
+ assertEquals(expected, editProjectDescriptor.toString());
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/find/FindClientCommandTest.java b/src/test/java/seedu/address/logic/commands/find/FindClientCommandTest.java
new file mode 100644
index 00000000000..19d18650a4c
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/find/FindClientCommandTest.java
@@ -0,0 +1,131 @@
+package seedu.address.logic.commands.find;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static seedu.address.logic.commands.CommandTestUtil.assertClientCommandSuccess;
+import static seedu.address.testutil.TypicalClients.ALICE;
+import static seedu.address.testutil.TypicalClients.BENSON;
+import static seedu.address.testutil.TypicalClients.CARL;
+import static seedu.address.testutil.TypicalClients.DANIEL;
+import static seedu.address.testutil.TypicalClients.getTypicalAddressBook;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.client.NameClientContainsKeywordsPredicate;
+import seedu.address.model.client.OrganisationContainsKeywordsPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindClientCommand}.
+ */
+public class FindClientCommandTest {
+ private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private final Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ NameClientContainsKeywordsPredicate firstPredicate =
+ new NameClientContainsKeywordsPredicate(Collections.singletonList("first"));
+ NameClientContainsKeywordsPredicate secondPredicate =
+ new NameClientContainsKeywordsPredicate(Collections.singletonList("second"));
+
+ FindClientCommand findFirstCommand = new FindClientCommand(firstPredicate);
+ FindClientCommand findSecondCommand = new FindClientCommand(secondPredicate);
+
+ // same object -> returns true
+ assertEquals(findFirstCommand, findFirstCommand);
+
+ // same values -> returns true
+ FindClientCommand findFirstCommandCopy = new FindClientCommand(firstPredicate);
+ assertEquals(findFirstCommand, findFirstCommandCopy);
+
+ // different types -> returns false
+ assertNotEquals(1, findFirstCommand);
+
+ // null -> returns false
+ assertNotEquals(null, findFirstCommand);
+
+ // different client -> returns false
+ assertNotEquals(findFirstCommand, findSecondCommand);
+ }
+
+ @Test
+ public void execute_zeroKeywords_noPersonFound() {
+ String expectedMessage = "There are no clients with matching information.";
+ NameClientContainsKeywordsPredicate predicate = prepareNamePredicate("hii");
+ FindClientCommand command = new FindClientCommand(predicate);
+ expectedModel.updateFilteredClientList(predicate);
+ assertClientCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredClientList());
+ }
+
+ @Test
+ public void execute_multipleKeywords_multiplePersonsFound() {
+ String expectedMessage = "These are the 3 clients with matching information.";
+ NameClientContainsKeywordsPredicate predicate = prepareNamePredicate("Alice Benson Carl");
+ FindClientCommand command = new FindClientCommand(predicate);
+ expectedModel.updateFilteredClientList(predicate);
+ assertClientCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(ALICE, BENSON, CARL), model.getFilteredClientList());
+ }
+
+ @Test
+ public void toStringMethod() {
+ NameClientContainsKeywordsPredicate predicate =
+ new NameClientContainsKeywordsPredicate(List.of("keyword"));
+ FindClientCommand findClientCommand = new FindClientCommand(predicate);
+ String expected = FindClientCommand.class.getCanonicalName() + "{predicate=" + predicate + "}";
+ assertEquals(expected, findClientCommand.toString());
+ }
+
+ @Test
+ public void execute_caseInsensitiveSearch_clientFound() {
+ String expectedMessage = "This is the 1 client with matching information.";
+ OrganisationContainsKeywordsPredicate predicate = prepareOrganisationPredicate("Microsoft"); // using mixed case
+ FindClientCommand command = new FindClientCommand(predicate);
+ expectedModel.updateFilteredClientList(predicate);
+ assertClientCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(DANIEL), model.getFilteredClientList());
+ }
+
+ @Test
+ public void execute_partialName_clientFound() {
+ String expectedMessage = "This is the 1 client with matching information.";
+ NameClientContainsKeywordsPredicate predicate = prepareNamePredicate("rl");
+ FindClientCommand command = new FindClientCommand(predicate);
+ expectedModel.updateFilteredClientList(predicate);
+ assertClientCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(CARL), model.getFilteredClientList());
+ }
+
+ @Test
+ public void execute_noMatchingClients_noClientFound() {
+ String expectedMessage = "There are no clients with matching information.";
+ NameClientContainsKeywordsPredicate predicate = prepareNamePredicate("NonExistentClient");
+ FindClientCommand command = new FindClientCommand(predicate);
+ expectedModel.updateFilteredClientList(predicate);
+ assertClientCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredClientList());
+ }
+
+
+ /**
+ * Parses {@code userInput} into a {@code NameClientContainsKeywordsPredicate}.
+ */
+ private NameClientContainsKeywordsPredicate prepareNamePredicate(String userInput) {
+ return new NameClientContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code OrganisationClientContainsKeywordsPredicate}.
+ */
+ private OrganisationContainsKeywordsPredicate prepareOrganisationPredicate(String userInput) {
+ return new OrganisationContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/find/FindDeadlineCommandTest.java b/src/test/java/seedu/address/logic/commands/find/FindDeadlineCommandTest.java
new file mode 100644
index 00000000000..888c11409e5
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/find/FindDeadlineCommandTest.java
@@ -0,0 +1,61 @@
+package seedu.address.logic.commands.find;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.logic.commands.CommandTestUtil.assertProjectCommandSuccess;
+import static seedu.address.testutil.TypicalProjects.PROJECT_A;
+import static seedu.address.testutil.TypicalProjects.PROJECT_A_NO_SPACING;
+import static seedu.address.testutil.TypicalProjects.PROJECT_B;
+import static seedu.address.testutil.TypicalProjects.PROJECT_C;
+import static seedu.address.testutil.TypicalProjects.getTypicalAddressBook;
+
+import java.util.Arrays;
+import java.util.function.Predicate;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.commons.Date;
+import seedu.address.model.project.Deadline;
+import seedu.address.model.project.Priority;
+
+public class FindDeadlineCommandTest {
+ private Model model;
+
+ @BeforeEach
+ public void setUp() {
+ model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ }
+
+ @Test
+ public void execute_zeroKeywords_noDeadlineFound() throws ParseException {
+ //String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
+ String expectedMessage = "There are no deadlines with matching information.";
+ Predicate finalPredicate = deadline -> true;
+ String dateKeywords = "10-10-2000";
+ Date input = ParserUtil.parseDateDeadline(dateKeywords);
+ finalPredicate =
+ finalPredicate.and(d -> !d.getDate().value.after(input.value));
+ FindDeadlineCommand command = new FindDeadlineCommand(finalPredicate);
+ model.updateFilteredProjectDeadlineList(finalPredicate);
+ assertProjectCommandSuccess(command, model, expectedMessage, model);
+ }
+
+ @Test
+ public void execute_multipleKeywords_onePersonsFound() {
+ //String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3);
+ String expectedMessage = "This is the 1 deadline with matching information.";
+ Predicate finalPredicate = deadline -> true;
+ finalPredicate = finalPredicate.and(d -> d.getPriority().equals(Priority.HIGH));
+ FindDeadlineCommand command = new FindDeadlineCommand(finalPredicate);
+ model.updateFilteredProjectDeadlineList(finalPredicate);
+ assertProjectCommandSuccess(command, model, expectedMessage, model);
+ assertEquals(Arrays.asList(PROJECT_A, PROJECT_B, PROJECT_C, PROJECT_A_NO_SPACING),
+ model.getFilteredProjectList());
+ }
+
+}
diff --git a/src/test/java/seedu/address/logic/commands/find/FindDeveloperCommandTest.java b/src/test/java/seedu/address/logic/commands/find/FindDeveloperCommandTest.java
index aed7b9d9966..75142943477 100644
--- a/src/test/java/seedu/address/logic/commands/find/FindDeveloperCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/find/FindDeveloperCommandTest.java
@@ -84,6 +84,39 @@ public void toStringMethod() {
assertEquals(expected, findDeveloperCommand.toString());
}
+ @Test
+ public void execute_caseInsensitiveSearch_personFound() {
+ String expectedMessage = "This is the 1 developer with matching information.";
+ NameDeveloperContainsKeywordsPredicate predicate = preparePredicate("ElLe"); // using mixed case
+ FindDeveloperCommand command = new FindDeveloperCommand(predicate);
+ expectedModel.updateFilteredDeveloperList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(ELLE), model.getFilteredDeveloperList());
+ }
+
+ @Test
+ public void execute_partialName_personFound() {
+ String expectedMessage = "This is the 1 developer with matching information.";
+ NameDeveloperContainsKeywordsPredicate predicate = preparePredicate("Ell");
+ FindDeveloperCommand command = new FindDeveloperCommand(predicate);
+ expectedModel.updateFilteredDeveloperList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(ELLE), model.getFilteredDeveloperList());
+ }
+
+ @Test
+ public void execute_noMatchingPersons_noPersonFound() {
+ String expectedMessage = "There are no developers with matching information.";
+ NameDeveloperContainsKeywordsPredicate predicate = preparePredicate("NonExistentDeveloper");
+ FindDeveloperCommand command = new FindDeveloperCommand(predicate);
+ expectedModel.updateFilteredDeveloperList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredDeveloperList());
+ }
+
+
+
+
/**
* Parses {@code userInput} into a {@code NameContainsKeywordsPredicate}.
*/
diff --git a/src/test/java/seedu/address/logic/commands/find/FindProjectCommandTest.java b/src/test/java/seedu/address/logic/commands/find/FindProjectCommandTest.java
new file mode 100644
index 00000000000..9efdd89da39
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/find/FindProjectCommandTest.java
@@ -0,0 +1,124 @@
+package seedu.address.logic.commands.find;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static seedu.address.logic.commands.CommandTestUtil.assertProjectCommandSuccess;
+import static seedu.address.testutil.TypicalProjects.PROJECT_A;
+import static seedu.address.testutil.TypicalProjects.PROJECT_A_NO_SPACING;
+import static seedu.address.testutil.TypicalProjects.PROJECT_B;
+import static seedu.address.testutil.TypicalProjects.PROJECT_C;
+import static seedu.address.testutil.TypicalProjects.getTypicalAddressBook;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.project.ProjectNameContainsKeywordsPredicate;
+
+/**
+ * Contains integration tests (interaction with the Model) for {@code FindProjectCommand}.
+ */
+public class FindProjectCommandTest {
+ private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private final Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ ProjectNameContainsKeywordsPredicate firstPredicate =
+ new ProjectNameContainsKeywordsPredicate(Collections.singletonList("first"));
+ ProjectNameContainsKeywordsPredicate secondPredicate =
+ new ProjectNameContainsKeywordsPredicate(Collections.singletonList("second"));
+
+ FindProjectCommand findFirstCommand = new FindProjectCommand(firstPredicate);
+ FindProjectCommand findSecondCommand = new FindProjectCommand(secondPredicate);
+
+ // same object -> returns true
+ assertEquals(findFirstCommand, findFirstCommand);
+
+ // same values -> returns true
+ FindProjectCommand findFirstCommandCopy = new FindProjectCommand(firstPredicate);
+ assertEquals(findFirstCommand, findFirstCommandCopy);
+
+ // different types -> returns false
+ assertNotEquals(1, findFirstCommand);
+
+ // null -> returns false
+ assertNotEquals(null, findFirstCommand);
+
+ // different project -> returns false
+ assertNotEquals(findFirstCommand, findSecondCommand);
+ }
+
+ @Test
+ public void execute_zeroKeywords_noProjectFound() {
+ String expectedMessage = "There are no projects with matching information.";
+ ProjectNameContainsKeywordsPredicate predicate = preparePredicate("hii");
+ FindProjectCommand command = new FindProjectCommand(predicate);
+ expectedModel.updateFilteredProjectList(predicate);
+ assertProjectCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredProjectList());
+ }
+
+ @Test
+ public void execute_multipleKeywords_multipleProjectsFound() {
+ String expectedMessage = "These are the 4 projects with matching information.";
+ ProjectNameContainsKeywordsPredicate predicate = preparePredicate("Project A B C");
+ FindProjectCommand command = new FindProjectCommand(predicate);
+ expectedModel.updateFilteredProjectList(predicate);
+ assertProjectCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(PROJECT_A, PROJECT_B, PROJECT_C, PROJECT_A_NO_SPACING),
+ model.getFilteredProjectList());
+ }
+
+ @Test
+ public void toStringMethod() {
+ ProjectNameContainsKeywordsPredicate predicate =
+ new ProjectNameContainsKeywordsPredicate(List.of("keyword"));
+ FindProjectCommand findProjectCommand = new FindProjectCommand(predicate);
+ String expected = FindProjectCommand.class.getCanonicalName() + "{predicate=" + predicate + "}";
+ assertEquals(expected, findProjectCommand.toString());
+ }
+
+ @Test
+ public void execute_caseInsensitiveSearch_projectFound() {
+ String expectedMessage = "These are the 2 projects with matching information.";
+ ProjectNameContainsKeywordsPredicate predicate = preparePredicate("a"); // using mixed case
+ FindProjectCommand command = new FindProjectCommand(predicate);
+ expectedModel.updateFilteredProjectList(predicate);
+ assertProjectCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(PROJECT_A, PROJECT_A_NO_SPACING), model.getFilteredProjectList());
+ }
+
+
+ @Test
+ public void execute_partialName_projectFound() {
+ String expectedMessage = "This is the 1 project with matching information.";
+ ProjectNameContainsKeywordsPredicate predicate = preparePredicate("jecta");
+ FindProjectCommand command = new FindProjectCommand(predicate);
+ expectedModel.updateFilteredProjectList(predicate);
+ assertProjectCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Arrays.asList(PROJECT_A_NO_SPACING), model.getFilteredProjectList());
+ }
+
+ @Test
+ public void execute_noMatchingProjects_noProjectFound() {
+ String expectedMessage = "There are no projects with matching information.";
+ ProjectNameContainsKeywordsPredicate predicate = preparePredicate("NonExistentProject");
+ FindProjectCommand command = new FindProjectCommand(predicate);
+ expectedModel.updateFilteredProjectList(predicate);
+ assertProjectCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredProjectList());
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code ProjectNameContainsKeywordsPredicate}.
+ */
+ private ProjectNameContainsKeywordsPredicate preparePredicate(String userInput) {
+ return new ProjectNameContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/list/ListClientCommandTest.java b/src/test/java/seedu/address/logic/commands/list/ListClientCommandTest.java
index ee232924aa2..0b310e03f6c 100644
--- a/src/test/java/seedu/address/logic/commands/list/ListClientCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/list/ListClientCommandTest.java
@@ -1,6 +1,6 @@
package seedu.address.logic.commands.list;
-import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.assertClientCommandSuccess;
import static seedu.address.logic.commands.CommandTestUtil.showClientAtIndex;
import static seedu.address.testutil.TypicalClients.getTypicalAddressBook;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
@@ -28,12 +28,12 @@ public void setUp() {
@Test
public void execute_listIsNotFiltered_showsSameList() {
- assertCommandSuccess(new ListClientCommand(), model, ListClientCommand.MESSAGE_SUCCESS, expectedModel);
+ assertClientCommandSuccess(new ListClientCommand(), model, ListClientCommand.MESSAGE_SUCCESS, expectedModel);
}
@Test
public void execute_listIsFiltered_showsEverything() {
showClientAtIndex(model, INDEX_FIRST_PERSON);
- assertCommandSuccess(new ListClientCommand(), model, ListClientCommand.MESSAGE_SUCCESS, expectedModel);
+ assertClientCommandSuccess(new ListClientCommand(), model, ListClientCommand.MESSAGE_SUCCESS, expectedModel);
}
}
diff --git a/src/test/java/seedu/address/logic/commands/list/ListProjectCommandTest.java b/src/test/java/seedu/address/logic/commands/list/ListProjectCommandTest.java
index 36cd31b1c13..d7bfa327096 100644
--- a/src/test/java/seedu/address/logic/commands/list/ListProjectCommandTest.java
+++ b/src/test/java/seedu/address/logic/commands/list/ListProjectCommandTest.java
@@ -1,4 +1,43 @@
package seedu.address.logic.commands.list;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static seedu.address.testutil.Assert.assertThrows;
+import static seedu.address.testutil.TypicalProjects.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+
public class ListProjectCommandTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_listIsNotFiltered_showsSameList() {
+ ListProjectCommand listProjectCommand = new ListProjectCommand();
+ CommandResult commandResult = listProjectCommand.execute(model);
+
+ assertEquals(ListProjectCommand.MESSAGE_SUCCESS, commandResult.getFeedbackToUser());
+ assertEquals(model.getAddressBook().getProjectList(), model.getFilteredProjectList());
+ }
+
+ @Test
+ public void execute_listIsFiltered_showsEverything() {
+ // Assume the list is filtered by some predicate
+ model.updateFilteredProjectList(project -> project.getProjectDeadlines().equals("2023-01-01"));
+ ListProjectCommand listProjectCommand = new ListProjectCommand();
+ CommandResult commandResult = listProjectCommand.execute(model);
+
+ assertEquals(ListProjectCommand.MESSAGE_SUCCESS, commandResult.getFeedbackToUser());
+ assertEquals(model.getAddressBook().getProjectList(), model.getFilteredProjectList());
+ }
+
+ @Test
+ public void execute_modelIsNull_throwsAssertionError() {
+ ListProjectCommand listProjectCommand = new ListProjectCommand();
+ assertThrows(AssertionError.class, () -> listProjectCommand.execute(null));
+ }
}
diff --git a/src/test/java/seedu/address/logic/commands/mark/MarkDeadlineCommandTest.java b/src/test/java/seedu/address/logic/commands/mark/MarkDeadlineCommandTest.java
new file mode 100644
index 00000000000..15273b4d675
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/mark/MarkDeadlineCommandTest.java
@@ -0,0 +1,123 @@
+package seedu.address.logic.commands.mark;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertProjectCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.showProjectAtIndex;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PROJECT;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PROJECT_AND_DEADLINE;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PROJECT;
+import static seedu.address.testutil.TypicalProjects.getTypicalAddressBook;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.Messages;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.project.Project;
+import seedu.address.testutil.ProjectBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for MarkDeadlineCommand.
+ */
+public class MarkDeadlineCommandTest {
+
+ private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexesUnfilteredList_success() {
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index projectIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(0);
+ Index deadlineIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(1);
+ List markedDeadline = projectToEdit.markDeadlineStringRep(deadlineIndex.getOneBased());
+
+ MarkDeadlineCommand markDeadlineCommand = new MarkDeadlineCommand(projectIndex, deadlineIndex);
+
+ ProjectBuilder projectInList = new ProjectBuilder(projectToEdit);
+ Project editedProject = projectInList.withDeadlinesString(markedDeadline).build();
+
+ String expectedMessage = MarkDeadlineCommand.MESSAGE_SUCCESS;
+
+ ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ expectedModel.setProject(projectToEdit, editedProject);
+
+ assertProjectCommandSuccess(markDeadlineCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidProjectIndexUnfilteredList_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredProjectList().size() + 1);
+ MarkDeadlineCommand markDeadlineCommand = new MarkDeadlineCommand(outOfBoundIndex, INDEX_FIRST_PROJECT);
+
+ assertCommandFailure(markDeadlineCommand, model, Messages.MESSAGE_INVALID_PROJECT_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_invalidDeadlineIndexUnfilteredList_failure() {
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index outOfBoundIndex = Index.fromOneBased(projectToEdit.deadlineListSize() + 1);
+ MarkDeadlineCommand markDeadlineCommand = new MarkDeadlineCommand(INDEX_FIRST_PROJECT, outOfBoundIndex);
+
+ assertCommandFailure(markDeadlineCommand, model, Messages.MESSAGE_INVALID_DEADLINE_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ MarkDeadlineCommand markFirstCommand = new MarkDeadlineCommand(INDEX_FIRST_PROJECT, INDEX_FIRST_PROJECT);
+ MarkDeadlineCommand markSecondCommand = new MarkDeadlineCommand(INDEX_SECOND_PROJECT, INDEX_SECOND_PROJECT);
+
+ // same object -> returns true
+ assertTrue(markFirstCommand.equals(markFirstCommand));
+
+ // same values -> returns true
+ MarkDeadlineCommand markFirstCommandCopy = new MarkDeadlineCommand(INDEX_FIRST_PROJECT, INDEX_FIRST_PROJECT);
+ assertTrue(markFirstCommand.equals(markFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(markFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(markFirstCommand.equals(null));
+
+ // different project index -> returns false
+ assertFalse(markFirstCommand.equals(markSecondCommand));
+ }
+
+ @Test
+ public void execute_validIndexesFilteredList_success() {
+ showProjectAtIndex(model, INDEX_FIRST_PROJECT);
+
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index projectIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(0);
+ Index deadlineIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(1);
+ List markedDeadline = projectToEdit.markDeadlineStringRep(deadlineIndex.getOneBased());
+
+ MarkDeadlineCommand markDeadlineCommand = new MarkDeadlineCommand(projectIndex, deadlineIndex);
+
+ ProjectBuilder projectInList = new ProjectBuilder(projectToEdit);
+ Project editedProject = projectInList.withDeadlinesString(markedDeadline).build();
+
+ String expectedMessage = MarkDeadlineCommand.MESSAGE_SUCCESS;
+
+ ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ expectedModel.setProject(projectToEdit, editedProject);
+
+ assertProjectCommandSuccess(markDeadlineCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidDeadlineIndexFilteredList_failure() {
+ showProjectAtIndex(model, INDEX_FIRST_PROJECT);
+
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index outOfBoundIndex = Index.fromOneBased(projectToEdit.deadlineListSize() + 1);
+ MarkDeadlineCommand markDeadlineCommand = new MarkDeadlineCommand(INDEX_FIRST_PROJECT, outOfBoundIndex);
+
+ assertCommandFailure(markDeadlineCommand, model, Messages.MESSAGE_INVALID_DEADLINE_DISPLAYED_INDEX);
+ }
+}
diff --git a/src/test/java/seedu/address/logic/commands/mark/UnmarkDeadlineCommandTest.java b/src/test/java/seedu/address/logic/commands/mark/UnmarkDeadlineCommandTest.java
new file mode 100644
index 00000000000..77a4ab73701
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/mark/UnmarkDeadlineCommandTest.java
@@ -0,0 +1,125 @@
+package seedu.address.logic.commands.mark;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure;
+import static seedu.address.logic.commands.CommandTestUtil.assertProjectCommandSuccess;
+import static seedu.address.logic.commands.CommandTestUtil.showProjectAtIndex;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PROJECT;
+import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PROJECT_AND_DEADLINE;
+import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PROJECT;
+import static seedu.address.testutil.TypicalProjects.getTypicalAddressBook;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.Messages;
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.project.Project;
+import seedu.address.testutil.ProjectBuilder;
+
+/**
+ * Contains integration tests (interaction with the Model) and unit tests for UnmarkDeadlineCommand.
+ */
+public class UnmarkDeadlineCommandTest {
+
+ private final Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void execute_validIndexesUnfilteredList_success() {
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index projectIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(0);
+ Index deadlineIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(1);
+ List markedDeadline = projectToEdit.markDeadlineStringRep(deadlineIndex.getOneBased());
+
+ UnmarkDeadlineCommand unmarkDeadlineCommand = new UnmarkDeadlineCommand(projectIndex, deadlineIndex);
+
+ ProjectBuilder projectInList = new ProjectBuilder(projectToEdit);
+ Project editedProject = projectInList.withDeadlinesString(markedDeadline).build();
+
+ String expectedMessage = UnmarkDeadlineCommand.MESSAGE_SUCCESS;
+
+ ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ expectedModel.setProject(projectToEdit, editedProject);
+
+ assertProjectCommandSuccess(unmarkDeadlineCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidProjectIndexUnfilteredList_failure() {
+ Index outOfBoundIndex = Index.fromOneBased(model.getFilteredProjectList().size() + 1);
+ UnmarkDeadlineCommand unmarkDeadlineCommand = new UnmarkDeadlineCommand(outOfBoundIndex, INDEX_FIRST_PROJECT);
+
+ assertCommandFailure(unmarkDeadlineCommand, model, Messages.MESSAGE_INVALID_PROJECT_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void execute_invalidDeadlineIndexUnfilteredList_failure() {
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index outOfBoundIndex = Index.fromOneBased(projectToEdit.deadlineListSize() + 1);
+ UnmarkDeadlineCommand unmarkDeadlineCommand = new UnmarkDeadlineCommand(INDEX_FIRST_PROJECT, outOfBoundIndex);
+
+ assertCommandFailure(unmarkDeadlineCommand, model, Messages.MESSAGE_INVALID_DEADLINE_DISPLAYED_INDEX);
+ }
+
+ @Test
+ public void equals() {
+ UnmarkDeadlineCommand unmarkFirstCommand = new UnmarkDeadlineCommand(INDEX_FIRST_PROJECT, INDEX_FIRST_PROJECT);
+ UnmarkDeadlineCommand unmarkSecondCommand =
+ new UnmarkDeadlineCommand(INDEX_SECOND_PROJECT, INDEX_SECOND_PROJECT);
+
+ // same object -> returns true
+ assertTrue(unmarkFirstCommand.equals(unmarkFirstCommand));
+
+ // same values -> returns true
+ UnmarkDeadlineCommand unmarkFirstCommandCopy =
+ new UnmarkDeadlineCommand(INDEX_FIRST_PROJECT, INDEX_FIRST_PROJECT);
+ assertTrue(unmarkFirstCommand.equals(unmarkFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(unmarkFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(unmarkFirstCommand.equals(null));
+
+ // different project index -> returns false
+ assertFalse(unmarkFirstCommand.equals(unmarkSecondCommand));
+ }
+
+ @Test
+ public void execute_validIndexesFilteredList_success() {
+ showProjectAtIndex(model, INDEX_FIRST_PROJECT);
+
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index projectIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(0);
+ Index deadlineIndex = INDEX_FIRST_PROJECT_AND_DEADLINE.get(1);
+ List markedDeadline = projectToEdit.markDeadlineStringRep(deadlineIndex.getOneBased());
+
+ UnmarkDeadlineCommand unmarkDeadlineCommand = new UnmarkDeadlineCommand(projectIndex, deadlineIndex);
+
+ ProjectBuilder projectInList = new ProjectBuilder(projectToEdit);
+ Project editedProject = projectInList.withDeadlinesString(markedDeadline).build();
+
+ String expectedMessage = UnmarkDeadlineCommand.MESSAGE_SUCCESS;
+
+ ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs());
+ expectedModel.setProject(projectToEdit, editedProject);
+
+ assertProjectCommandSuccess(unmarkDeadlineCommand, model, expectedMessage, expectedModel);
+ }
+
+ @Test
+ public void execute_invalidDeadlineIndexFilteredList_failure() {
+ showProjectAtIndex(model, INDEX_FIRST_PROJECT);
+
+ Project projectToEdit = model.getFilteredProjectList().get(INDEX_FIRST_PROJECT.getZeroBased());
+ Index outOfBoundIndex = Index.fromOneBased(projectToEdit.deadlineListSize() + 1);
+ UnmarkDeadlineCommand unmarkDeadlineCommand = new UnmarkDeadlineCommand(INDEX_FIRST_PROJECT, outOfBoundIndex);
+
+ assertCommandFailure(unmarkDeadlineCommand, model, Messages.MESSAGE_INVALID_DEADLINE_DISPLAYED_INDEX);
+ }
+}
diff --git a/src/test/java/seedu/address/model/VersionedAddressBookTest.java b/src/test/java/seedu/address/model/VersionedAddressBookTest.java
new file mode 100644
index 00000000000..0be58d4a166
--- /dev/null
+++ b/src/test/java/seedu/address/model/VersionedAddressBookTest.java
@@ -0,0 +1,85 @@
+package seedu.address.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.testutil.TypicalClients.getTypicalAddressBook;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.TabIndex;
+import seedu.address.logic.commands.exceptions.CommandException;
+
+
+public class VersionedAddressBookTest {
+
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private VersionedAddressBook versionedAddressBook = new VersionedAddressBook(model.getAddressBook());
+
+ @Test
+ public void commit_validModelState_successfullyCommits() {
+ versionedAddressBook.commit(model, "Committing state", TabIndex.Client);
+
+ // Ensure that the model's address book is updated
+ assertEquals(model.getAddressBook(), versionedAddressBook.getCurrentState(1));
+
+ // Ensure that the state pointer has moved to the latest state
+ assertEquals(1, versionedAddressBook.getCurrentStatePointer());
+ }
+
+ @Test
+ public void undo_validModelState_successfullyUndoes() throws CommandException {
+ versionedAddressBook.commit(model, "Committing state", TabIndex.Client);
+ versionedAddressBook.undo(model);
+
+ // Ensure that the model's address book is updated to the previous state
+ assertEquals(model.getAddressBook(), versionedAddressBook.getCurrentState(1));
+
+ // Ensure that the state pointer has moved to the previous state
+ assertEquals(0, versionedAddressBook.getCurrentStatePointer());
+
+ // Ensure that the success message and tab index are retrieved
+ assertEquals("Committing state", versionedAddressBook.getPreviousMessage());
+ assertEquals(TabIndex.Client, versionedAddressBook.getPreviousTabIndex());
+ }
+
+ @Test
+ public void redo_validModelState_successfullyRedoes() throws CommandException {
+ versionedAddressBook.commit(model, "Committing state", TabIndex.Client);
+ versionedAddressBook.undo(model);
+ versionedAddressBook.redo(model);
+
+ // Ensure that the model's address book is updated to the next state
+ assertEquals(model.getAddressBook(), versionedAddressBook.getCurrentState(1));
+
+ // Ensure that the state pointer has moved to the next state
+ assertEquals(1, versionedAddressBook.getCurrentStatePointer());
+
+ // Ensure that the success message and tab index are retrieved
+ assertEquals("Committing state", versionedAddressBook.getPreviousMessageForRedo());
+ assertEquals(TabIndex.Client, versionedAddressBook.getPreviousTabIndexForRedo());
+ }
+
+ @Test
+ public void canUndo_noStatesToUndo_returnsFalse() {
+ assertFalse(versionedAddressBook.canUndo());
+ }
+
+ @Test
+ public void canRedo_noStatesToRedo_returnsFalse() {
+ assertFalse(versionedAddressBook.canRedo());
+ }
+
+ @Test
+ public void canUndo_hasStatesToUndo_returnsTrue() throws CommandException {
+ versionedAddressBook.commit(model, "Committing state", TabIndex.Client);
+ assertTrue(versionedAddressBook.canUndo());
+ }
+
+ @Test
+ public void canRedo_hasStatesToRedo_returnsTrue() throws CommandException {
+ versionedAddressBook.commit(model, "Committing state", TabIndex.Client);
+ versionedAddressBook.undo(model);
+ assertTrue(versionedAddressBook.canRedo());
+ }
+}
diff --git a/src/test/java/seedu/address/model/project/ProjectTest.java b/src/test/java/seedu/address/model/project/ProjectTest.java
index aa0f14b86e8..18c85e04f11 100644
--- a/src/test/java/seedu/address/model/project/ProjectTest.java
+++ b/src/test/java/seedu/address/model/project/ProjectTest.java
@@ -24,5 +24,4 @@ public void isValidProjectName() {
assertThrows(NullPointerException.class, () -> Project.isValidProjectName(null));
}
*/
-
}
diff --git a/src/test/java/seedu/address/testutil/DeveloperBuilder.java b/src/test/java/seedu/address/testutil/DeveloperBuilder.java
index ff49201b755..5e109d11da0 100644
--- a/src/test/java/seedu/address/testutil/DeveloperBuilder.java
+++ b/src/test/java/seedu/address/testutil/DeveloperBuilder.java
@@ -79,25 +79,25 @@ public DeveloperBuilder withName(String name) {
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code Projects} of the {@code Developer} that we are building. */
public DeveloperBuilder withProjects(String... projects) {
this.projects = SampleDataUtil.getProjectSet(projects);
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code GithubId} of the {@code Developer} that we are building. */
public DeveloperBuilder withGithubId(String githubId) {
this.githubId = new GithubId(githubId);
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code Rating} of the {@code Developer} that we are building. */
public DeveloperBuilder withRating(String rating) {
this.rating = new Rating(rating);
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code Address} of the {@code Developer} that we are building. */
public DeveloperBuilder withAddress(String address) {
this.address = new Address(address);
return this;
@@ -109,31 +109,31 @@ public DeveloperBuilder withPhone(String phone) {
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code Email} of the {@code Developer} that we are building. */
public DeveloperBuilder withEmail(String email) {
this.email = new Email(email);
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code DateJoined} of the {@code Developer} that we are building. */
public DeveloperBuilder withDateJoined(String dateJoined) {
this.dateJoined = new Date(dateJoined, false);
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code Role} of the {@code Developer} that we are building. */
public DeveloperBuilder withRole(String role) {
this.role = new DeveloperRoles(role);
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Sets the {@code Salary} of the {@code Developer} that we are building. */
public DeveloperBuilder withSalary(String salary) {
this.salary = new Salary(salary);
return this;
}
- /** Sets the {@code Phone} of the {@code Developer} that we are building. */
+ /** Builds the developer. */
public Developer build() {
return new Developer(name, phone, email, address, role, projects, salary, dateJoined, githubId, rating);
}
diff --git a/src/test/java/seedu/address/testutil/EditClientDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditClientDescriptorBuilder.java
index 31c3bb2d1ce..1bd28c4e6a4 100644
--- a/src/test/java/seedu/address/testutil/EditClientDescriptorBuilder.java
+++ b/src/test/java/seedu/address/testutil/EditClientDescriptorBuilder.java
@@ -29,7 +29,7 @@ public EditClientDescriptorBuilder(EditClientCommand.EditClientDescriptor descri
}
/**
- * Returns an {@code EditPersonDescriptor} with fields containing {@code developer}'s details
+ * Returns an {@code EditClientDescriptor} with fields containing {@code client}'s details.
*/
public EditClientDescriptorBuilder(Client client) {
descriptor = new EditClientCommand.EditClientDescriptor();
diff --git a/src/test/java/seedu/address/testutil/EditProjectDescriptorBuilder.java b/src/test/java/seedu/address/testutil/EditProjectDescriptorBuilder.java
new file mode 100644
index 00000000000..eb233dd93f6
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/EditProjectDescriptorBuilder.java
@@ -0,0 +1,73 @@
+package seedu.address.testutil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.logic.commands.edit.EditProjectCommand;
+import seedu.address.model.project.Deadline;
+import seedu.address.model.project.Description;
+import seedu.address.model.project.Project;
+
+/**
+ * A utility class to help with building EditProjectDescriptor objects.
+ */
+public class EditProjectDescriptorBuilder {
+
+ private final EditProjectCommand.EditProjectDescriptor descriptor;
+
+ public EditProjectDescriptorBuilder() {
+ descriptor = new EditProjectCommand.EditProjectDescriptor();
+ }
+
+ public EditProjectDescriptorBuilder(EditProjectCommand.EditProjectDescriptor descriptor) {
+ this.descriptor = new EditProjectCommand.EditProjectDescriptor(descriptor);
+ }
+
+ /**
+ * Returns an {@code EditProjectDescriptor} with fields containing {@code project}'s details
+ */
+ public EditProjectDescriptorBuilder(Project project) {
+ descriptor = new EditProjectCommand.EditProjectDescriptor();
+ descriptor.setDescription(project.getProjectDescription());
+ descriptor.setDeadlines(project.getProjectDeadlines());
+ }
+
+ /**
+ * Sets the {@code Description} of the {@code EditProjectDescriptor} that we are building.
+ */
+ public EditProjectDescriptorBuilder withDescription(String description) {
+ descriptor.setDescription(new Description(description));
+ return this;
+ }
+
+ /**
+ * Sets the {@code Deadlines} of the {@code EditProjectDescriptor} that we are building.
+ */
+ public EditProjectDescriptorBuilder withDeadlines(String... deadlines) {
+ List deadlineList = new ArrayList<>();
+ int index = 1;
+ for (String deadline : deadlines) {
+ deadlineList.add(new Deadline(deadline, index));
+ index += 1;
+ }
+ descriptor.setDeadlines(deadlineList);
+ return this;
+ }
+
+ /**
+ * Sets the {@code Deadline} of the {@code EditProjectDescriptor} that we are building.
+ */
+ public EditProjectDescriptorBuilder withDeadline(String deadline) {
+ List deadlineList = new ArrayList<>();
+ deadlineList.add(new Deadline(deadline, 1));
+ descriptor.setDeadlines(deadlineList);
+ return this;
+ }
+
+ /**
+ * Builds and returns the EditProjectDescriptor.
+ */
+ public EditProjectCommand.EditProjectDescriptor build() {
+ return descriptor;
+ }
+}
diff --git a/src/test/java/seedu/address/testutil/ProjectBuilder.java b/src/test/java/seedu/address/testutil/ProjectBuilder.java
new file mode 100644
index 00000000000..34fa9b563de
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/ProjectBuilder.java
@@ -0,0 +1,88 @@
+package seedu.address.testutil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.model.commons.Name;
+import seedu.address.model.project.Deadline;
+import seedu.address.model.project.Description;
+import seedu.address.model.project.Project;
+
+/**
+ * A utility class to help with building Project objects.
+ */
+public class ProjectBuilder {
+ public static final String DEFAULT_NAME = "AppleApp";
+ public static final String DEFAULT_DESCRIPTION = "Developing the AppleApp";
+ public static final String DEFAULT_DEADLINE = "31-12-2019,Develop front end interface,HIGH,0";
+
+ private Name name;
+ private Description description;
+ private List deadlineList;
+
+ /**
+ * Creates a {@code ProjectBuilder} with the default details.
+ */
+ public ProjectBuilder() {
+ name = new Name(DEFAULT_NAME);
+ description = new Description(DEFAULT_DESCRIPTION);
+ deadlineList = new ArrayList<>();
+ deadlineList.add(new Deadline(DEFAULT_DEADLINE, 1));
+ }
+
+ /**
+ * Initializes the ProjectBuilder with the data of {@code projectToCopy}.
+ * @param projectToCopy
+ */
+ public ProjectBuilder(Project projectToCopy) {
+ name = projectToCopy.getProjectName();
+ description = projectToCopy.getProjectDescription();
+ deadlineList = projectToCopy.getProjectDeadlines();
+ }
+
+ /** Sets the {@code Name} of the {@code Project} that we are building. */
+ public ProjectBuilder withName(String name) {
+ this.name = new Name(name);
+ return this;
+ }
+
+ /** Sets the {@code Description} of the {@code Project} that we are building. */
+ public ProjectBuilder withDescription(String description) {
+ this.description = new Description(description);
+ return this;
+ }
+
+ /** Sets the {@code Deadline} of the {@code Project} that we are building. */
+ public ProjectBuilder withDeadline(String deadline) {
+ this.deadlineList = new ArrayList<>();
+ this.deadlineList.add(new Deadline(deadline, 1));
+ return this;
+ }
+
+ /** Sets the {@code Deadline} of the {@code Project} that we are building. */
+ public ProjectBuilder withDeadlines(List deadlines) {
+ this.deadlineList = new ArrayList<>();
+ int index = 1;
+ for (Deadline d : deadlines) {
+ this.deadlineList.add(new Deadline(d.getStringRepresentation(), index));
+ index += 1;
+ }
+ return this;
+ }
+
+ /** Sets the {@code Deadline} of the {@code Project} that we are building. */
+ public ProjectBuilder withDeadlinesString(List deadlines) {
+ this.deadlineList = new ArrayList<>();
+ int index = 1;
+ for (String d : deadlines) {
+ this.deadlineList.add(new Deadline(d, index));
+ index += 1;
+ }
+ return this;
+ }
+
+ /** Builds a Project object. */
+ public Project build() {
+ return new Project(name, description, deadlineList);
+ }
+}
diff --git a/src/test/java/seedu/address/testutil/TypicalClients.java b/src/test/java/seedu/address/testutil/TypicalClients.java
index fca73480717..b5f6790e4a9 100644
--- a/src/test/java/seedu/address/testutil/TypicalClients.java
+++ b/src/test/java/seedu/address/testutil/TypicalClients.java
@@ -14,6 +14,7 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_2_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_2_BOB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_ROLE_AMY;
+import static seedu.address.testutil.TypicalProjects.getTypicalProjects;
import java.util.ArrayList;
import java.util.Arrays;
@@ -21,6 +22,7 @@
import seedu.address.model.AddressBook;
import seedu.address.model.client.Client;
+import seedu.address.model.project.Project;
/**
* A utility class containing a list of {@code Developer} objects to be used in tests.
@@ -79,7 +81,7 @@ private TypicalClients() {
} // prevents instantiation
/**
- * Returns an {@code AddressBook} with all the typical persons.
+ * Returns an {@code AddressBook} with all the typical clients.
*/
public static AddressBook getTypicalAddressBook() {
AddressBook ab = new AddressBook();
@@ -89,6 +91,20 @@ public static AddressBook getTypicalAddressBook() {
return ab;
}
+ /**
+ * Returns an {@code AddressBook} with all the typical clients integrated with projects.
+ */
+ public static AddressBook getTypicalAddressBookWithProjects() {
+ AddressBook ab = new AddressBook();
+ for (Client client: getTypicalClients()) {
+ ab.addClient(client);
+ }
+ for (Project project : getTypicalProjects()) {
+ ab.addProject(project);
+ }
+ return ab;
+ }
+
public static List getTypicalClients() {
return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE));
}
diff --git a/src/test/java/seedu/address/testutil/TypicalDevelopers.java b/src/test/java/seedu/address/testutil/TypicalDevelopers.java
index 3975be53698..a319f5388f4 100644
--- a/src/test/java/seedu/address/testutil/TypicalDevelopers.java
+++ b/src/test/java/seedu/address/testutil/TypicalDevelopers.java
@@ -16,6 +16,7 @@
import static seedu.address.logic.commands.CommandTestUtil.VALID_RATING_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_ROLE_AMY;
import static seedu.address.logic.commands.CommandTestUtil.VALID_SALARY_AMY;
+import static seedu.address.testutil.TypicalProjects.getTypicalProjects;
import java.util.ArrayList;
import java.util.Arrays;
@@ -23,6 +24,7 @@
import seedu.address.model.AddressBook;
import seedu.address.model.developer.Developer;
+import seedu.address.model.project.Project;
/**
* A utility class containing a list of {@code Developer} objects to be used in tests.
@@ -84,13 +86,27 @@ private TypicalDevelopers() {
*/
public static AddressBook getTypicalAddressBook() {
AddressBook ab = new AddressBook();
- for (Developer developer : getTypicalPersons()) {
+ for (Developer developer : getTypicalDevelopers()) {
ab.addDeveloper(developer);
}
return ab;
}
- public static List getTypicalPersons() {
+ /**
+ * Returns an {@code AddressBook} with all the typical developers integrated with projects.
+ */
+ public static AddressBook getTypicalAddressBookWithProjects() {
+ AddressBook ab = new AddressBook();
+ for (Developer developer: getTypicalDevelopers()) {
+ ab.addDeveloper(developer);
+ }
+ for (Project project : getTypicalProjects()) {
+ ab.addProject(project);
+ }
+ return ab;
+ }
+
+ public static List getTypicalDevelopers() {
return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE));
}
}
diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/seedu/address/testutil/TypicalIndexes.java
index 1e613937657..8ac23139257 100644
--- a/src/test/java/seedu/address/testutil/TypicalIndexes.java
+++ b/src/test/java/seedu/address/testutil/TypicalIndexes.java
@@ -1,5 +1,7 @@
package seedu.address.testutil;
+import java.util.List;
+
import seedu.address.commons.core.index.Index;
/**
@@ -9,4 +11,9 @@ public class TypicalIndexes {
public static final Index INDEX_FIRST_PERSON = Index.fromOneBased(1);
public static final Index INDEX_SECOND_PERSON = Index.fromOneBased(2);
public static final Index INDEX_THIRD_PERSON = Index.fromOneBased(3);
+ public static final Index INDEX_FIRST_PROJECT = Index.fromOneBased(1);
+ public static final Index INDEX_SECOND_PROJECT = Index.fromOneBased(2);
+ public static final Index INVALID_INDEX_PROJECT = Index.fromOneBased(5);
+ public static final List INDEX_FIRST_PROJECT_AND_DEADLINE = List.of(Index.fromOneBased(1),
+ Index.fromOneBased(1));
}
diff --git a/src/test/java/seedu/address/testutil/TypicalProjects.java b/src/test/java/seedu/address/testutil/TypicalProjects.java
new file mode 100644
index 00000000000..c1c0d8dc852
--- /dev/null
+++ b/src/test/java/seedu/address/testutil/TypicalProjects.java
@@ -0,0 +1,95 @@
+package seedu.address.testutil;
+
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DEADLINE_ANDROIDAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DEADLINE_APPLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DEADLINE_GOOGLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DESCRIPTION_ANDROIDAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DESCRIPTION_APPLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_DESCRIPTION_GOOGLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_NAME_ANDROIDAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_NAME_APPLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_NAME_GOOGLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_PRIORITY_ANDROIDAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_PRIORITY_APPLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_PRIORITY_GOOGLEAPP;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_TAG_BACKEND;
+import static seedu.address.logic.commands.CommandTestUtil.VALID_PROJECT_TAG_UI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import seedu.address.model.AddressBook;
+import seedu.address.model.project.Project;
+
+/**
+ * A utility class containing a list of {@code Project} objects to be used in tests.
+ */
+public class TypicalProjects {
+
+ public static final Project PROJECT_A = new ProjectBuilder().withName("Project A")
+ .withDescription("This is Project A").withDeadline("20-12-2023,Design frontend,MEDIUM,0").build();
+ public static final Project PROJECT_B = new ProjectBuilder().withName("Project B")
+ .withDescription("This is Project B").withDeadline("22-12-2023,Design backend,HIGH,0").build();
+ public static final Project PROJECT_C = new ProjectBuilder().withName("Project C")
+ .withDescription("This is Project C").withDeadline("25-12-2023,Testing,LOW,1").build();
+
+ public static final Project PROJECT_A_NO_SPACING = new ProjectBuilder().withName("ProjectA")
+ .withDescription("This is Project A").withDeadline("20-12-2023,Design frontend,MEDIUM,0").build();
+
+ private TypicalProjects() {} // prevents instantiation
+
+ /**
+ * Returns an {@code AddressBook} with all the typical projects.
+ */
+ public static AddressBook getTypicalAddressBook() {
+ AddressBook ab = new AddressBook();
+ for (Project project : getTypicalProjects()) {
+ ab.addProject(project);
+ }
+ return ab;
+ }
+
+ public static List getTypicalProjects() {
+ return new ArrayList<>(Arrays.asList(PROJECT_A, PROJECT_B, PROJECT_C, PROJECT_A_NO_SPACING));
+ }
+
+ /**
+ * Returns a list of typical project names.
+ */
+ public static List getTypicalProjectNames() {
+ return new ArrayList<>(Arrays.asList(VALID_PROJECT_NAME_APPLEAPP, VALID_PROJECT_NAME_GOOGLEAPP,
+ VALID_PROJECT_NAME_ANDROIDAPP));
+ }
+
+ /**
+ * Returns a list of typical project descriptions.
+ */
+ public static List getTypicalProjectDescriptions() {
+ return new ArrayList<>(Arrays.asList(VALID_PROJECT_DESCRIPTION_APPLEAPP, VALID_PROJECT_DESCRIPTION_GOOGLEAPP,
+ VALID_PROJECT_DESCRIPTION_ANDROIDAPP));
+ }
+
+ /**
+ * Returns a list of typical project deadlines.
+ */
+ public static List getTypicalProjectDeadlines() {
+ return new ArrayList<>(Arrays.asList(VALID_PROJECT_DEADLINE_APPLEAPP, VALID_PROJECT_DEADLINE_GOOGLEAPP,
+ VALID_PROJECT_DEADLINE_ANDROIDAPP));
+ }
+
+ /**
+ * Returns a list of typical project priorities.
+ */
+ public static List getTypicalProjectPriorities() {
+ return new ArrayList<>(Arrays.asList(VALID_PROJECT_PRIORITY_APPLEAPP, VALID_PROJECT_PRIORITY_GOOGLEAPP,
+ VALID_PROJECT_PRIORITY_ANDROIDAPP));
+ }
+
+ /**
+ * Returns a list of typical project tags.
+ */
+ public static List getTypicalProjectTags() {
+ return new ArrayList<>(Arrays.asList(VALID_PROJECT_TAG_UI, VALID_PROJECT_TAG_BACKEND));
+ }
+}