From 530223bb16b0bb2ad1a241b7a09c53e76ec6fe74 Mon Sep 17 00:00:00 2001 From: emilfa Date: Thu, 26 Feb 2026 10:08:14 +0100 Subject: [PATCH 01/20] feat: created Organisation class --- .../app/model/organization/Organization.java | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/group5/app/model/organization/Organization.java b/src/main/java/edu/group5/app/model/organization/Organization.java index 825945f..abb2f71 100644 --- a/src/main/java/edu/group5/app/model/organization/Organization.java +++ b/src/main/java/edu/group5/app/model/organization/Organization.java @@ -1,5 +1,45 @@ package edu.group5.app.model.organization; +import java.util.Objects; + public class Organization { - + private final int orgNumber; + private final String name; + private final boolean trusted; + private final String websiteURL; + private final boolean isPreApproved; + private final String description; + + public Organization(int orgNumber, String name, boolean trusted, String websiteURL, boolean isPreApproved, String description) { + this.orgNumber = orgNumber; + this.name = Objects.requireNonNull(name, "name cannot be null"); + this.trusted = trusted; + this.websiteURL = Objects.requireNonNull(websiteURL, "websiteURL cannot be null"); + this.isPreApproved = isPreApproved; + this.description = Objects.requireNonNull(description, "description cannot be null"); + } + + public int getOrgNumber() { + return orgNumber; + } + + public String getName() { + return name; + } + + public boolean isTrusted() { + return trusted; + } + + public String getWebsiteURL() { + return websiteURL; + } + + public boolean isPreApproved() { + return isPreApproved; + } + + public String getDescription() { + return description; + } } From 51a85e685c7dce635c38e1e8f835f93cf5c676b8 Mon Sep 17 00:00:00 2001 From: emilfa Date: Thu, 26 Feb 2026 10:47:33 +0100 Subject: [PATCH 02/20] feat: made Organization into a record class + error handling + javadoc --- .../app/model/organization/Organization.java | 67 ++++++++++--------- .../model/organization/OrganizationTest.java | 4 ++ 2 files changed, 40 insertions(+), 31 deletions(-) create mode 100644 src/test/java/edu/group5/app/model/organization/OrganizationTest.java diff --git a/src/main/java/edu/group5/app/model/organization/Organization.java b/src/main/java/edu/group5/app/model/organization/Organization.java index abb2f71..885f0ed 100644 --- a/src/main/java/edu/group5/app/model/organization/Organization.java +++ b/src/main/java/edu/group5/app/model/organization/Organization.java @@ -2,44 +2,49 @@ import java.util.Objects; -public class Organization { - private final int orgNumber; - private final String name; - private final boolean trusted; - private final String websiteURL; - private final boolean isPreApproved; - private final String description; - +/** + * Represents an organization. + * + *

An organization is identified by an organization number, a name, + * trust status, website URL, pre-approval status, and a textual description. + * + *

Instances are validated on creation: + *

+ */ +public record Organization(int orgNumber, String name, boolean trusted, String websiteURL, boolean isPreApproved, + String description) { + /** + * Creates a new organization. + * + * @param orgNumber the organization number; must be non-negative + * @param name the organization name; must not be null or blank + * @param trusted whether the organization is trusted + * @param websiteURL the organization's website URL; must not be null or blank + * @param isPreApproved whether the organization is pre-approved + * @param description a textual description of the organization; must not be null + * @throws NullPointerException if name, websiteURL or description is null + * @throws IllegalArgumentException if orgNumber is negative, or if name or websiteURL is blank + */ public Organization(int orgNumber, String name, boolean trusted, String websiteURL, boolean isPreApproved, String description) { + if (orgNumber < 0) { + throw new IllegalArgumentException("orgNumber cannot be negative"); + } this.orgNumber = orgNumber; this.name = Objects.requireNonNull(name, "name cannot be null"); this.trusted = trusted; this.websiteURL = Objects.requireNonNull(websiteURL, "websiteURL cannot be null"); this.isPreApproved = isPreApproved; this.description = Objects.requireNonNull(description, "description cannot be null"); - } - - public int getOrgNumber() { - return orgNumber; - } - - public String getName() { - return name; - } - - public boolean isTrusted() { - return trusted; - } - - public String getWebsiteURL() { - return websiteURL; - } - - public boolean isPreApproved() { - return isPreApproved; - } - public String getDescription() { - return description; + if (name.isBlank()) { + throw new IllegalArgumentException("name cannot be blank"); + } + if (websiteURL.isBlank()) { + throw new IllegalArgumentException("websiteURL cannot be blank"); + } } } diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java new file mode 100644 index 0000000..557c0c0 --- /dev/null +++ b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java @@ -0,0 +1,4 @@ +import static org.junit.jupiter.api.Assertions.*; +class OrganizationTest { + +} \ No newline at end of file From fbbdab4b439806938429819006c2d7ce8305b45e Mon Sep 17 00:00:00 2001 From: emilfa Date: Thu, 26 Feb 2026 10:48:02 +0100 Subject: [PATCH 03/20] test: made unit tests for Organization --- .../model/organization/OrganizationTest.java | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java index 557c0c0..3b086c3 100644 --- a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java +++ b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java @@ -1,4 +1,86 @@ +package edu.group5.app.model.organization; + +import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.*; + class OrganizationTest { + @Test + void constructor_ThrowsWhenOrgNumberIsNegative() { + assertThrows(IllegalArgumentException.class, () -> {new Organization( + -1, + "Org", + true, + null, + true, + "Org description" + ); + }); + } + + @Test + void constructor_ThrowsWhenNameIsNull() { + assertThrows(NullPointerException.class, () -> {new Organization( + 1, + null, + true, + "org.com", + true, + "Org description" + ); + }); + } + + @Test + void constructor_ThrowsWhenNameIsBlank() { + assertThrows(IllegalArgumentException.class, () -> {new Organization( + 1, + "", + true, + "org.com", + true, + "Org description" + ); + }); + } + + @Test + void constructor_ThrowsWhenWebsiteURLIsNull() { + assertThrows(NullPointerException.class, () -> {new Organization( + 1, + "Org", + true, + null, + true, + "Org description" + ); + }); + } + + @Test + void constructor_ThrowsWhenWebsiteURLIsBlank() { + assertThrows(IllegalArgumentException.class, () -> {new Organization( + 1, + "Org", + true, + "", + true, + "Org description" + ); + }); + } + + @Test + void constructor_ThrowsWhenDescriptionIsNull() { + assertThrows(NullPointerException.class, () -> {new Organization( + 1, + "Org", + true, + "org.com", + true, + null + ); + }); + } } \ No newline at end of file From 837cf93c5eec1f6c7ae866e6c708e7c388e8168e Mon Sep 17 00:00:00 2001 From: Fredrik Marjoni Date: Thu, 26 Feb 2026 11:03:46 +0100 Subject: [PATCH 04/20] feat[User]: add constructor and get methods --- .../java/edu/group5/app/model/user/User.java | 111 +++++++++++++++++- .../edu/group5/app/model/user/User.class | Bin 289 -> 1917 bytes 2 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/group5/app/model/user/User.java b/src/main/java/edu/group5/app/model/user/User.java index e163785..939bea9 100644 --- a/src/main/java/edu/group5/app/model/user/User.java +++ b/src/main/java/edu/group5/app/model/user/User.java @@ -1,5 +1,114 @@ package edu.group5.app.model.user; +/** + * User class represents a user in the system. It is an abstract class that will be extended by specific user types such as Donor, Recipient, and Admin. + * Each user has a unique userId, a role that defines their permissions in the system, and personal information such as first name, last name, email, and password hash. + * The constructor validates that all required fields are provided and throws an IllegalArgumentException if any of the fields are null or empty. + * This ensures that the User objects are always in a valid state when created. + */ +public abstract class User { + private int userId; + private String role; + private String firstName; + private String lastName; + private String email; + private String passwordHash; + + /** + * Constructor for User class. Validates that all required fields + * are provided and throws an IllegalArgumentException if any of the fields are null or empty. + * @param userId the unique identifier for the user, must be a positive integer + * @param role the role of the user (e.g., "Donor", "Recipient", "Admin") + * @param firstName the first name of the user + * @param lastName the last name of the user + * @param email the email address of the user + * @param passwordHash the hashed password of the user + */ + public User(int userId, String role, String firstName, + String lastName, String email, String passwordHash) { + if (userId <= 0) { + throw new IllegalArgumentException("User ID must be positive"); + } + if (role == null || role.trim().isEmpty()) { + throw new IllegalArgumentException("Role cannot be null or empty"); + } + if (firstName == null || firstName.trim().isEmpty()) { + throw new IllegalArgumentException("First name cannot be null or empty"); + } + if (lastName == null || lastName.trim().isEmpty()) { + throw new IllegalArgumentException("Last name cannot be null or empty"); + } + if (email == null || email.trim().isEmpty()) { + throw new IllegalArgumentException("Email cannot be null or empty"); + } + if (passwordHash == null || passwordHash.trim().isEmpty()) { + throw new IllegalArgumentException("Password hash cannot be null or empty"); + } + this.userId = userId; + this.role = role.trim(); + this.firstName = firstName.trim(); + this.lastName = lastName.trim(); + this.email = email.trim(); + this.passwordHash = passwordHash; +} -public class User { + /** + * Gets the unique identifier for the user. + * @return the userId of the user + */ + public int getUserId() { + return userId; + } + + /** + * Gets the role of the user, which defines their permissions in the system. + * @return the role of the user + */ + public String getRole() { + return role; + } + + /** + * Gets the first name of the user. + * @return the first name of the user + */ + public String getFirstName() { + return firstName; + } + /** + * Gets the last name of the user. + * @return the last name of the user + */ + public String getLastName() { + return lastName; + } + + /** + * Gets the email address of the user. + * @return the email of the user + */ + public String getEmail() { + return email; + } + + /** + * Gets the hashed password of the user. + * This is used for authentication purposes and should not be exposed in plaintext. + * @return the password hash of the user + */ + public String getPasswordHash() { + return passwordHash; + } + + /** + * Verifies if the provided password matches the stored password hash for the user. + * This method should implement the logic to hash the input password + * and compare it with the stored password hash. + * @param password the plaintext password to verify + * @return true if the password is correct, false otherwise + */ + public boolean verifyPassword(String password) { + // TODO Implement password verification logic here, e.g., using a hashing algorithm + return true; // Placeholder return value + } } diff --git a/target/classes/edu/group5/app/model/user/User.class b/target/classes/edu/group5/app/model/user/User.class index 950b2f7160ec2652685a7081f89e90b9a1c868d5..4f41b157efad2b627e7442266011a3ad90367176 100644 GIT binary patch literal 1917 zcmb_cL37hq5dNNHTXrHR5CSD60R>2EizEsmgtVcw5F9WB+97RbN;{oVY~hH?l17qK z_yaxn(nDv;vA0gAovF!8JA@kteiX3#Venv&l{%i8x5~!IYu+I0^=K66r=?X+&8yO!!g~u@#V&Ss~QPp*`rbu5EX%R z;5nAS;OZN{wJ5ON`jSBYo*jhIZL>iRImg@;Ggia29Rbxh!|*3Bs9iV1O$vL_cJ1hr zzz@aB-e@06Q(C8-m#NTR^x&Y10tN+oiluc0Ljot?R8espt8O}%gL<=Jxl#E+)$$|T zb8|Q%aFqGcDp$2eGmNwiOY^af7!;@+f7>%ADkn1ay`YGcY&9LEVt zkN9f{3>8az@r)id<^oa@;Ie~#y+qG^t8yi;ewYd=wq*pbabu+N}+*YQeO*<6OR^L7N zG`fYg$gKW&%ka zzhwpXy@$KXeMaUky`J5tBG9|$HG`_PV)NB`&S{2+Ha$*c_0Z$aBE>9{lwuC$P7KPO z_>()aCwJnG_8cJ#=%;l65WiCtg|s{RHV%wDLg9ZL`gZW}Ha>bf^$dln$2j&F+HYteWZmMo$qg9R_FU#nA2tW z7Up#st%U`BINQSFKU6^vKBe^zhG;#8G)Ae?F%04aH2QRUM2k3uE0`dkNqmnY9F(wy zGx!-(_ysfg6$Tz*7JuL@{=yu#aSl%~k0pwDJ!T0P@fn?nFUh))67!yt5;MG-bYKj6O6pXz60}A;RQnQnB(}buhZIc+zbt`@WcS7^xkGsQ delta 159 zcmey%w~&eJ)W2Q(7#J8_83ZPB*~;2v=4F=HF)}b~XofK|usG+Zq;fGZGjQ@Surjbs zzRnb!#TA@iT9lmXmYI{v$iNv|oLZ!pl~|U@pvVB!1vH2ONHc;|14(uuPan)@U|`kS m&cLw|D8R(P1tdYz3_uOsK#~W{W(Cr`KprClACP2X;0FLGfEL^U From 76e620f7cd2582413d39aea6d37310f65f5298c9 Mon Sep 17 00:00:00 2001 From: emilfa Date: Thu, 26 Feb 2026 11:15:16 +0100 Subject: [PATCH 05/20] feat: created OrganizationRepo class --- .../model/organization/OrganizationRepo.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/edu/group5/app/model/organization/OrganizationRepo.java diff --git a/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java b/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java new file mode 100644 index 0000000..850333f --- /dev/null +++ b/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java @@ -0,0 +1,39 @@ +package edu.group5.app.model.organization; + +import edu.group5.app.model.Repository; + +import java.util.HashMap; +import java.util.Objects; + +/** + * Handles business logic associated with organizations + */ +public class OrganizationRepo implements Repository { + private HashMap content; + + /** + * Creates a new Organization Repository + * + * @param content holds all current organizations + * @throws NullPointerException if content is null + */ + public OrganizationRepo(HashMap content) { + this.content = Objects.requireNonNull(content, "content cannot be null"); + } + + public HashMap getContent() { + return content; + } + + public HashMap getTrustedOrganizations() { + HashMap trustedOrgs = new HashMap<>(); + + content.forEach((orgNr, org) -> { + if (org.trusted()) { + trustedOrgs.put(orgNr, org); + } + }); + + return trustedOrgs; + } +} From 98b995bf787af59c7f73c54b8716b1272014ca45 Mon Sep 17 00:00:00 2001 From: emilfa Date: Thu, 26 Feb 2026 11:53:56 +0100 Subject: [PATCH 06/20] test: created OrganizationRepoTest class --- .../group5/app/model/organization/OrganizationRepoTest.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java new file mode 100644 index 0000000..780bf8e --- /dev/null +++ b/src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java @@ -0,0 +1,4 @@ +import static org.junit.jupiter.api.Assertions.*; +class OrganizationRepoTest { + +} \ No newline at end of file From aefd5ffb8f758c8ee43d8ea4b3a5d210f0b80fb8 Mon Sep 17 00:00:00 2001 From: emilfa Date: Thu, 26 Feb 2026 11:55:04 +0100 Subject: [PATCH 07/20] feat: created abstract class Repository --- .../java/edu/group5/app/model/Repository.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/edu/group5/app/model/Repository.java diff --git a/src/main/java/edu/group5/app/model/Repository.java b/src/main/java/edu/group5/app/model/Repository.java new file mode 100644 index 0000000..d0d2792 --- /dev/null +++ b/src/main/java/edu/group5/app/model/Repository.java @@ -0,0 +1,20 @@ +package edu.group5.app.model; + +/** + * Represents a repository + */ +public abstract class Repository { + protected final Object content; + + public Repository(Object content) { + this.content = content; + } + + /** + * Gets the content of the repo + * @return content of the repo + */ + public Object getContent() { + return content; + } +} From dc7bc8f024a98a06108320789cee82ee0f772aed Mon Sep 17 00:00:00 2001 From: emilfa Date: Thu, 26 Feb 2026 11:56:16 +0100 Subject: [PATCH 08/20] feat: minor changes to OrganizationRepo --- .../app/model/organization/OrganizationRepo.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java b/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java index 850333f..27b128f 100644 --- a/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java +++ b/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java @@ -8,23 +8,24 @@ /** * Handles business logic associated with organizations */ -public class OrganizationRepo implements Repository { - private HashMap content; +public class OrganizationRepo extends Repository { + private final HashMap content; /** * Creates a new Organization Repository * - * @param content holds all current organizations + * @param content holds all current organizations in the repository * @throws NullPointerException if content is null */ public OrganizationRepo(HashMap content) { this.content = Objects.requireNonNull(content, "content cannot be null"); + super(content); } - public HashMap getContent() { - return content; - } - + /** + * Gets all trusted organizations in the repository + * @return all organizations with trusted = true + */ public HashMap getTrustedOrganizations() { HashMap trustedOrgs = new HashMap<>(); From b9693b75fd3928334c1dc67372f69c4ba2e5224b Mon Sep 17 00:00:00 2001 From: Fredrik Marjoni Date: Thu, 26 Feb 2026 11:57:03 +0100 Subject: [PATCH 09/20] feat[User]: Add Bcrpyt in verifying password in class and dependency in pom.xml --- pom.xml | 7 +++++++ .../java/edu/group5/app/model/user/User.java | 18 ++++++++++++------ .../edu/group5/app/model/user/User.class | Bin 1917 -> 2200 bytes 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 4895163..4d088c4 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,13 @@ javafx-controls ${javafx.version} + + + + org.springframework.security + spring-security-crypto + 7.0.2 + diff --git a/src/main/java/edu/group5/app/model/user/User.java b/src/main/java/edu/group5/app/model/user/User.java index 939bea9..e20e4f4 100644 --- a/src/main/java/edu/group5/app/model/user/User.java +++ b/src/main/java/edu/group5/app/model/user/User.java @@ -1,9 +1,13 @@ package edu.group5.app.model.user; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; /** * User class represents a user in the system. It is an abstract class that will be extended by specific user types such as Donor, Recipient, and Admin. * Each user has a unique userId, a role that defines their permissions in the system, and personal information such as first name, last name, email, and password hash. * The constructor validates that all required fields are provided and throws an IllegalArgumentException if any of the fields are null or empty. * This ensures that the User objects are always in a valid state when created. + * The class also includes a method to verify the user's password + * by comparing the provided plaintext password with the stored hashed password using BCrypt. + * */ public abstract class User { private int userId; @@ -21,7 +25,7 @@ public abstract class User { * @param firstName the first name of the user * @param lastName the last name of the user * @param email the email address of the user - * @param passwordHash the hashed password of the user + * @param passwordHash the hashed password of the user, used for authentication purposes */ public User(int userId, String role, String firstName, String lastName, String email, String passwordHash) { @@ -101,14 +105,16 @@ public String getPasswordHash() { } /** - * Verifies if the provided password matches the stored password hash for the user. - * This method should implement the logic to hash the input password - * and compare it with the stored password hash. + * Verifies if the provided password matches the stored password hash. + * This method uses BCrypt to compare the plaintext password with the hashed password. * @param password the plaintext password to verify * @return true if the password is correct, false otherwise */ public boolean verifyPassword(String password) { - // TODO Implement password verification logic here, e.g., using a hashing algorithm - return true; // Placeholder return value + if (password == null || password.isEmpty()) { + return false; + } + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + return encoder.matches(password, this.passwordHash); } } diff --git a/target/classes/edu/group5/app/model/user/User.class b/target/classes/edu/group5/app/model/user/User.class index 4f41b157efad2b627e7442266011a3ad90367176..a863d4f6ccfa7c6a4b044c45dcae7ab0efd15832 100644 GIT binary patch delta 509 zcmbu5O-mb56o#McsL}BY1-BZpXlo)Peg>mfA{tv0zo8Ta8OJg4E73cNB3-!ax+N6a zMR&SWL0V$5)I}Fv_$&MqE|s2%KS3^>`@HWx=Wxz_sQ=n%-acO60Fx|Vn&-xGfH#Wq ztWH_pp5Dx)HnhF#9%l8n<+)B?Z|06HM<4CwvesJZwqg^$oVPtsveqXvPIleZCet+f zAyG?`Sw&#i&N*qT)pF7$#fI*8Coj8`m*S|Q91-5g-?ksdzL%NP3iPCus%aKRu~ z4Dp9ZAzpE!UKj2vn+vM4Q^iX(CNx)~4?^!s^h;<}XhfxbeLO`RMT7jfham@AL;o;C zMS|a`FwTB6{r-x#$#AIaCy^pEXOdztEU`%z08NdQ){&=K291gnd}_l8qoSlCbF!wA WcawP*C}T|Aa>{BH)k-!+tfl`Z*MLF* delta 240 zcmbOs_?M6C)W2Q(7#J8_8N4@gt!3tBWZ)=BEG{n3FG|_GfW?B*SBim!L56{YL6$*? zL7qVY2(=iL7%Ui+8JrkY8G;zp7-ASS7;+di8Oj*68QK_h7$z|2F-&F9XPC=iz_66T zkYOEz5yN%{V}`v9CX-d!mM~gRZe$moe4kC7(HYE=VOMAL2D2i8tY9F^hA|q Date: Thu, 26 Feb 2026 12:44:50 +0100 Subject: [PATCH 10/20] feat[test]: add tests classes to visually display the folder structure of the project --- src/test/java/edu/group5/app/control/WrapperTest.java | 5 +++++ .../java/edu/group5/app/model/donation/DonationTest.java | 5 +++++ .../edu/group5/app/model/organization/OrganizationTest.java | 5 +++++ src/test/java/edu/group5/app/model/user/UserTest.java | 5 +++++ src/test/java/edu/group5/app/utils/UtilitiesTest.java | 5 +++++ src/test/java/edu/group5/app/view/ViewTest.java | 5 +++++ 6 files changed, 30 insertions(+) create mode 100644 src/test/java/edu/group5/app/control/WrapperTest.java create mode 100644 src/test/java/edu/group5/app/model/donation/DonationTest.java create mode 100644 src/test/java/edu/group5/app/model/organization/OrganizationTest.java create mode 100644 src/test/java/edu/group5/app/model/user/UserTest.java create mode 100644 src/test/java/edu/group5/app/utils/UtilitiesTest.java create mode 100644 src/test/java/edu/group5/app/view/ViewTest.java diff --git a/src/test/java/edu/group5/app/control/WrapperTest.java b/src/test/java/edu/group5/app/control/WrapperTest.java new file mode 100644 index 0000000..d626fd7 --- /dev/null +++ b/src/test/java/edu/group5/app/control/WrapperTest.java @@ -0,0 +1,5 @@ +package edu.group5.app.control; + +public class WrapperTest { + +} diff --git a/src/test/java/edu/group5/app/model/donation/DonationTest.java b/src/test/java/edu/group5/app/model/donation/DonationTest.java new file mode 100644 index 0000000..a905209 --- /dev/null +++ b/src/test/java/edu/group5/app/model/donation/DonationTest.java @@ -0,0 +1,5 @@ +package edu.group5.app.model.donation; + +public class DonationTest { + +} diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java new file mode 100644 index 0000000..45e04ca --- /dev/null +++ b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java @@ -0,0 +1,5 @@ +package edu.group5.app.model.organization; + +public class OrganizationTest { + +} diff --git a/src/test/java/edu/group5/app/model/user/UserTest.java b/src/test/java/edu/group5/app/model/user/UserTest.java new file mode 100644 index 0000000..bc0bcce --- /dev/null +++ b/src/test/java/edu/group5/app/model/user/UserTest.java @@ -0,0 +1,5 @@ +package edu.group5.app.model.user; + +public class UserTest { + +} diff --git a/src/test/java/edu/group5/app/utils/UtilitiesTest.java b/src/test/java/edu/group5/app/utils/UtilitiesTest.java new file mode 100644 index 0000000..88aa0c9 --- /dev/null +++ b/src/test/java/edu/group5/app/utils/UtilitiesTest.java @@ -0,0 +1,5 @@ +package edu.group5.app.utils; + +public class UtilitiesTest { + +} diff --git a/src/test/java/edu/group5/app/view/ViewTest.java b/src/test/java/edu/group5/app/view/ViewTest.java new file mode 100644 index 0000000..bd0cd83 --- /dev/null +++ b/src/test/java/edu/group5/app/view/ViewTest.java @@ -0,0 +1,5 @@ +package edu.group5.app.view; + +public class ViewTest { + +} From fae604f512c477b0117e9155c18647d3d0ed24a8 Mon Sep 17 00:00:00 2001 From: Fredrik Marjoni Date: Thu, 26 Feb 2026 12:50:56 +0100 Subject: [PATCH 11/20] update: delete target by mvn clean --- target/classes/edu/group5/app/App.class | Bin 543 -> 0 bytes .../classes/edu/group5/app/control/Wrapper.class | Bin 292 -> 0 bytes .../edu/group5/app/model/donation/Donation.class | Bin 309 -> 0 bytes .../app/model/organization/Organization.class | Bin 329 -> 0 bytes .../classes/edu/group5/app/model/user/User.class | Bin 2200 -> 0 bytes .../classes/edu/group5/app/utils/Utilities.class | Bin 294 -> 0 bytes target/classes/edu/group5/app/view/View.class | Bin 277 -> 0 bytes .../compile/default-compile/createdFiles.lst | 1 - .../compile/default-compile/inputFiles.lst | 1 - target/test-classes/edu/group5/app/AppTest.class | Bin 503 -> 0 bytes 10 files changed, 2 deletions(-) delete mode 100644 target/classes/edu/group5/app/App.class delete mode 100644 target/classes/edu/group5/app/control/Wrapper.class delete mode 100644 target/classes/edu/group5/app/model/donation/Donation.class delete mode 100644 target/classes/edu/group5/app/model/organization/Organization.class delete mode 100644 target/classes/edu/group5/app/model/user/User.class delete mode 100644 target/classes/edu/group5/app/utils/Utilities.class delete mode 100644 target/classes/edu/group5/app/view/View.class delete mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst delete mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst delete mode 100644 target/test-classes/edu/group5/app/AppTest.class diff --git a/target/classes/edu/group5/app/App.class b/target/classes/edu/group5/app/App.class deleted file mode 100644 index e3679e1b8be800f5bef6f802b19397fadbe36584..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 543 zcmZuu%SyvQ6g|^d9!6XH@~y3_)`eM#i;5tkxCkm#>cZ8u9paQE6VgQRvvi^0!VmDH z#G6*A#S%Do?!9x)J#+K*{qYIl0{a>=3}rD)Y&TL#cx3Z1w9mp&Lyn;|;!oW6c;MPM z{gD{N422UJ$oP~Y+iLe1a_4F&Ok`nL$fLkebYvi|6TdH_JKpyMi92e*y&jKbn*SDa z@uM6wRGt5mJEZD!88Fma56;X%H;!cBcG^7ytEgxw&-v>&RR63emm)S(Z+Lm_;K zxyx^Vwru~tTz~%nEYT0)5e8~si-R?FITNxhMP`c1nq2HGld>UvLjNScq{wA)5bN}$ zvWn1r)rGF!2#xV%OYj$FuOc+ijuD_q=q0*P@AYS@?1xNqMR-n3CiAVd+VP|4S4Vv& z43qy|%n8xP)HYKq?RLcvcQ4KuMqnHK5;&4O&l)m`I|IS=2d!@|c!*eC8$8fqjqiED M@rjAhW%baz0k+0J=l}o! diff --git a/target/classes/edu/group5/app/model/donation/Donation.class b/target/classes/edu/group5/app/model/donation/Donation.class deleted file mode 100644 index 687d00e7e82e816b337c9de3a13b0be79dc8c689..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcma)%F>b;@5JmqO8-oJ@aRV9z6xk|OqBJC_EGR(qYkLKY%&ui@?nM=eA_vH!B4!cv zG=Jv*(Tv{w{hxmUe4!u0BaBp5i%n_k;#J6^5PO@cTx8bBN?Rj7Z%qiF(BH|U6uC4T zu}F3*tq9F`ZFKcPXpARofu|D>)9hH7#OlW2g(ud| OwGX&<*%6*uJ@hV=jz&NL diff --git a/target/classes/edu/group5/app/model/organization/Organization.class b/target/classes/edu/group5/app/model/organization/Organization.class deleted file mode 100644 index af118ddfe1be2c754d3f950677451cf175401840..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 329 zcmb7pP5!g$MX ztZKHES{7SfwuJt@v8H_>^rly9LOho<8G1M!AVHrn%8k`e-LBC7nTuKzE^}9My=HF$ z{}1E##k>-3^5d-T2-(VYzSNH<+`c$eo&{S>Aa3$+NTuK;nF^^r1IhI#PCjH1A(ITx TkcBhJ!M;zVo(mC%k`YFK{nk$L diff --git a/target/classes/edu/group5/app/model/user/User.class b/target/classes/edu/group5/app/model/user/User.class deleted file mode 100644 index a863d4f6ccfa7c6a4b044c45dcae7ab0efd15832..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2200 zcmb_dT~ixX7=BJjvPsxLOF@gYu=InHKv<+eQEES+p+o~zs5oUDoz1c&+irH({XqEx zUVGz(GxpNEj-xXMX6%S}T==8Z_nZy3fuI*U$?SR0d(QLjd!FYx$?t#satNS^#}Z-; zgT{8KRy`+lXH?B~)w;87SZe4Sp863zB*YocJ=JzK)za*$x>k8==mA5L?R*gi+T_i$QiZ-~Yn#wwE=(MrCiCwi(=E z_;j>%y4wGh$!${4i*(QoI&fY_7Cj6dqq$89y$n}gouXt}Mpd)!d)2UR*g^42-Eafb zu~T@1;UecpDLqi?p&uv}LvbD749s1sdI1-C)qaM)(bG-mHZvH&WeJyBsEsI-F^C~* zkNB%I^p56E<2ia*#uZ#;kW9Z=cY{6A|5ggu87{4p8j7yjwjZlN(F}NkD4+oHPZR4t!Xf*G7?Dg=xrGiQarjT zBOOIEGBQzgOGalDy(2?LilMt~+Qw>FuNdBAtr8j1(KTyR^GrT(CgVZP^cj@$KO3K{ zo81UB{n?7}MLs<)TeNlZ zyO+T-&htlE#tK&H1a&RYYX%Wgc-^UsHO<>FJ`W9BH|9?}FtZ^wX6@jC+Kl7D6O6+`0lQG~6(;dDrtl4J z;yI@AJ!bF&W^sU9_?1xeRB<_C3Agbc&4@3-IujA+JtiW~JXhtA-%RR(N1XkHh&caA z+@W{`oqtkmk_5&i47~mYvgvHPTYN~PySNuAMSapA3}F-bpE2=*f|xjPQY7z+Cgo^D zvq^^g7@`cx+yb8b@dWr`Tkt|#@YG50T3hg9Tk!Nr@W*Yz588rfPl7*d3of<=&z%I< z+Jcwxut}ItI&vk4#*UB~6IUS7@!}n9|(W*}&TQ+TskT6{9Z>F(|qWxFoc`5%5|~O4g35%4DA=U zguC>Ai)TVIuUwOxH}Y4I_w%dYRb-afgeo3<4xV{|s5U6!y=3 NB=t&?oE8QcoB)e9K-&NS diff --git a/target/classes/edu/group5/app/view/View.class b/target/classes/edu/group5/app/view/View.class deleted file mode 100644 index bc21f75c019877955f50631d6137819bf7288900..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 277 zcmZ{fJ&wXa427RVLLmH#3enL41ygOcXdA><5fq^GlQ4ooA&IgHoQrBD3J$=bR(PUq zX+HbevY-9@yFUP|(05@GhH77mL!Oq|hmct&E?Qkhz;Iy``X_mjB9_TPY{HX@3POFM z6J2}}YLjU|u$Spxd8nb;hJ!kx=j%kR%X6smoeX0|82D)<<3Q%x=>MW!9Q6-j)!&6cJ)YHseq80^kJfFl`KrproH8gOR6XxzA9!DE^>c%a2>SGmKn!-~*l HTIjt1jj%a; diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst deleted file mode 100644 index 28e9804..0000000 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ /dev/null @@ -1 +0,0 @@ -edu\group5\app\App.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst deleted file mode 100644 index 16a5464..0000000 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ /dev/null @@ -1 +0,0 @@ -C:\Users\marjo\Documents\Github\Help-Me-Help\src\main\java\edu\group5\app\App.java diff --git a/target/test-classes/edu/group5/app/AppTest.class b/target/test-classes/edu/group5/app/AppTest.class deleted file mode 100644 index 4c6649954e613037560eadfde5c4dcaf50c01019..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 503 zcmZutO-sW-6r4@dMq{)e*4lyxy;Tq9Af75h5IqG2Efu_N+oj!-?uN}qf0rl4gFnC@ zCBCEuFTK3k_vSHgXMTRaz5(2#=fPp_S@i3n zYv(d!=*F9`4;b3nT<6I&QrVj@&(h9^CMUJtW3H@RijmAD$wf+O%dOOk)Q)0pX5k{I z4^mB~6^1Oyu<$eR(L&q9KEv_mttiWcDU|{opu^zva&m$Xl{paCB{RD;z5;VyLyd&D}ZueTb6h0p~t YrI7oH=D(0nt3VSj8QdgxNUVeIAF#x0fB*mh From 8bd6986511498780071f5d99c0223bde9a634d99 Mon Sep 17 00:00:00 2001 From: Fredrik Marjoni Date: Thu, 26 Feb 2026 13:23:59 +0100 Subject: [PATCH 12/20] test[User]: Add dependency for the Bcrypt, and add positive and Negative JUnit tests --- pom.xml | 5 + .../java/edu/group5/app/model/user/User.java | 2 +- .../edu/group5/app/model/user/UserTest.java | 108 +++++++++++++++++- 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b0f6764..5f7773d 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,11 @@ spring-security-crypto 7.0.2 + + commons-logging + commons-logging + 1.3.5 + diff --git a/src/main/java/edu/group5/app/model/user/User.java b/src/main/java/edu/group5/app/model/user/User.java index e20e4f4..8dd48cd 100644 --- a/src/main/java/edu/group5/app/model/user/User.java +++ b/src/main/java/edu/group5/app/model/user/User.java @@ -9,7 +9,7 @@ * by comparing the provided plaintext password with the stored hashed password using BCrypt. * */ -public abstract class User { +public class User { private int userId; private String role; private String firstName; diff --git a/src/test/java/edu/group5/app/model/user/UserTest.java b/src/test/java/edu/group5/app/model/user/UserTest.java index bc0bcce..b49f153 100644 --- a/src/test/java/edu/group5/app/model/user/UserTest.java +++ b/src/test/java/edu/group5/app/model/user/UserTest.java @@ -1,5 +1,111 @@ package edu.group5.app.model.user; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + public class UserTest { - + private static final int TEST_USER_ID = 1; + private static final String TEST_ROLE = "Donor"; + private static final String TEST_FIRST_NAME = "John"; + private static final String TEST_LAST_NAME = "Doe"; + private static final String TEST_EMAIL = "john.doe@example.com"; + private static final String TEST_PASSWORD = "password123"; + private static final String TEST_PASSWORD_HASH = new BCryptPasswordEncoder().encode(TEST_PASSWORD); + + private static final int WRONG_USER_ID = -5; + private static final String WRONG_ROLE = ""; + private static final String WRONG_FIRST_NAME = ""; + private static final String WRONG_LAST_NAME = ""; + private static final String WRONG_EMAIL = ""; + private static final String WRONG_PASSWORD_HASH = ""; + + private void constructorTest(int userId, String role, String firstName, String lastName, String email, String passwordHash, boolean negativeTest) { + boolean exceptionThrown = negativeTest; + try { + new User(userId, role, firstName, lastName, email, passwordHash); + } catch (Exception e) { + exceptionThrown = !negativeTest; + } finally { + assertFalse(exceptionThrown); + } + } + + @Test + public void constructorThrowsNoException() { + constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, false); + } + + @Test + public void constructorWithNegativeUserIdThrowsException() { + constructorTest(WRONG_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithEmptyRoleThrowsException() { + constructorTest(TEST_USER_ID, WRONG_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithEmptyFirstNameThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, WRONG_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithEmptyLastNameThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, WRONG_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithEmptyEmailThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, WRONG_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithEmptyPasswordHashThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, WRONG_PASSWORD_HASH, true); + } + + private void getMethodComparer(User user, boolean negativeTest) { + if (user.getUserId() == TEST_USER_ID && + user.getRole().equals(TEST_ROLE) && + user.getFirstName().equals(TEST_FIRST_NAME) && + user.getLastName().equals(TEST_LAST_NAME) && + user.getEmail().equals(TEST_EMAIL) && + user.getPasswordHash() != null) { + assertFalse(negativeTest); + } + } + + @Test + public void getMethodsReturnCorrectInformation() { + User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); + getMethodComparer(testUser, false); + } + + @Test + public void verifyPasswordReturnsTrueForCorrectPassword() { + User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); + assertTrue(testUser.verifyPassword(TEST_PASSWORD)); + } + + @Test + public void verifyPasswordReturnsFalseForIncorrectPassword() { + User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); + assertFalse(testUser.verifyPassword("wrongPassword")); + } + + @Test + public void verifyPasswordReturnsFalseForNullPassword() { + User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); + assertFalse(testUser.verifyPassword(null)); + } + + @Test + public void verifyPasswordReturnsFalseForEmptyPassword() { + User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); + assertFalse(testUser.verifyPassword("")); + } } From 50b7c3aefbf8fa75fa28bfd732129387ec5d377d Mon Sep 17 00:00:00 2001 From: Fredrik Marjoni Date: Thu, 26 Feb 2026 13:38:18 +0100 Subject: [PATCH 13/20] update[User]: Add negative test scenario for null-inputs for better coverage --- .../edu/group5/app/model/user/UserTest.java | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/test/java/edu/group5/app/model/user/UserTest.java b/src/test/java/edu/group5/app/model/user/UserTest.java index b49f153..1e7277a 100644 --- a/src/test/java/edu/group5/app/model/user/UserTest.java +++ b/src/test/java/edu/group5/app/model/user/UserTest.java @@ -95,17 +95,42 @@ public void verifyPasswordReturnsTrueForCorrectPassword() { public void verifyPasswordReturnsFalseForIncorrectPassword() { User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); assertFalse(testUser.verifyPassword("wrongPassword")); - } + } @Test public void verifyPasswordReturnsFalseForNullPassword() { User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); assertFalse(testUser.verifyPassword(null)); - } + } @Test public void verifyPasswordReturnsFalseForEmptyPassword() { User testUser = new User(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH); assertFalse(testUser.verifyPassword("")); - } + } + + @Test + public void constructorWithNullRoleThrowsException() { + constructorTest(TEST_USER_ID, null, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithNullFirstNameThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, null, TEST_LAST_NAME, TEST_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithNullLastNameThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, null, TEST_EMAIL, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithNullEmailThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, null, TEST_PASSWORD_HASH, true); + } + + @Test + public void constructorWithNullPasswordHashThrowsException() { + constructorTest(TEST_USER_ID, TEST_ROLE, TEST_FIRST_NAME, TEST_LAST_NAME, TEST_EMAIL, null, true); + } } From 0523bcefcf8cc128493dc34c10901aa020ce0889 Mon Sep 17 00:00:00 2001 From: Emil-F Date: Sun, 1 Mar 2026 13:59:19 +0100 Subject: [PATCH 14/20] test: added positive test for the constructor in OrganizationTest --- ...nRepo.java => OrganizationRepository.java} | 0 .../model/organization/OrganizationTest.java | 46 +++++++++++-------- 2 files changed, 27 insertions(+), 19 deletions(-) rename src/main/java/edu/group5/app/model/organization/{OrganizationRepo.java => OrganizationRepository.java} (100%) diff --git a/src/main/java/edu/group5/app/model/organization/OrganizationRepo.java b/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java similarity index 100% rename from src/main/java/edu/group5/app/model/organization/OrganizationRepo.java rename to src/main/java/edu/group5/app/model/organization/OrganizationRepository.java diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java index 3b086c3..9568ab5 100644 --- a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java +++ b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java @@ -5,82 +5,90 @@ import static org.junit.jupiter.api.Assertions.*; class OrganizationTest { - + + @Test + void constructor_CreatesAnOrganizationWhenInputIsValid() { + Organization org = new Organization( + 1, + "Org", + true, + "org.com", + true, + "Org description" + ); + + assertEquals(1, org.orgNumber()); + } + @Test void constructor_ThrowsWhenOrgNumberIsNegative() { - assertThrows(IllegalArgumentException.class, () -> {new Organization( + assertThrows(IllegalArgumentException.class, () -> new Organization( -1, "Org", true, null, true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenNameIsNull() { - assertThrows(NullPointerException.class, () -> {new Organization( + assertThrows(NullPointerException.class, () -> new Organization( 1, null, true, "org.com", true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenNameIsBlank() { - assertThrows(IllegalArgumentException.class, () -> {new Organization( + assertThrows(IllegalArgumentException.class, () -> new Organization( 1, "", true, "org.com", true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenWebsiteURLIsNull() { - assertThrows(NullPointerException.class, () -> {new Organization( + assertThrows(NullPointerException.class, () -> new Organization( 1, "Org", true, null, true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenWebsiteURLIsBlank() { - assertThrows(IllegalArgumentException.class, () -> {new Organization( + assertThrows(IllegalArgumentException.class, () -> new Organization( 1, "Org", true, "", true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenDescriptionIsNull() { - assertThrows(NullPointerException.class, () -> {new Organization( + assertThrows(NullPointerException.class, () -> new Organization( 1, "Org", true, "org.com", true, null - ); - }); + )); } } \ No newline at end of file From ee4a9cadfc9a94dbf3c3b0c01137aaee2b724560 Mon Sep 17 00:00:00 2001 From: emilfa Date: Sun, 1 Mar 2026 14:42:00 +0100 Subject: [PATCH 15/20] test: created tests for the OrganizationRepository --- .../organization/OrganizationRepoTest.java | 4 -- .../OrganizationRepositoryTest.java | 57 +++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) delete mode 100644 src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java create mode 100644 src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java deleted file mode 100644 index 780bf8e..0000000 --- a/src/test/java/edu/group5/app/model/organization/OrganizationRepoTest.java +++ /dev/null @@ -1,4 +0,0 @@ -import static org.junit.jupiter.api.Assertions.*; -class OrganizationRepoTest { - -} \ No newline at end of file diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java new file mode 100644 index 0000000..3249078 --- /dev/null +++ b/src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java @@ -0,0 +1,57 @@ +package edu.group5.app.model.organization; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class OrganizationRepositoryTest { + + private Map content; + private Organization trustedOrganization1; + private Organization trustedOrganization2; + private Organization untrustedOrganization1; + private Organization untrustedOrganization2; + private OrganizationRepository repository; + + @BeforeEach + void setUp() { + content = new HashMap<>(); + + trustedOrganization1 = + new Organization(1, "Trusted Org1", true, "org.com", true, "description"); + trustedOrganization2 = + new Organization(2, "Trusted Org2", true, "org.com", true, "description"); + untrustedOrganization1 = + new Organization(3, "Untrusted Org1", false, "org.com", true, "description"); + untrustedOrganization2 = + new Organization(4, "Untrusted Org2", false, "org.com", true, "description"); + + content.put(1, trustedOrganization1); + content.put(2, trustedOrganization2); + content.put(3, untrustedOrganization1); + content.put(4, untrustedOrganization2); + + repository = new OrganizationRepository(content); + } + + @Test + void constructor_ThrowsWhenContentIsNull() { + assertThrows(NullPointerException.class, () -> new OrganizationRepository(null)); + } + + @Test + void getTrustedOrganizations_OnlyReturnsTrustedOrganizations() { + Map trusted = repository.getTrustedOrganizations(); + + assertEquals(2, trusted.size()); + assertTrue(trusted.containsKey(1)); + assertTrue(trusted.containsKey(2)); + assertFalse(trusted.containsKey(3)); + assertFalse(trusted.containsKey(4)); + assertTrue(trusted.values().stream().allMatch(Organization::trusted)); + } +} \ No newline at end of file From e2c0f1a25e0a3b658033787603101dc9ce70b0f8 Mon Sep 17 00:00:00 2001 From: emilfa Date: Sun, 1 Mar 2026 14:42:47 +0100 Subject: [PATCH 16/20] refactor: minor changes to OrganizationRepository --- .../organization/OrganizationRepository.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java b/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java index 27b128f..a9e5bb6 100644 --- a/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java +++ b/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java @@ -3,38 +3,48 @@ import edu.group5.app.model.Repository; import java.util.HashMap; +import java.util.Map; import java.util.Objects; /** - * Handles business logic associated with organizations + * Handles the business logic associated with organizations */ -public class OrganizationRepo extends Repository { - private final HashMap content; +public class OrganizationRepository extends Repository { + private final Map content; /** * Creates a new Organization Repository * - * @param content holds all current organizations in the repository + * @param content holds all current organizations in the repository; must not be null * @throws NullPointerException if content is null */ - public OrganizationRepo(HashMap content) { + public OrganizationRepository(Map content) { this.content = Objects.requireNonNull(content, "content cannot be null"); super(content); } + /** + * Returns the organizations within the repository. + * @return all organizations within the repository. + */ + @Override + public Map getContent() { + return content; + } + /** * Gets all trusted organizations in the repository * @return all organizations with trusted = true */ - public HashMap getTrustedOrganizations() { - HashMap trustedOrgs = new HashMap<>(); + public Map getTrustedOrganizations() { + Map trustedOrganizations = new HashMap<>(); content.forEach((orgNr, org) -> { if (org.trusted()) { - trustedOrgs.put(orgNr, org); + trustedOrganizations.put(orgNr, org); } }); - return trustedOrgs; + return trustedOrganizations; } } From 7f88fa1876e87bc9874fc3066a6212e3303dfcfd Mon Sep 17 00:00:00 2001 From: emilfa Date: Sun, 1 Mar 2026 16:04:39 +0100 Subject: [PATCH 17/20] refactor: minor changes to OrganizationRepositoryTest --- .../OrganizationRepositoryTest.java | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java index 3249078..3a3392e 100644 --- a/src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java +++ b/src/test/java/edu/group5/app/model/organization/OrganizationRepositoryTest.java @@ -10,25 +10,16 @@ class OrganizationRepositoryTest { - private Map content; - private Organization trustedOrganization1; - private Organization trustedOrganization2; - private Organization untrustedOrganization1; - private Organization untrustedOrganization2; private OrganizationRepository repository; @BeforeEach void setUp() { - content = new HashMap<>(); - - trustedOrganization1 = - new Organization(1, "Trusted Org1", true, "org.com", true, "description"); - trustedOrganization2 = - new Organization(2, "Trusted Org2", true, "org.com", true, "description"); - untrustedOrganization1 = - new Organization(3, "Untrusted Org1", false, "org.com", true, "description"); - untrustedOrganization2 = - new Organization(4, "Untrusted Org2", false, "org.com", true, "description"); + Map content = new HashMap<>(); + + Organization trustedOrganization1 = new Organization(1, "Trusted Org1", true, "org.com", true, "description"); + Organization trustedOrganization2 = new Organization(2, "Trusted Org2", true, "org.com", true, "description"); + Organization untrustedOrganization1 = new Organization(3, "Untrusted Org1", false, "org.com", true, "description"); + Organization untrustedOrganization2 = new Organization(4, "Untrusted Org2", false, "org.com", true, "description"); content.put(1, trustedOrganization1); content.put(2, trustedOrganization2); From 23c7524e507a0379ffd0dbfebaf3d83ccda0653e Mon Sep 17 00:00:00 2001 From: emilfa Date: Tue, 3 Mar 2026 13:39:27 +0100 Subject: [PATCH 18/20] refactor: made Repository use generics instead of Object type --- src/main/java/edu/group5/app/model/Repository.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/group5/app/model/Repository.java b/src/main/java/edu/group5/app/model/Repository.java index d0d2792..6850bfe 100644 --- a/src/main/java/edu/group5/app/model/Repository.java +++ b/src/main/java/edu/group5/app/model/Repository.java @@ -1,12 +1,14 @@ package edu.group5.app.model; +import java.util.Map; + /** * Represents a repository */ -public abstract class Repository { - protected final Object content; +public abstract class Repository { + protected final Map content; - public Repository(Object content) { + public Repository(Map content) { this.content = content; } @@ -14,7 +16,7 @@ public Repository(Object content) { * Gets the content of the repo * @return content of the repo */ - public Object getContent() { + public Map getContent() { return content; } } From 662c4cee9832fb55e09a60e49ba6b18790564baa Mon Sep 17 00:00:00 2001 From: emilfa Date: Tue, 3 Mar 2026 13:40:17 +0100 Subject: [PATCH 19/20] refactor: made OrganizationRepository consistent with Repository --- .../organization/OrganizationRepository.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java b/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java index a9e5bb6..14a77d0 100644 --- a/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java +++ b/src/main/java/edu/group5/app/model/organization/OrganizationRepository.java @@ -9,9 +9,7 @@ /** * Handles the business logic associated with organizations */ -public class OrganizationRepository extends Repository { - private final Map content; - +public class OrganizationRepository extends Repository { /** * Creates a new Organization Repository * @@ -19,17 +17,7 @@ public class OrganizationRepository extends Repository { * @throws NullPointerException if content is null */ public OrganizationRepository(Map content) { - this.content = Objects.requireNonNull(content, "content cannot be null"); - super(content); - } - - /** - * Returns the organizations within the repository. - * @return all organizations within the repository. - */ - @Override - public Map getContent() { - return content; + super(Objects.requireNonNull(content, "content cannot be null")); } /** From 81a0a4372a23fd1cc496b72b714798f6c81b87ae Mon Sep 17 00:00:00 2001 From: emilfa Date: Tue, 3 Mar 2026 13:57:54 +0100 Subject: [PATCH 20/20] refactor: made the positive test for Organization more robust --- .../app/model/organization/Organization.java | 10 +++- .../model/organization/OrganizationTest.java | 55 ++++++++++++------- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/main/java/edu/group5/app/model/organization/Organization.java b/src/main/java/edu/group5/app/model/organization/Organization.java index 885f0ed..941ed5a 100644 --- a/src/main/java/edu/group5/app/model/organization/Organization.java +++ b/src/main/java/edu/group5/app/model/organization/Organization.java @@ -15,8 +15,14 @@ *
  • description must not be null
  • * */ -public record Organization(int orgNumber, String name, boolean trusted, String websiteURL, boolean isPreApproved, - String description) { +public record Organization( + int orgNumber, + String name, + boolean trusted, + String websiteURL, + boolean isPreApproved, + String description +) { /** * Creates a new organization. * diff --git a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java index 3b086c3..7f1b898 100644 --- a/src/test/java/edu/group5/app/model/organization/OrganizationTest.java +++ b/src/test/java/edu/group5/app/model/organization/OrganizationTest.java @@ -5,82 +5,97 @@ import static org.junit.jupiter.api.Assertions.*; class OrganizationTest { - + + @Test + void constructor_CreatesAnOrganizationWhenInputIsValid() { + Organization org = new Organization( + 1, + "Org", + true, + "org.com", + true, + "Org description" + ); + + assertAll( + () -> assertEquals(1, org.orgNumber()), + () -> assertEquals("Org", org.name()), + () -> assertTrue(org.trusted()), + () -> assertEquals("org.com", org.websiteURL()), + () -> assertTrue(org.isPreApproved()), + () -> assertEquals("Org description", org.description()) + ); + } + @Test void constructor_ThrowsWhenOrgNumberIsNegative() { - assertThrows(IllegalArgumentException.class, () -> {new Organization( + assertThrows(IllegalArgumentException.class, () -> new Organization( -1, "Org", true, - null, + "org.com", true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenNameIsNull() { - assertThrows(NullPointerException.class, () -> {new Organization( + assertThrows(NullPointerException.class, () -> new Organization( 1, null, true, "org.com", true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenNameIsBlank() { - assertThrows(IllegalArgumentException.class, () -> {new Organization( + assertThrows(IllegalArgumentException.class, () -> new Organization( 1, "", true, "org.com", true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenWebsiteURLIsNull() { - assertThrows(NullPointerException.class, () -> {new Organization( + assertThrows(NullPointerException.class, () -> new Organization( 1, "Org", true, null, true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenWebsiteURLIsBlank() { - assertThrows(IllegalArgumentException.class, () -> {new Organization( + assertThrows(IllegalArgumentException.class, () -> new Organization( 1, "Org", true, "", true, "Org description" - ); - }); + )); } @Test void constructor_ThrowsWhenDescriptionIsNull() { - assertThrows(NullPointerException.class, () -> {new Organization( + assertThrows(NullPointerException.class, () -> new Organization( 1, "Org", true, "org.com", true, null - ); - }); + )); } } \ No newline at end of file