diff --git a/docs/SqlDatabase/ER-Diagram v5.png b/docs/SqlDatabase/ER-Diagram v5.png new file mode 100644 index 0000000..df22994 Binary files /dev/null and b/docs/SqlDatabase/ER-Diagram v5.png differ diff --git a/docs/SqlDatabase/ER-DiagramFile.mwb b/docs/SqlDatabase/ER-DiagramFile.mwb index ee90f5e..15edab1 100644 Binary files a/docs/SqlDatabase/ER-DiagramFile.mwb and b/docs/SqlDatabase/ER-DiagramFile.mwb differ diff --git a/docs/SqlDatabase/ER-DiagramFile.mwb.bak b/docs/SqlDatabase/ER-DiagramFile.mwb.bak index 64d9533..c348da3 100644 Binary files a/docs/SqlDatabase/ER-DiagramFile.mwb.bak and b/docs/SqlDatabase/ER-DiagramFile.mwb.bak differ diff --git a/helpmehelpapplication/.ai/mcp/mcp.json b/helpmehelpapplication/.ai/mcp/mcp.json new file mode 100644 index 0000000..e69de29 diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/DonationDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/DonationDAO.java index c99056f..8b6cbf4 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/DonationDAO.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/DonationDAO.java @@ -4,6 +4,7 @@ import java.util.UUID; import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.user.User; /** * This class is responsible for sending concurrent information about the donation to the Donation @@ -19,11 +20,11 @@ public class DonationDAO { * @param charity * @param amount */ - public static void addDonation(Charity charity, double amount) { + public static void addDonation(Charity charity, User user, double amount) { String sql_query = """ - INSERT INTO Donations (UUID_Donations, amount, date, Charities_UUID_charities) - VALUES (?, ?, ?, ?) + INSERT INTO Donations (UUID_Donations, amount, date, charity_id, user_id) + VALUES (?, ?, ?, ?, ?) """; try (Connection conn = connection.getMySqlConnection(); PreparedStatement ps = conn.prepareStatement(sql_query)) { @@ -33,6 +34,8 @@ INSERT INTO Donations (UUID_Donations, amount, date, Charities_UUID_charities) ps.setDouble(2, amount); ps.setDate(3, new Date(System.currentTimeMillis())); ps.setString(4, charity.getUUID().toString()); + ps.setString(5, user.getId().toString()); + ps.executeUpdate(); conn.commit(); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/UserDAO.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/UserDAO.java index f1ce4aa..19c7714 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/UserDAO.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/DAO/UserDAO.java @@ -7,8 +7,8 @@ import ntnu.systemutvikling.team6.models.user.User; /** - * This class is responsible for sending concurrent information about the user to the User - * database, and user settings to the settings database. + * This class is responsible for sending concurrent information about the user to the User database, + * and user settings to the settings database. * * @author Robin Strand Prestmo */ diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java index fc3588d..a78be83 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/HmHApplication.java @@ -9,7 +9,7 @@ import ntnu.systemutvikling.team6.database.DatabaseSetup; import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.registry.CharityRegistry; -import ntnu.systemutvikling.team6.scraper.APICharityScraper; +import ntnu.systemutvikling.team6.scraper.scraperComponents.APICharityScraper; import ntnu.systemutvikling.team6.service.APIToDatabaseService; public class HmHApplication extends Application { @@ -49,6 +49,7 @@ public void init() { try { HttpClient https = HttpClient.newHttpClient(); APICharityScraper scraper = new APICharityScraper(https); + DatabaseConnection conn = new DatabaseConnection(); APIToDatabaseService db = new APIToDatabaseService(conn); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java index 0ce757f..d07910c 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/DonationPageController.java @@ -9,6 +9,7 @@ import javafx.scene.control.TextField; import ntnu.systemutvikling.team6.DAO.DonationDAO; import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.user.User; /** * This controller represents the donation page, where the user can enter a donation amount and @@ -97,7 +98,7 @@ public void Donate(ActionEvent event) { if (result.isPresent() && result.get() == ButtonType.OK) { // Process donation - processDonation(charity, amount); + //processDonation(charity, user, amount); showAlert( Alert.AlertType.INFORMATION, "Thank you!", @@ -114,8 +115,8 @@ public void Donate(ActionEvent event) { * @param charity * @param amount */ - public void processDonation(Charity charity, double amount) { - DonationDAO.addDonation(charity, amount); + public void processDonation(Charity charity, User user, double amount) { + DonationDAO.addDonation(charity, user, amount); } /** diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java index 3dc7f4c..91ac90c 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/controller/FrontpageController.java @@ -16,8 +16,8 @@ import ntnu.systemutvikling.team6.database.Readers.CharitySelect; import ntnu.systemutvikling.team6.database.Readers.DonationSelect; import ntnu.systemutvikling.team6.models.Charity; -import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import ntnu.systemutvikling.team6.models.Donation; +import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import ntnu.systemutvikling.team6.models.registry.DonationRegistry; /** diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseManager.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseManager.java deleted file mode 100644 index 4f6d3ae..0000000 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseManager.java +++ /dev/null @@ -1,384 +0,0 @@ -package ntnu.systemutvikling.team6.database; - -import java.sql.*; -import java.util.*; - -import ntnu.systemutvikling.team6.models.Charity; -import ntnu.systemutvikling.team6.models.registry.CharityRegistry; -import ntnu.systemutvikling.team6.models.Donation; -import ntnu.systemutvikling.team6.models.registry.DonationRegistry; -import ntnu.systemutvikling.team6.scraper.APICharityData; -import ntnu.systemutvikling.team6.scraper.LogoDownloader; -import ntnu.systemutvikling.team6.scraper.URLCharityScraper; - -/** - * Manages the Database with MySQL tables and JDBC. - * - *

This class is responsible for creating the tables needed for the application, if not done - * already and maintaining the {@code charities} table based on data retrieved from the IK API. It - * is also responsible for retrieving the data from the database and sending it to the application - * through the CharityRegistry and DonationRegistry. It is used by the FrontpageController to - * retrieve the data needed to display the charities - */ -public class DatabaseManager { - private final DatabaseConnection connection; - - /** - * Contractor for DatabaseManager. It uses a DatabaseConnection object that contains a connection - * credentials. - */ - public DatabaseManager() { - this.connection = new DatabaseConnection(); - } - - /** - * Connection test for the Database. Does a simple SELECT SQL query and returns either true og and - * Exception if failed - * - * @return true if Sucsedd or SQLExepction if failed - */ - public boolean testConnection() { - try (Connection conn = connection.getMySqlConnection(); - Statement stmt = conn.createStatement()) { - - ResultSet rs = stmt.executeQuery("SELECT 1"); - - if (rs.next()) { - System.out.println("Database connection verified."); - return true; - } - - } catch (SQLException e) { - System.out.println("Database connection failed."); - e.printStackTrace(); - } - - return false; - } - - /** - * Creates the {@code Charities} and {@code Donations} tables if they do not already exist. - * - *

The table structure for Charities is based on fields from {@link APICharityData}. - * - * @throws RuntimeException if a {@link SQLException} occurs while creating the table - */ - public void createTables() { - String sql_query1 = - """ - -- ----------------------------------------------------- - -- Table `HelpMeHelp`.`Charities` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS Charities ( - UUID_charities CHAR(36) PRIMARY KEY, - org_number VARCHAR(255) NOT NULL, - charity_name VARCHAR(255) NOT NULL, - charity_link VARCHAR(255) NOT NULL, - pre_approved TINYINT NOT NULL, - status VARCHAR(255) NOT NULL, - description TEXT, - logoURL TEXT, - categories TEXT, - key_values TEXT, - logoBlob MEDIUMBLOB, - UNIQUE KEY unique_org_number (org_number) - ) ENGINE=InnoDB; - - - """; - String sql_query2 = - """ - -- ----------------------------------------------------- - -- Table `HelpMeHelp`.`Donations` - -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS Donations ( - `UUID_Donations` CHAR(36) NOT NULL, - `amount` DECIMAL NOT NULL, - `date` DATE NOT NULL, - `Charities_UUID_charities` CHAR(36) NOT NULL, - PRIMARY KEY (`UUID_Donations`), - INDEX `fk_Donations_Charities_idx` (`Charities_UUID_charities` ASC) VISIBLE, - CONSTRAINT `fk_Donations_Charities` - FOREIGN KEY (`Charities_UUID_charities`) - REFERENCES Charities (`UUID_charities`) - ON DELETE CASCADE - ON UPDATE CASCADE) - ENGINE = InnoDB; - """; - - try (Connection conn = connection.getMySqlConnection(); - Statement s = conn.createStatement()) { - - s.execute(sql_query1); - s.execute(sql_query2); - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("Error creating table."); - } - } - - /** - * This method is used to verify the integrity of the data in the {@code charities} table and to - * update it based on the data retrieved from the IK API and the charity's URL. - * The param charities are retrieved from - * the IK API through the APICharityData class. Called in initialize method in - * HmHApplication.java, which is the main class of the application, to ensure that the data is up - * to date when the application starts. Uses a temp table to ensure that the data in the database - * is consistent with the data from the API. - *

Uses a URLScraper object to get data not contained in the API, and static methods from - * LogoDownloader to get the charity's logo as a blob.

- * - * @param charities a list of {@code Charity} objects to add to the database - */ - public void addAPIDataToTable(List charities) { - Connection conn = null; - int charityCounter = 0; - - // Scrapes description, logo, categories, and key values from IK - for (Charity charity : charities) { - charityCounter++; - - System.out.println("Scraping charity " + charityCounter + " of " + charities.size()); - URLCharityScraper urlScraper = new URLCharityScraper(charity.getURL()); - urlScraper.scrapeCharityPage(); - - charity.setDescription(urlScraper.getDescription()); - charity.setCategory(urlScraper.getCategories()); - charity.setLogoURL(urlScraper.getLogoURL()); - charity.setKeyValues(urlScraper.getKeyValues()); - byte[] logoBlob = LogoDownloader.downloadImageAsBlob(charity.getLogoURL()); - charity.setLogoBlob(logoBlob); - } - try { - conn = connection.getMySqlConnection(); - conn.setAutoCommit(false); - String sql_query = - """ - INSERT INTO Charities (UUID_charities, org_number, charity_name, charity_link, pre_approved, status, description, logoURL, categories, key_values, logoBlob) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - ON DUPLICATE KEY UPDATE - charity_name = VALUES(charity_name), - charity_link = VALUES(charity_link), - pre_approved = VALUES(pre_approved), - status = VALUES(status), - description = VALUES(description), - logoURL = VALUES(logoURL), - categories = VALUES(categories), - key_values = VALUES(key_values), - logoBlob = VALUES(logoBlob) - """; - - try (PreparedStatement ps = conn.prepareStatement(sql_query)) { - for (Charity charity : charities) { - if (charity.getUUID() == null) { - ps.setString(1, UUID.randomUUID().toString()); - } else { - ps.setString(1, charity.getUUID().toString()); - } - - ps.setString(2, charity.getOrg_number().replaceAll("\\s", "")); - ps.setString(3, charity.getName()); - ps.setString(4, charity.getURL()); - ps.setBoolean(5, charity.getPreApproved()); - ps.setString(6, charity.getStatus()); - ps.setString(7, charity.getDescription()); - ps.setString(8, charity.getLogoURL()); - ps.setString(9, charity.getCategory()); - ps.setString(10, charity.getKeyValues()); - ps.setBytes(11, charity.getLogoBlob()); - - ps.addBatch(); - } - ps.executeBatch(); - } - - // -- Intergerty Check: - String createTemp = - """ - CREATE TEMPORARY TABLE temp_api_charities ( - org_number VARCHAR(20) PRIMARY KEY - ) - """; - - try (PreparedStatement ps = conn.prepareStatement(createTemp)) { - ps.execute(); - } - - String insertTemp = "INSERT IGNORE INTO temp_api_charities (org_number) VALUES (?)"; - - try (PreparedStatement ps = conn.prepareStatement(insertTemp)) { - - for (Charity charity : charities) { - ps.setString(1, charity.getOrg_number().replaceAll("\\s", "")); - ps.addBatch(); - } - - ps.executeBatch(); - } - - String deleteSql = - """ - DELETE FROM Charities c - WHERE NOT EXISTS ( - SELECT 1 - FROM temp_api_charities t - WHERE t.org_number = c.org_number - ) - """; - - try (PreparedStatement ps = conn.prepareStatement(deleteSql)) { - ps.executeUpdate(); - } - - conn.commit(); - - } catch (SQLException e) { - if (conn != null) { - try { - conn.rollback(); - } catch (SQLException ex) { - ex.printStackTrace(); - } - } - e.printStackTrace(); - - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } finally { - if (conn != null) { - try { - conn.setAutoCommit(true); - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - } - } - - /** - * Fetches the data stored in the database and converts it to a list of Charity objects - * in the form of a registry (CharityRegistry). - * - * @return a CharityRegistry of all the charities registered in the database - */ - public CharityRegistry getCharitiesFromDB() { - CharityRegistry registry = null; - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - "SELECT UUID_charities, org_number, charity_name, charity_link, pre_approved, status, description, logoURL, " + - "categories, key_values, logoBlob FROM Charities"; - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql_query); - - registry = new CharityRegistry(); - while (rs.next()) { - Charity charity = - new Charity( - rs.getString("UUID_charities"), - rs.getString("org_number"), - rs.getString("charity_link"), - rs.getString("charity_name"), - rs.getBoolean("pre_approved"), - rs.getString("status")); - charity.setDescription(rs.getString("description")); - charity.setLogoURL(rs.getString("logoURL")); - charity.setCategory(rs.getString("categories")); - charity.setKeyValues(rs.getString("key_values")); - charity.setLogoBlob(rs.getBytes("logoBlob")); - - registry.addCharity(charity); - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - return registry; - } - - public List getCategoriesFromDB() { - Map categoryMap = new HashMap<>(); - - String sql_query = "SELECT categories FROM Charities"; - - try (Connection conn = connection.getMySqlConnection(); - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql_query)) { - - while (rs.next()) { - String categoriesStr = rs.getString("categories"); - - if (categoriesStr != null && !categoriesStr.isEmpty()) { - String[] splitCategories = categoriesStr.split(","); - - for (String category : splitCategories) { - String trimmed = category.trim(); - - if (!trimmed.isEmpty()) { - categoryMap.putIfAbsent(trimmed.toLowerCase(), trimmed); - } - } - } - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong while fetching categories from the database."); - } - - var categories = new ArrayList<>(categoryMap.values()); - Collections.sort(categories); - - return categories; - } - - public DonationRegistry getDonationFromDB() { - DonationRegistry registry = null; - Connection conn = null; - try { - conn = connection.getMySqlConnection(); - String sql_query = - """ - SELECT - d.UUID_Donations, - d.amount, - d.date, - c.UUID_charities, - c.org_number, - c.charity_name, - c.charity_link, - c.pre_approved, - c.status - FROM Donations d - JOIN Charities c - ON d.Charities_UUID_charities = c.UUID_charities - """; - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql_query); - - registry = new DonationRegistry(); - while (rs.next()) { - Charity charity = - new Charity( - rs.getString("UUID_charities"), - rs.getString("org_number"), - rs.getString("charity_name"), - rs.getString("charity_link"), - rs.getBoolean("pre_approved"), - rs.getString("status")); - - Donation donation = - new Donation( - rs.getString("UUID_Donations"), - rs.getDouble("amount"), - rs.getDate("date").toLocalDate(), - charity); - registry.addDonation(donation); - } - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("ERROR: Something went wrong during updating charities table."); - } - return registry; - } -} \ No newline at end of file diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java index 62de2e8..e5775da 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/DatabaseSetup.java @@ -57,18 +57,14 @@ public void createTables() { -- ----------------------------------------------------- -- Table `HelpMeHelp`.`Charities` -- ----------------------------------------------------- - CREATE TABLE IF NOT EXISTS `apbaluna`.`Charities` ( - `UUID_charities` CHAR(36) NOT NULL, - `org_number` VARCHAR(255) NOT NULL, - `charity_name` VARCHAR(255) NOT NULL, - `charity_description` VARCHAR(255) NOT NULL, - `charity_link` VARCHAR(255) NOT NULL, - `pre_approved` TINYINT NOT NULL, - `status` VARCHAR(255) NOT NULL, - PRIMARY KEY (`UUID_charities`), - UNIQUE INDEX `org_number_UNIQUE` (`org_number` ASC) VISIBLE) - ENGINE = InnoDB; - + CREATE TABLE IF NOT EXISTS `apbaluna`.`Charities` ( + `UUID_charities` CHAR(36) NOT NULL, + `org_number` VARCHAR(255) NOT NULL, + `pre_approved` TINYINT NOT NULL, + `status` VARCHAR(255) NOT NULL, + PRIMARY KEY (`UUID_charities`), + UNIQUE INDEX `org_number_UNIQUE` (`org_number` ASC) VISIBLE) + ENGINE = InnoDB; """; String donationsTable = """ @@ -118,14 +114,14 @@ PRIMARY KEY (`UUID_User`)) -- Table `apbaluna`.`Settings` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `apbaluna`.`Settings` ( - `User_UUID_User` CHAR(36) NOT NULL, + `UUID_user` CHAR(36) NOT NULL, `isAnonymous` TINYINT NOT NULL, `language` VARCHAR(45) NOT NULL, `lightmode` TINYINT NOT NULL, - PRIMARY KEY (`User_UUID_User`), - INDEX `fk_Settings_User1_idx` (`User_UUID_User` ASC) VISIBLE, + PRIMARY KEY (`UUID_user`), + INDEX `fk_Settings_User1_idx` (`UUID_user` ASC) VISIBLE, CONSTRAINT `fk_Settings_User1` - FOREIGN KEY (`User_UUID_User`) + FOREIGN KEY (`UUID_user`) REFERENCES `apbaluna`.`User` (`UUID_User`) ON DELETE NO ACTION ON UPDATE NO ACTION) @@ -253,6 +249,25 @@ FOREIGN KEY (`User_UUID_User`) ON UPDATE NO ACTION) ENGINE = InnoDB; """; + String charityVanityTable = + """ + CREATE TABLE IF NOT EXISTS `apbaluna`.`CharityVanity` ( + `UUID_charity` CHAR(36) NOT NULL, + `charity_name` VARCHAR(255) NOT NULL, + `charity_link` VARCHAR(255) NOT NULL, + `description` TEXT NULL, + `logoURL` TEXT NULL, + `key_values` TEXT NULL, + `logoBLOB` MEDIUMBLOB NULL, + INDEX `fk_CharityVanity_Charities1_idx` (`UUID_charity` ASC) VISIBLE, + PRIMARY KEY (`UUID_charity`), + CONSTRAINT `fk_CharityVanity_Charities1` + FOREIGN KEY (`UUID_charity`) + REFERENCES `apbaluna`.`Charities` (`UUID_charities`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) + ENGINE = InnoDB; + """; try (Connection conn = connection.getMySqlConnection(); Statement s = conn.createStatement()) { @@ -266,6 +281,7 @@ FOREIGN KEY (`User_UUID_User`) s.execute(categoriesTable); s.execute(charityCategoriesTable); s.execute(charityUserTable); + s.execute(charityVanityTable); } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("Error creating table."); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java index cdcee40..a3b5d32 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/CharitySelect.java @@ -3,10 +3,14 @@ import java.sql.*; import java.time.LocalDate; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.models.Charity; -import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import ntnu.systemutvikling.team6.models.Feedback; +import ntnu.systemutvikling.team6.models.registry.CharityRegistry; +import ntnu.systemutvikling.team6.models.user.Language; +import ntnu.systemutvikling.team6.models.user.Settings; import ntnu.systemutvikling.team6.models.user.User; /** @@ -34,11 +38,12 @@ public CharitySelect(DatabaseConnection connection) { * Retrieves all charities from the database, including their associated feedback and the users * who submitted each piece of feedback. * - *

The query performs a LEFT JOIN between the {@code Charities}, {@code Feedback}, and {@code - * User} tables. Each unique charity is added once to the registry; any feedback rows found for - * that charity are appended to its feedback list. + *

The query performs a LEFT JOIN between the {@code Charities}, {@code Feedback}, {@code + * User}, {@code CharityVanity}, and {@code category(s)} tables. Each unique charity is added once + * to the registry; any feedback rows found for that charity are appended to its feedback list. * - *

Note: charities with no feedback are still included in the result due to the LEFT JOIN. + *

Note: charities with no feedback and categories are still included in the result due to the + * LEFT JOIN. * * @return a {@link CharityRegistry} containing all charities found in the database, each * populated with its associated {@link Feedback} objects (if any) @@ -51,20 +56,27 @@ public CharityRegistry getCharitiesFromDB() { conn = connection.getMySqlConnection(); String sql_query = """ - SELECT - c.UUID_charities, c.org_number, c.charity_name, c.charity_link, c.pre_approved, c.status, - f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, - u.UUID_user, u.user_name, u.user_email, u.user_password, u.role - FROM Charities c - LEFT JOIN Feedback f ON f.charity_id = c.UUID_charities - LEFT JOIN User u ON f.user_id = u.UUID_user - """; + SELECT + c.UUID_charities, c.org_number, c.pre_approved, c.status, + f.UUID_feedback, f.feedback_comment, f.feedback_date, f.isAnonymous, f.charity_id, f.user_id, + cv.charity_name, cv.charity_link, cv.description, cv.logoURL, cv.key_values, cv.logoBLOB, + u.UUID_user, u.user_name, u.user_email, u.user_password, u.role, + cat.category + FROM Charities c + LEFT JOIN Feedback f ON f.charity_id = c.UUID_charities + LEFT JOIN User u ON f.user_id = u.UUID_user + LEFT JOIN Charity_Categories cc ON cc.Charities_UUID_charities = c.UUID_charities + LEFT JOIN Cateegories cat ON cat.category_id = cc.Categories_category_id + INNER JOIN CharityVanity cv ON cv.UUID_charity = c.UUID_charities; + """; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql_query); Charity currentCharity = null; String lastCharity = null; + Set seenFeedbackIds = new HashSet<>(); + registry = new CharityRegistry(); while (rs.next()) { String currentId = rs.getString("UUID_charities"); @@ -74,33 +86,47 @@ public CharityRegistry getCharitiesFromDB() { new Charity( rs.getString("UUID_charities"), rs.getString("org_number"), - rs.getString("charity_link"), rs.getString("charity_name"), + rs.getString("charity_link"), + rs.getString("status"), rs.getBoolean("pre_approved"), - rs.getString("status")); + rs.getString("description"), + rs.getString("logoURL"), + rs.getString("key_values"), + rs.getBytes("logoBLOB")); registry.addCharity(currentCharity); lastCharity = currentId; + seenFeedbackIds.clear(); + } + + String categoryName = rs.getString("category"); + if (categoryName != null & !currentCharity.getCategory().contains(categoryName)) { + currentCharity.getCategory().add(categoryName); } + String feedbackId = rs.getString("UUID_feedback"); - if (feedbackId != null) { - User userWithNoSettingsAndInbox = + if (feedbackId != null && !seenFeedbackIds.contains(feedbackId)) { + seenFeedbackIds.add(feedbackId); + User userWithMinimalSettingsAndInbox = new User( rs.getString("UUID_User"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), rs.getString("role")); + userWithMinimalSettingsAndInbox.setSettings(new Settings(false, Language.ENGLISH, false)); Feedback feedback = new Feedback( rs.getString("UUID_feedback"), - userWithNoSettingsAndInbox, + userWithMinimalSettingsAndInbox, rs.getString("feedback_comment"), LocalDate.parse(rs.getString("feedback_date"))); currentCharity.getFeedbacks().add(feedback); } } + } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("ERROR: Something went wrong during updating charities table."); @@ -142,17 +168,18 @@ public ArrayList getFeedbackforCharityUUID(String charity_uuid) { ResultSet rs = stmt.executeQuery(); while (rs.next()) { - User userWithNoSettingsAndInbox = + User userWithSettingsAndNoInbox = new User( rs.getString("UUID_User"), rs.getString("user_name"), rs.getString("user_email"), rs.getString("user_password"), rs.getString("role")); + userWithSettingsAndNoInbox.setSettings(new Settings(false, Language.NORWEGIAN, false)); Feedback feedback = new Feedback( rs.getString("UUID_feedback"), - userWithNoSettingsAndInbox, + userWithSettingsAndNoInbox, rs.getString("feedback_comment"), LocalDate.parse(rs.getString("feedback_date"))); Feedbacks.add(feedback); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java index 5990fc3..1183d75 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/DonationSelect.java @@ -8,13 +8,20 @@ import ntnu.systemutvikling.team6.models.Charity; import ntnu.systemutvikling.team6.models.Donation; import ntnu.systemutvikling.team6.models.registry.DonationRegistry; +import ntnu.systemutvikling.team6.models.user.User; /** * Data access class responsible for reading donation data from the database. * - *

Retrieves donations along with their associated charity information by performing an INNER - * JOIN between the {@code Donations} and {@code Charities} tables. Only donations that have a - * matching charity record are returned. + *

Retrieves donations along with their associated {@link Charity} by performing an INNER JOIN + * between the {@code Donations} and {@code Charities} tables. Only donations with a matching + * charity record are included. Donor ({@link User}) and {@code CharityVanity} details are + * intentionally excluded to keep this query lightweight — join those separately if richer data is + * needed. + * + *

Note: {@code CharityVanity} fields (name, link, description, logo) are NOT fetched here since + * they live in a separate table. The {@link Charity} objects returned will only contain the core + * fields present in the {@code Charities} table. */ public class DonationSelect { @@ -50,18 +57,12 @@ public DonationRegistry getDonationFromDB() { String sql_query = """ SELECT - d.UUID_Donations, - d.amount, - d.date, - c.UUID_charities, - c.org_number, - c.charity_name, - c.charity_link, - c.pre_approved, - c.status + d.UUID_Donations, d.amount, d.isAnonymous, d.date, d.charity_id, d.user_id, + c.UUID_charities, c.org_number, c,pre_approved, c.status, + u.UUID_User, u.user_name, u.user_email, u.user_password, u.role FROM Donations d - JOIN Charities c - ON d.Charities_UUID_charities = c.UUID_charities + INNER JOIN Charities c ON d.charity_id = c.UUID_charities + INNER JOIN User u ON d.user_id = u.UUID_user """; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql_query); @@ -72,17 +73,24 @@ public DonationRegistry getDonationFromDB() { new Charity( rs.getString("UUID_charities"), rs.getString("org_number"), - rs.getString("charity_name"), - rs.getString("charity_link"), rs.getBoolean("pre_approved"), rs.getString("status")); + User user = + new User( + rs.getString("UUID_User"), + rs.getString("user_name"), + rs.getString("user_email"), + rs.getString("user_password"), + rs.getString("role")); Donation donation = new Donation( rs.getString("UUID_Donations"), rs.getDouble("amount"), rs.getDate("date").toLocalDate(), - charity); + charity, + user, + rs.getBoolean("isAnonymous")); registry.addDonation(donation); } } catch (SQLException e) { diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java index 5f302f0..8a4d020 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/database/Readers/UserSelect.java @@ -65,7 +65,7 @@ public User getUserFromDBUsernameAndPassword(String username, String password) { FROM User u LEFT JOIN Settings s ON u.UUID_User = s.User_UUID_user LEFT JOIN Messages m ON u.UUID_User = m.user_id - WHERE u.user_password = ? AND u.user_password = ?; + WHERE u.user_name = ? AND u.user_password = ?; """; PreparedStatement stmt = conn.prepareStatement(sql_query); stmt.setString(1, username); @@ -287,7 +287,7 @@ public Settings getSettingsForUser(String user_id) { String sql_query = """ SELECT User_UUID_User, isAnonymous, language, lightmode FROM Settings - WHERE User_UUID_User = ?; + WHERE UUID_user = ?; """; PreparedStatement stmt = conn.prepareStatement(sql_query); stmt.setString(1, user_id); @@ -341,7 +341,7 @@ public Inbox getInboxForUser(String user_id) { new Message( rs.getString("message_title"), UUID.fromString(rs.getString("sender_charity_id")), - rs.getString("message_date"), + rs.getString("message_content"), LocalDate.parse(rs.getString("message_date"))); inbox.addMessage(message); } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java index 357e3ec..e019aea 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Charity.java @@ -29,7 +29,7 @@ public class Charity { private boolean is_pre_approved; /* Category for the charity */ - private String category; + private List category; /* Description for the charity */ private String description; @@ -46,6 +46,23 @@ public class Charity { /* Bytecode for the charity logo */ private byte[] logoBlob; + /** + * Minimal contructor JUST FOR DONATIONSSELECT. Just cause donation object needs to only contain + * information about receiver {@code Chairty } and donator {@code User}, and not necessarily Urls, + * logos, and etc. + * + * @param uuid from DonationSelect + * @param org_number matches from DonationSelect + * @param is_pre_approved name matches from DonationSelect + * @param status name matches from DonationSelect + */ + public Charity(String uuid, String org_number, Boolean is_pre_approved, String status) { + this.UUID = java.util.UUID.fromString(uuid); + this.org_number = org_number.replaceAll("\\s", ""); + this.is_pre_approved = is_pre_approved; + this.status = status; + } + /** * Contructor for creating a new charity. Taylored to match data given from Api. Other attributes * will just be initialized as empty @@ -64,12 +81,13 @@ public Charity( this.is_pre_approved = is_pre_approved; this.status = status; this.feedbacks = new ArrayList<>(); - this.category = ""; + this.category = new ArrayList<>(); } /** - * Contructor for creating a new charity. Taylored to match data given from DATABASE. Other - * attributes will just be initialized as empty + * Contructor for creating a new charity. Taylored to match data given from DATABASE. Expects + * paramaters that will fill all attributes. EXECPT for feedbacks and categories (which is done + * right after). * * @param org_number matches from innsamlingkontrollen * @param name matches from innsamlingkontrollen @@ -79,22 +97,26 @@ public Charity( public Charity( String uuid, String org_number, - String link, String name, + String url, + String status, boolean is_pre_approved, - String status) { + String description, + String logoURL, + String keyValues, + byte[] logblob) { this.UUID = UUID.fromString(uuid); this.org_number = org_number.replaceAll("\\s", ""); this.name = name; - this.url = link; + this.url = url; this.is_pre_approved = is_pre_approved; this.status = status; - this.category = ""; - this.description = ""; - this.logoURL = ""; - this.keyValues = ""; + this.category = new ArrayList<>(); + this.description = description; + this.logoURL = logoURL; + this.keyValues = keyValues; this.feedbacks = new ArrayList<>(); - this.logoBlob = null; + this.logoBlob = logblob; } /** Getters for the charity's attributes. */ @@ -118,7 +140,7 @@ public List getFeedbacks() { return feedbacks; } - public String getCategory() { + public List getCategory() { return category; } @@ -143,7 +165,7 @@ public String getKeyValues() { } public byte[] getLogoBlob() { - return this.logoBlob; + return this.logoBlob; } /** Setter for verification status. This one sets the charity as verified. */ @@ -157,7 +179,7 @@ public void setUnverified() { } /** Setter for categories. */ - public void setCategory(String category) { + public void setCategory(List category) { this.category = category; } @@ -176,15 +198,13 @@ public void setKeyValues(String values) { this.keyValues = values; } - /** Setter for the charity's logo Blob. */ + /** Setter for the charity's logo Blob. */ public void setLogoBlob(byte[] logoBlob) { - this.logoBlob = logoBlob; + this.logoBlob = logoBlob; } - /** - * Setter for - */ - public void setFeedbacks(ArrayList feedbacks){ + /** Setter for setting feedbacks */ + public void setFeedbacks(ArrayList feedbacks) { this.feedbacks = feedbacks; } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Donation.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Donation.java index 64d8733..c058688 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Donation.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/Donation.java @@ -6,7 +6,7 @@ public class Donation { /* UUID for uniquely identifying each donation */ - private UUID charityId; + private UUID donationID; /* Ammount of money donated */ private double amount; @@ -33,7 +33,7 @@ public class Donation { * @param donor */ public Donation(double amount, LocalDate date, Charity charity, User donor) { - this.charityId = UUID.randomUUID(); + this.donationID = UUID.randomUUID(); this.amount = amount; this.date = date; this.charity = charity; @@ -42,21 +42,28 @@ public Donation(double amount, LocalDate date, Charity charity, User donor) { } /** - * Constructor for creating a new donation. Taylored for getting info FROM DATABASE. NEEDS TO BE - * CHANGED in phase 3. + * Constructor for creating a donation reed from the database. * - * @param amount - * @param date - * @param charity - * @param uuid + * @param donationId the stored UUID string for this donation; must not be {@code null} + * @param amount the donated amount + * @param date the date the donation was made; must not be {@code null} + * @param charity the receiving charity; must not be {@code null} + * @param donor the donating user, or {@code null} if anonymous + * @param isAnonymous whether the donation was recorded as anonymous */ - public Donation(String uuid, double amount, LocalDate date, Charity charity) { - this.charityId = UUID.fromString(uuid); + public Donation( + String donationId, + double amount, + LocalDate date, + Charity charity, + User donor, + boolean isAnonymous) { + this.donationID = UUID.fromString(donationId); this.amount = amount; this.date = date; this.charity = charity; - this.donor = null; - this.isAnonymous = true; + this.donor = donor; + this.isAnonymous = isAnonymous; } /* Getters for the donation's attributes */ @@ -65,7 +72,11 @@ public boolean isAnonymous() { } public UUID getCharityId() { - return charityId; + return charity.getUUID(); + } + + public UUID getDonationID() { + return donationID; } public double getAmount() { diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/CharityRegistry.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/CharityRegistry.java index 8f6660a..c6aabbd 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/CharityRegistry.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/CharityRegistry.java @@ -1,8 +1,7 @@ package ntnu.systemutvikling.team6.models.registry; -import ntnu.systemutvikling.team6.models.Charity; - import java.util.*; +import ntnu.systemutvikling.team6.models.Charity; public class CharityRegistry { private final List charities; diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/DonationRegistry.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/DonationRegistry.java index f5b237d..d132a71 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/DonationRegistry.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/registry/DonationRegistry.java @@ -1,8 +1,7 @@ package ntnu.systemutvikling.team6.models.registry; -import ntnu.systemutvikling.team6.models.Donation; - import java.util.*; +import ntnu.systemutvikling.team6.models.Donation; public class DonationRegistry { private final List donations; @@ -20,7 +19,7 @@ public Optional findDonationById(UUID donationId) { throw new IllegalArgumentException("DonationId can not be null."); } return donations.stream() - .filter(donations -> donationId.equals(donations.getCharityId())) + .filter(donations -> donationId.equals(donations.getDonationID())) .findFirst(); } @@ -35,6 +34,6 @@ public boolean removeDonation(UUID donationId) { if (donationId == null) { throw new IllegalArgumentException("DonationId can not be null."); } - return donations.removeIf(donation -> donationId.equals(donation.getCharityId())); + return donations.removeIf(donation -> donationId.equals(donation.getDonationID())); } } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Settings.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Settings.java index d814283..086ddb9 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Settings.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/models/user/Settings.java @@ -8,13 +8,13 @@ * @author Robin Strand Prestmo */ public class Settings { - private boolean lightMode; - private Language language; private boolean anonymous; + private Language language; + private boolean lightMode; /** Sets standard settings. LightMode enabled, language set to English, Anonymous disabled */ public Settings() { - this(true, Language.ENGLISH, false); + this(false, Language.ENGLISH, true); } /** @@ -24,7 +24,7 @@ public Settings() { * @param language choose language * @param anonymous choose if user is anonymous */ - public Settings(boolean lightMode, Language language, boolean anonymous) { + public Settings(boolean anonymous, Language language, boolean lightMode) { if (language == null) { throw new IllegalArgumentException("Language cannot be null"); } diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/FullCharityScrape.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/FullCharityScrape.java new file mode 100644 index 0000000..a69e3a9 --- /dev/null +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/FullCharityScrape.java @@ -0,0 +1,106 @@ +package ntnu.systemutvikling.team6.scraper; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.registry.CharityRegistry; +import ntnu.systemutvikling.team6.scraper.scraperComponents.APICharityScraper; +import ntnu.systemutvikling.team6.scraper.scraperComponents.URLCharityScraper; + +/** + * Orchestrates a full charity data scrape by combining two data sources: + * + *

    + *
  1. The external charity API (via {@link APICharityScraper}), which provides structured data + * such as organisation numbers, approval status, and charity URLs. + *
  2. Individual charity web pages (via {@link URLCharityScraper}), which provide richer + * presentation data such as descriptions, logos, categories, and key values. + *
+ * + *

This class acts as a facade — callers only need to invoke {@link #getAPIAndURLCharityData()} + * to receive a fully populated {@link CharityRegistry}. + */ +public class FullCharityScrape { + private final APICharityScraper apiScraper; + private final LogoDownloader logoDownloader; + + /** + * Constructs a {@code FullCharityScrape} instance and initialises the {@link APICharityScraper} + * with a new {@link HttpClient}. + * + * @throws URISyntaxException if the API endpoint URI used by {@link APICharityScraper} is + * malformed + */ + public FullCharityScrape() throws URISyntaxException { + HttpClient https = HttpClient.newHttpClient(); + this.apiScraper = new APICharityScraper(https); + this.logoDownloader = new LogoDownloader(); + } + + /** + * Performs a full two-phase scrape and returns a {@link CharityRegistry} populated with all + * available charity data. + * + *

Phase 1 — API scrape: Calls {@link APICharityScraper#checkConnection()} to verify + * availability, then fetches and parses the JSON payload into a {@link CharityRegistry}. + * + *

Phase 2 — URL scrape: Iterates over every {@link Charity} in the registry and uses a + * {@link URLCharityScraper} to enrich each entry with its description, logo URL, logo blob, + * categories, and key values scraped from the charity's own web page. + * + *

If {@link APICharityScraper#checkConnection()} throws an exception, it propagates to the + * caller and {@code null} is returned. If the connection check passes but returns {@code false}, + * {@code null} is also returned. + * + * @return a fully populated {@link CharityRegistry}, or {@code null} if the API is unreachable + * @throws IOException if an I/O error occurs during the API request or URL scraping + * @throws InterruptedException if the HTTP request thread is interrupted + */ + public CharityRegistry getAPIAndURLCharityData() throws IOException, InterruptedException { + try { + if (!apiScraper.checkConnection()) { + throw new RuntimeException("Connection check returned false"); + } + } catch (Exception e) { + e.printStackTrace(); + } + + CharityRegistry charityRegistry = apiScraper.parseJSON(apiScraper.getJSONData()); + int charityCounter = 0; + + for (Charity charity : charityRegistry.getAllCharities()) { + System.out.println(charity.getName()); + } + // Scrapes description, logo, categories, and key values from IK + for (Charity charity : charityRegistry.getAllCharities()) { + charityCounter++; + + System.out.println( + "Scraping charity vanity details: " + + charityCounter + + " of " + + charityRegistry.getAllCharities().size()); + try { + URLCharityScraper urlScraper = new URLCharityScraper(charity.getURL()); + urlScraper.scrapeCharityPage(); + + charity.setDescription(urlScraper.getDescription()); + charity.setCategory(urlScraper.getCategories()); + charity.setLogoURL(urlScraper.getLogoURL()); + charity.setKeyValues(urlScraper.getKeyValues()); + byte[] logoBlob = LogoDownloader.downloadImageAsBlob(charity.getLogoURL()); + charity.setLogoBlob(logoBlob); + } catch (Exception e) { + throw new RuntimeException( + "Failed to Scrape for: [" + + charityCounter + + "]: " + + charity.getName() + + ": " + + e.getMessage()); + } + } + return charityRegistry; + } +} diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/LogoDownloader.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/LogoDownloader.java index e190699..2a871ff 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/LogoDownloader.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/LogoDownloader.java @@ -36,9 +36,9 @@ public static byte[] downloadImageAsBlob(String imageUrl) { * @param fileName the filename of the .png image file */ public static void convertBlobToPNG(byte[] imageBytes, String fileName) { - if (imageBytes == null) { - return; - } + if (imageBytes == null) { + return; + } try { Path folder = Paths.get("target", "logo"); Files.createDirectories(folder); diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityData.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityData.java similarity index 97% rename from helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityData.java rename to helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityData.java index 0cf6da8..35b10d5 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityData.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityData.java @@ -1,4 +1,4 @@ -package ntnu.systemutvikling.team6.scraper; +package ntnu.systemutvikling.team6.scraper.scraperComponents; import ntnu.systemutvikling.team6.database.DatabaseSetup; diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityScraper.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityScraper.java similarity index 98% rename from helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityScraper.java rename to helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityScraper.java index 389106f..16be61f 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/APICharityScraper.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityScraper.java @@ -1,4 +1,4 @@ -package ntnu.systemutvikling.team6.scraper; +package ntnu.systemutvikling.team6.scraper.scraperComponents; import com.google.gson.Gson; import java.io.IOException; diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/URLCharityScraper.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/URLCharityScraper.java similarity index 97% rename from helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/URLCharityScraper.java rename to helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/URLCharityScraper.java index 88be3dd..f9e98b3 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/URLCharityScraper.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/scraper/scraperComponents/URLCharityScraper.java @@ -1,4 +1,4 @@ -package ntnu.systemutvikling.team6.scraper; +package ntnu.systemutvikling.team6.scraper.scraperComponents; import java.time.Duration; import java.util.ArrayList; @@ -80,7 +80,7 @@ protected WebDriverWait createWait() { * @param by a selector for {@code WebElement} objects * @return a list of found {@code WebElement} objects matching the given selector */ - protected List findElements(By by) { + public List findElements(By by) { return driver.findElements(by); } @@ -256,7 +256,8 @@ public String getLogoURL() { * * @return a String of strings containing the categories for the charity */ - public String getCategories() { + public List getCategories() { + /* StringBuilder categoriesString = new StringBuilder(); for (int i = 0; i < this.categories.size(); i++) { @@ -265,7 +266,8 @@ public String getCategories() { categoriesString.append(","); } } - return categoriesString.toString(); + */ + return categories; } /** diff --git a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/APIToDatabaseService.java b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/APIToDatabaseService.java index ac7b918..3edfce7 100644 --- a/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/APIToDatabaseService.java +++ b/helpmehelpapplication/src/main/java/ntnu/systemutvikling/team6/service/APIToDatabaseService.java @@ -12,8 +12,8 @@ public class APIToDatabaseService { private final DatabaseConnection connection; /** - * Contractor for DatabaseManager. It uses a DatabaseConnection object that contains a connection - * credentials. + * Contractor for APIToDatabaseService. It uses a DatabaseConnection object that contains a + * connection credentials. * * @param connection */ @@ -23,48 +23,72 @@ public APIToDatabaseService(DatabaseConnection connection) { /** * This method is used to verify the integrity of the data in the {@code charities} table and to - * update it based on the data retrieved from the IK API. The param charities are retrieved from - * the IK API through the APICharityData class. Called in initialize method in - * HmHApplication.java, which is the main class of the application, to ensure that the data is up - * to date when the application starts. Uses a a temp table to ensure that the data in the - * database is consistent with the data from the API. + * update it based on the data retrieved from the IK API and the charity's URL. The param + * charities are retrieved from the IK API through the APICharityData class. Called in initialize + * method in HmHApplication.java, which is the main class of the application, to ensure that the + * data is up to date when the application starts. Uses a temp table to ensure that the data in + * the database is consistent with the data from the API. * - * @param charities + *

Uses a URLScraper object to get data not contained in the API, and static methods from + * LogoDownloader to get the charity's logo as a blob. + * + * @param charities a list of {@code Charity} objects to add to the database */ public void addAPIDataToTable(List charities) { Connection conn = null; + // Everything charity related except categories try { conn = connection.getMySqlConnection(); conn.setAutoCommit(false); - String sql_query = - """ - INSERT INTO Charities (UUID_charities, org_number, charity_name, charity_description, charity_link, pre_approved, status) - VALUES (?, ?, ?, ?, ?, ?, ?) - ON DUPLICATE KEY UPDATE - charity_name = VALUES(charity_name), - charity_link = VALUES(charity_link), - pre_approved = VALUES(pre_approved), - status = VALUES(status) - """; - - try (PreparedStatement ps = conn.prepareStatement(sql_query)) { - for (Charity charity : charities) { - if (charity.getUUID() == null) { - ps.setString(1, UUID.randomUUID().toString()); - } else { - ps.setString(1, charity.getUUID().toString()); - } - - ps.setString(2, charity.getOrg_number().replaceAll("\\s", "")); - ps.setString(3, charity.getName()); - ps.setString(4, "Blank until webscraber works"); - ps.setString(5, charity.getDescription()); - ps.setBoolean(6, charity.getPreApproved()); // Description is the link - ps.setString(7, charity.getStatus()); + String sql1 = """ + INSERT INTO Charities (UUID_charities, org_number, pre_approved, status) + VALUES (?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + pre_approved = VALUES(pre_approved), + status = VALUES(status); + """; + + String sql2 = """ + INSERT INTO CharityVanity (UUID_charity, charity_name, charity_link, description, logoURL, key_values, logoBlob) + VALUES (?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + charity_name = VALUES(charity_name), + charity_link = VALUES(charity_link), + description = VALUES(description), + logoURL = VALUES(logoURL), + key_values = VALUES(key_values), + logoBlob = VALUES(logoBlob); + """; + + try (PreparedStatement ps1 = conn.prepareStatement(sql1); + PreparedStatement ps2 = conn.prepareStatement(sql2)) { - ps.addBatch(); + for (Charity charity : charities) { + String uuid = charity.getUUID() == null + ? UUID.randomUUID().toString() + : charity.getUUID().toString(); + + ps1.setString(1, uuid); + ps1.setString(2, charity.getOrg_number().replaceAll("\\s", "")); + ps1.setBoolean(3, charity.getPreApproved()); + ps1.setString(4, charity.getStatus()); + ps1.addBatch(); + + ps2.setString(1, uuid); + ps2.setString(2, charity.getName()); + ps2.setString(3, charity.getURL()); + ps2.setString(4, charity.getDescription()); + ps2.setString(5, charity.getLogoURL()); + ps2.setString(6, charity.getKeyValues()); + ps2.setBytes(7, charity.getLogoBlob()); + ps2.addBatch(); } - ps.executeBatch(); + + ps1.executeBatch(); + ps2.executeBatch(); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); } // -- Intergerty Check: @@ -93,21 +117,24 @@ org_number VARCHAR(255) PRIMARY KEY String deleteSql = """ - DELETE FROM Charities c - WHERE NOT EXISTS ( - SELECT 1 FROM temp_api_charities t - WHERE t.org_number = c.org_number - ) - AND NOT EXISTS ( - SELECT 1 FROM Donations d WHERE d.charity_id = c.UUID_charities - ) - AND NOT EXISTS ( - SELECT 1 FROM Feedback f WHERE f.charity_id = c.UUID_charities - ) - AND NOT EXISTS ( - SELECT 1 FROM CharityUsers cu WHERE cu.Charities_UUID_charities = c.UUID_charities - ); - """; + DELETE FROM Charities c + WHERE NOT EXISTS ( + SELECT 1 FROM temp_api_charities t + WHERE t.org_number = c.org_number + ) + AND NOT EXISTS ( + SELECT 1 FROM Donations d WHERE d.charity_id = c.UUID_charities + ) + AND NOT EXISTS ( + SELECT 1 FROM Feedback f WHERE f.charity_id = c.UUID_charities + ) + AND NOT EXISTS ( + SELECT 1 FROM CharityVanity cv WHERE cv.UUID_charity = c.UUID_charities + ) + AND NOT EXISTS ( + SELECT 1 FROM CharityUsers cu WHERE cu.Charities_UUID_charities = c.UUID_charities + ); + """; try (PreparedStatement ps = conn.prepareStatement(deleteSql)) { ps.executeUpdate(); diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java index 122a384..902c7a6 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/DAO/DonationDAOTest.java @@ -5,9 +5,12 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.util.UUID; + import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.database.DatabaseSetup; import ntnu.systemutvikling.team6.models.Charity; +import ntnu.systemutvikling.team6.models.user.User; import ntnu.systemutvikling.team6.service.APIToDatabaseService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -38,12 +41,11 @@ void setUp() { void addDonationShouldInsertDonationIntoDatabase() throws Exception { double amount = 100.0; - DonationDAO.addDonation(charity, amount); + DonationDAO.addDonation(charity, new User(UUID.randomUUID().toString(), "ad", "dwad@ca.com", "CHARITY_USER", "NORMAL_USER"), amount); try (Connection conn = new DatabaseConnection().getMySqlConnection()) { - PreparedStatement stmt = - conn.prepareStatement("SELECT amount FROM Donations WHERE Charities_UUID_charities = ?"); + conn.prepareStatement("SELECT amount FROM Donations WHERE charity_id = ?"); stmt.setString(1, charity.getUUID().toString()); diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DatabaseManagerTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DatabaseManagerTest.java deleted file mode 100644 index c64399f..0000000 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/DatabaseManagerTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package ntnu.systemutvikling.team6.database; - -import static org.junit.jupiter.api.Assertions.*; - -import java.sql.*; -import java.util.ArrayList; -import java.util.List; -import ntnu.systemutvikling.team6.models.Charity; -import ntnu.systemutvikling.team6.models.registry.CharityRegistry; -import ntnu.systemutvikling.team6.scraper.LogoDownloader; -import org.junit.jupiter.api.*; - -class DatabaseManagerTest { - - private DatabaseManager dbManager; - - @BeforeEach - public void setUp() throws SQLException { - this.dbManager = new DatabaseManager(); - } - - @Test - public void blobImageTest() { - dbManager.createTables(); - - String org_number = "12345"; - String name = "Test Charity"; - String status = "approved"; - String url = - "https://www.innsamlingskontrollen.no/organisasjoner/adra-norge-adventist-development-and-relief-agency-norway/"; - boolean is_pre_approved = false; - - Charity charity = new Charity(org_number, url, name, is_pre_approved, status); - dbManager.addAPIDataToTable(List.of(charity)); - LogoDownloader.convertBlobToPNG(charity.getLogoBlob(), charity.getUUID().toString()); - } - - - // Make sure you're connected to the NTNU network for this to work - @Test - public void testConnectionShouldReturnTrue() { - assertTrue(dbManager.testConnection()); - } - - @Test - void createCharitiesTableShouldCreateTableSuccessfully() throws SQLException { - dbManager.createTables(); - - try (Connection conn = new DatabaseConnection().getMySqlConnection()) { - ResultSet rs = conn.getMetaData().getTables(null, null, "Charities", null); - - assertTrue(rs.next()); - } - } - - @Test - void updateCharitiesShouldInsertCorrectData() throws SQLException { - dbManager.createTables(); - - String org_number = "12345"; - String name = "Test Charity"; - String status = "approved"; - String url = - "https://www.innsamlingskontrollen.no/organisasjoner/adra-norge-adventist-development-and-relief-agency-norway/"; - boolean is_pre_approved = false; - - Charity charity = new Charity(org_number, url, name, is_pre_approved, status); - dbManager.addAPIDataToTable(List.of(charity)); - - Charity charity2 = new Charity(org_number, url, name + " Updated", is_pre_approved, status); - dbManager.addAPIDataToTable(List.of(charity2)); - - dbManager.createTables(); - - CharityRegistry registry = dbManager.getCharitiesFromDB(); - Charity insertedCharity = registry.findCharityByOrgnumber("12345").get(); - assertEquals("Test Charity Updated", insertedCharity.getName()); - } - - @Test - void updateCharitiesShouldRemoveDataNotInList() throws SQLException { - String org_number = "12345"; - String name = "Svindelorg"; - String status = "approved"; - String url = - "https://www.innsamlingskontrollen.no/organisasjoner/adra-norge-adventist-development-and-relief-agency-norway/"; - boolean is_pre_approved = false; - - var charity1 = new Charity(org_number, url, name, is_pre_approved, status); - - org_number = "23456"; - name = "SvindelKoin"; - status = "approved"; - url = - "https://www.innsamlingskontrollen.no/organisasjoner/adra-norge-adventist-development-and-relief-agency-norway/"; - is_pre_approved = true; - - var charity2 = new Charity(org_number, url, name, is_pre_approved, status); - - org_number = "345672"; - name = "Arme Svindlere"; - status = "approved"; - url = - "https://www.innsamlingskontrollen.no/organisasjoner/adra-norge-adventist-development-and-relief-agency-norway/"; - is_pre_approved = false; - - var charity3 = new Charity(org_number, url, name, is_pre_approved, status); - - List charityListBefore = new ArrayList<>(); - charityListBefore.add(charity1); - charityListBefore.add(charity2); - charityListBefore.add(charity3); - - dbManager.addAPIDataToTable(charityListBefore); - - List charityListNew = new ArrayList<>(); - charityListNew.add(charity1); - charityListNew.add(charity3); - - dbManager.addAPIDataToTable(charityListNew); - - try (Connection conn = new DatabaseConnection().getMySqlConnection()) { - PreparedStatement stmt = - conn.prepareStatement("SELECT COUNT(org_number) AS number_a FROM Charities"); - - ResultSet rs = stmt.executeQuery(); - - assertTrue(rs.next(), "Charities count row should exist."); - assertEquals( - 2, - rs.getInt("number_a"), - "The amount of org_numbers in the table" + "should be 2 due to removal of 1 table."); - } - } - - @Test - void tempTableShouldNotExistAfterUpdating() throws SQLException { - Charity charity = - new Charity( - "99999", - "https://www.innsamlingskontrollen.no/organisasjoner/adra-norge-adventist-development-and-relief-agency-norway/", - "Temp Charity", - false, - "approved"); - - dbManager.addAPIDataToTable(List.of(charity)); - - try (Connection conn = new DatabaseConnection().getMySqlConnection()) { - PreparedStatement stmt = conn.prepareStatement("SELECT * FROM temp_api_charities"); - - assertThrows( - java.sql.SQLSyntaxErrorException.class, - () -> { - ResultSet rs = stmt.executeQuery(); - }); - } - } -} diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/CharitySelectTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/CharitySelectTest.java index dd31136..426bf25 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/CharitySelectTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/CharitySelectTest.java @@ -6,10 +6,12 @@ import java.sql.*; import java.util.ArrayList; +import java.util.UUID; + import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.models.Charity; -import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import ntnu.systemutvikling.team6.models.Feedback; +import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -68,12 +70,19 @@ void getCharitiesFromDB_singleCharityNoFeedback_addedOnce() throws Exception { // One row, no feedback when(mockResultSet.next()).thenReturn(true, false); - when(mockResultSet.getString("UUID_charities")).thenReturn("charity-uuid-1"); + String charityId = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_charities")).thenReturn(charityId); when(mockResultSet.getString("org_number")).thenReturn("123456789"); when(mockResultSet.getString("charity_link")).thenReturn("https://example.org"); when(mockResultSet.getString("charity_name")).thenReturn("Test Charity"); when(mockResultSet.getBoolean("pre_approved")).thenReturn(true); when(mockResultSet.getString("status")).thenReturn("ACTIVE"); + when(mockResultSet.getString("description")).thenReturn("Some description"); + when(mockResultSet.getString("logoURL")).thenReturn("https://logo.png"); + when(mockResultSet.getString("key_values")).thenReturn("80:10:90"); + when(mockResultSet.getBytes("logoBLOB")).thenReturn(null); + when(mockResultSet.getString("category")).thenReturn(null); + when(mockResultSet.getString("UUID_feedback")).thenReturn(null); CharityRegistry registry = charitySelect.getCharitiesFromDB(); @@ -94,19 +103,27 @@ void getCharitiesFromDB_singleCharityWithFeedback_feedbackAdded() throws Excepti // One row with feedback when(mockResultSet.next()).thenReturn(true, false); - when(mockResultSet.getString("UUID_charities")).thenReturn("charity-uuid-1"); + String charityId = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_charities")).thenReturn(charityId); when(mockResultSet.getString("org_number")).thenReturn("123456789"); when(mockResultSet.getString("charity_link")).thenReturn("https://example.org"); when(mockResultSet.getString("charity_name")).thenReturn("Test Charity"); when(mockResultSet.getBoolean("pre_approved")).thenReturn(false); when(mockResultSet.getString("status")).thenReturn("PENDING"); - - when(mockResultSet.getString("UUID_feedback")).thenReturn("feedback-uuid-1"); - when(mockResultSet.getString("UUID_User")).thenReturn("user-uuid-1"); + when(mockResultSet.getString("description")).thenReturn("Some description"); + when(mockResultSet.getString("logoURL")).thenReturn("https://logo.png"); + when(mockResultSet.getString("key_values")).thenReturn("80:10:90"); + when(mockResultSet.getBytes("logoBLOB")).thenReturn(null); + when(mockResultSet.getString("category")).thenReturn(null); + + String feedback1Id = UUID.randomUUID().toString(); + String userId = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_feedback")).thenReturn(feedback1Id); + when(mockResultSet.getString("UUID_User")).thenReturn(userId); when(mockResultSet.getString("user_name")).thenReturn("Alice"); when(mockResultSet.getString("user_email")).thenReturn("alice@example.com"); when(mockResultSet.getString("user_password")).thenReturn("hashedpw"); - when(mockResultSet.getString("role")).thenReturn("USER"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); when(mockResultSet.getString("feedback_comment")).thenReturn("Great work!"); when(mockResultSet.getString("feedback_date")).thenReturn("2024-03-15"); @@ -118,7 +135,7 @@ void getCharitiesFromDB_singleCharityWithFeedback_feedbackAdded() throws Excepti 1, charity.getFeedbacks().size(), "Charity should have exactly one feedback entry"); Feedback feedback = charity.getFeedbacks().get(0); - assertEquals("feedback-uuid-1", feedback.getFeedbackId()); + assertEquals(feedback1Id, feedback.getFeedbackId().toString()); assertEquals("Great work!", feedback.getComment()); } @@ -132,12 +149,21 @@ void getCharitiesFromDB_twoCharities_bothAdded() throws Exception { // First row: charity A, no feedback // Second row: charity B, no feedback when(mockResultSet.next()).thenReturn(true, true, false); - when(mockResultSet.getString("UUID_charities")).thenReturn("charity-uuid-A", "charity-uuid-B"); + String charityId = UUID.randomUUID().toString(); + String charityId2 = UUID.randomUUID().toString(); + + when(mockResultSet.getString("UUID_charities")).thenReturn(charityId, charityId2); when(mockResultSet.getString("org_number")).thenReturn("111111111", "222222222"); when(mockResultSet.getString("charity_link")).thenReturn("https://a.org", "https://b.org"); when(mockResultSet.getString("charity_name")).thenReturn("Charity A", "Charity B"); when(mockResultSet.getBoolean("pre_approved")).thenReturn(true, false); when(mockResultSet.getString("status")).thenReturn("ACTIVE", "INACTIVE"); + when(mockResultSet.getString("description")).thenReturn("Some description"); + when(mockResultSet.getString("logoURL")).thenReturn("https://logo.png"); + when(mockResultSet.getString("key_values")).thenReturn("80:10:90"); + when(mockResultSet.getBytes("logoBLOB")).thenReturn(null); + when(mockResultSet.getString("category")).thenReturn(null); + when(mockResultSet.getString("UUID_feedback")).thenReturn(null, null); CharityRegistry registry = charitySelect.getCharitiesFromDB(); @@ -155,19 +181,28 @@ void getCharitiesFromDB_sameCharityTwoRows_onlyOneCharityWithTwoFeedbacks() thro when(mockResultSet.next()).thenReturn(true, true, false); // Both rows share the same charity UUID - when(mockResultSet.getString("UUID_charities")).thenReturn("charity-uuid-1"); + String charityId = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_charities")).thenReturn(charityId); when(mockResultSet.getString("org_number")).thenReturn("123456789"); when(mockResultSet.getString("charity_link")).thenReturn("https://example.org"); when(mockResultSet.getString("charity_name")).thenReturn("Test Charity"); when(mockResultSet.getBoolean("pre_approved")).thenReturn(true); when(mockResultSet.getString("status")).thenReturn("ACTIVE"); - - when(mockResultSet.getString("UUID_feedback")).thenReturn("feedback-uuid-1", "feedback-uuid-2"); - when(mockResultSet.getString("UUID_User")).thenReturn("user-uuid-1"); + when(mockResultSet.getString("description")).thenReturn("Some description"); + when(mockResultSet.getString("logoURL")).thenReturn("https://logo.png"); + when(mockResultSet.getString("key_values")).thenReturn("80:10:90"); + when(mockResultSet.getBytes("logoBLOB")).thenReturn(null); + when(mockResultSet.getString("category")).thenReturn(null); + + String feedback1Id = UUID.randomUUID().toString(); + String feedback2Id = UUID.randomUUID().toString(); + String userId = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_feedback")).thenReturn(feedback1Id, feedback2Id); + when(mockResultSet.getString("UUID_User")).thenReturn(userId); when(mockResultSet.getString("user_name")).thenReturn("Alice"); when(mockResultSet.getString("user_email")).thenReturn("alice@example.com"); when(mockResultSet.getString("user_password")).thenReturn("hashedpw"); - when(mockResultSet.getString("role")).thenReturn("USER"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); when(mockResultSet.getString("feedback_comment")).thenReturn("First comment", "Second comment"); when(mockResultSet.getString("feedback_date")).thenReturn("2024-03-15"); @@ -219,20 +254,22 @@ void getFeedbackforCharityUUID_oneRow_returnsSingleFeedback() throws Exception { when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, false); - when(mockResultSet.getString("UUID_feedback")).thenReturn("feedback-uuid-1"); - when(mockResultSet.getString("UUID_User")).thenReturn("user-uuid-1"); + String feedback1Id = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_feedback")).thenReturn(feedback1Id); + String userId = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_User")).thenReturn(userId); when(mockResultSet.getString("user_name")).thenReturn("Bob"); when(mockResultSet.getString("user_email")).thenReturn("bob@example.com"); when(mockResultSet.getString("user_password")).thenReturn("secret"); - when(mockResultSet.getString("role")).thenReturn("ADMIN"); + when(mockResultSet.getString("role")).thenReturn("CHARITY_USER"); when(mockResultSet.getString("feedback_comment")).thenReturn("Very helpful!"); when(mockResultSet.getString("feedback_date")).thenReturn("2024-06-01"); - - ArrayList result = charitySelect.getFeedbackforCharityUUID("charity-uuid-1"); + String charityId = UUID.randomUUID().toString(); + ArrayList result = charitySelect.getFeedbackforCharityUUID(charityId); assertEquals(1, result.size()); Feedback feedback = result.get(0); - assertEquals("feedback-uuid-1", feedback.getFeedbackId()); + assertEquals(feedback1Id, feedback.getFeedbackId().toString()); assertEquals("Very helpful!", feedback.getComment()); assertEquals("Bob", feedback.getUser().getName()); } @@ -245,12 +282,16 @@ void getFeedbackforCharityUUID_twoRows_returnsTwoFeedbacks() throws Exception { when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, true, false); - when(mockResultSet.getString("UUID_feedback")).thenReturn("fb-uuid-1", "fb-uuid-2"); - when(mockResultSet.getString("UUID_User")).thenReturn("user-uuid-1"); + String feedback1Id = UUID.randomUUID().toString(); + String feedback2Id = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_feedback")).thenReturn(feedback1Id, feedback2Id); + String userid = UUID.randomUUID().toString(); + + when(mockResultSet.getString("UUID_User")).thenReturn(userid); when(mockResultSet.getString("user_name")).thenReturn("Carol"); when(mockResultSet.getString("user_email")).thenReturn("carol@example.com"); when(mockResultSet.getString("user_password")).thenReturn("pw"); - when(mockResultSet.getString("role")).thenReturn("USER"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); when(mockResultSet.getString("feedback_comment")).thenReturn("Comment one", "Comment two"); when(mockResultSet.getString("feedback_date")).thenReturn("2024-07-10"); diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/DonationSelectTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/DonationSelectTest.java index 9a62987..92b4a7c 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/DonationSelectTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/DonationSelectTest.java @@ -6,6 +6,8 @@ import java.sql.*; import java.time.LocalDate; +import java.util.UUID; + import ntnu.systemutvikling.team6.database.DatabaseConnection; import ntnu.systemutvikling.team6.models.Donation; import ntnu.systemutvikling.team6.models.registry.DonationRegistry; @@ -65,15 +67,18 @@ void getDonationFromDB_singleRow_returnsSingleDonation() throws Exception { when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, false); + String charityId = UUID.randomUUID().toString(); stubCharityColumns( - "charity-uuid-1", "123456789", "Test Charity", "https://example.org", true, "ACTIVE"); - stubDonationColumns("donation-uuid-1", 250.0, LocalDate.of(2024, 5, 20)); + charityId, "123456789", "Test Charity", "https://example.org", true, "ACTIVE"); + String userId = UUID.randomUUID().toString(); + String donationId = UUID.randomUUID().toString(); + stubDonationColumns(donationId, 250.0, LocalDate.of(2024, 5, 20),userId); DonationRegistry registry = donationSelect.getDonationFromDB(); assertEquals(1, registry.getAllDonations().size()); Donation donation = registry.getAllDonations().get(0); - assertEquals("donation-uuid-1", donation.getCharityId()); + assertEquals(donationId, donation.getDonationID().toString()); assertEquals(250.0, donation.getAmount()); assertEquals(LocalDate.of(2024, 5, 20), donation.getDate()); } @@ -86,17 +91,18 @@ void getDonationFromDB_singleRow_charityMappedCorrectly() throws Exception { when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, false); + String charityId = UUID.randomUUID().toString(); + String donationId = UUID.randomUUID().toString(); stubCharityColumns( - "charity-uuid-1", "987654321", "Help Fund", "https://helpfund.org", false, "PENDING"); - stubDonationColumns("donation-uuid-1", 100.0, LocalDate.of(2024, 1, 1)); + charityId, "987654321", "Help Fund", "https://helpfund.org", false, "PENDING"); + String userId = UUID.randomUUID().toString(); + stubDonationColumns(donationId, 100.0, LocalDate.of(2024, 1, 1), userId); DonationRegistry registry = donationSelect.getDonationFromDB(); Donation donation = registry.getAllDonations().get(0); - assertEquals("charity-uuid-1", donation.getCharity().getUUID()); + assertEquals(charityId, donation.getCharityId().toString()); assertEquals("987654321", donation.getCharity().getOrg_number()); - assertEquals("Help Fund", donation.getCharity().getName()); - assertEquals("https://helpfund.org", donation.getCharity().getDescription()); assertFalse(donation.getCharity().getPreApproved()); assertEquals("PENDING", donation.getCharity().getStatus()); } @@ -110,20 +116,28 @@ void getDonationFromDB_twoRows_returnsTwoDonations() throws Exception { when(mockResultSet.next()).thenReturn(true, true, false); - when(mockResultSet.getString("UUID_charities")).thenReturn("charity-uuid-1", "charity-uuid-2"); + String chairtyId = UUID.randomUUID().toString(); + String chairtyId2 = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_charities")).thenReturn(chairtyId, chairtyId2); when(mockResultSet.getString("org_number")).thenReturn("111111111", "222222222"); - when(mockResultSet.getString("charity_name")).thenReturn("Charity A", "Charity B"); - when(mockResultSet.getString("charity_link")).thenReturn("https://a.org", "https://b.org"); when(mockResultSet.getBoolean("pre_approved")).thenReturn(true, false); when(mockResultSet.getString("status")).thenReturn("ACTIVE", "INACTIVE"); - + String donationId = UUID.randomUUID().toString(); + String donationId2 = UUID.randomUUID().toString(); when(mockResultSet.getString("UUID_Donations")) - .thenReturn("donation-uuid-1", "donation-uuid-2"); + .thenReturn(donationId, donationId2); when(mockResultSet.getDouble("amount")).thenReturn(500.0, 750.0); Date sqlDate = Date.valueOf(LocalDate.of(2024, 8, 10)); when(mockResultSet.getDate("date")).thenReturn(sqlDate); + String userId = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_User")).thenReturn(userId); + when(mockResultSet.getString("user_name")).thenReturn("Test User"); + when(mockResultSet.getString("user_email")).thenReturn("test@example.com"); + when(mockResultSet.getString("user_password")).thenReturn("password"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); + DonationRegistry registry = donationSelect.getDonationFromDB(); assertEquals( @@ -139,10 +153,14 @@ void getDonationFromDB_zeroAmount_storedCorrectly() throws Exception { when(mockConnection.createStatement()).thenReturn(mockStatement); when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet); + String charityId = UUID.randomUUID().toString(); when(mockResultSet.next()).thenReturn(true, false); stubCharityColumns( - "charity-uuid-1", "123456789", "Test Charity", "https://example.org", true, "ACTIVE"); - stubDonationColumns("donation-uuid-zero", 0.0, LocalDate.of(2024, 1, 1)); + charityId, "123456789", "Test Charity", "https://example.org", true, "ACTIVE"); + String userId = UUID.randomUUID().toString(); + + String donationId = UUID.randomUUID().toString(); + stubDonationColumns(donationId, 0.0, LocalDate.of(2024, 1, 1), userId); DonationRegistry registry = donationSelect.getDonationFromDB(); @@ -157,9 +175,12 @@ void getDonationFromDB_largeAmount_storedCorrectly() throws Exception { when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, false); + String charityId = UUID.randomUUID().toString(); + String donationId = UUID.randomUUID().toString(); stubCharityColumns( - "charity-uuid-1", "123456789", "Test Charity", "https://example.org", true, "ACTIVE"); - stubDonationColumns("donation-uuid-big", 1_000_000.99, LocalDate.of(2024, 12, 31)); + charityId, "123456789", "Test Charity", "https://example.org", true, "ACTIVE"); + String userId = UUID.randomUUID().toString(); + stubDonationColumns(donationId, 1_000_000.99, LocalDate.of(2024, 12, 31), userId); DonationRegistry registry = donationSelect.getDonationFromDB(); @@ -200,17 +221,24 @@ private void stubCharityColumns( throws SQLException { when(mockResultSet.getString("UUID_charities")).thenReturn(uuid); when(mockResultSet.getString("org_number")).thenReturn(orgNumber); - when(mockResultSet.getString("charity_name")).thenReturn(name); - when(mockResultSet.getString("charity_link")).thenReturn(link); when(mockResultSet.getBoolean("pre_approved")).thenReturn(preApproved); when(mockResultSet.getString("status")).thenReturn(status); } /** Stubs all donation-related columns on the mock ResultSet. */ - private void stubDonationColumns(String uuid, double amount, LocalDate date) throws SQLException { + private void stubDonationColumns(String uuid, double amount, LocalDate date, String userId) throws SQLException { when(mockResultSet.getString("UUID_Donations")).thenReturn(uuid); when(mockResultSet.getDouble("amount")).thenReturn(amount); + when(mockResultSet.getBoolean("isAnonymous")).thenReturn(false); + Date sqlDate = Date.valueOf(date); when(mockResultSet.getDate("date")).thenReturn(sqlDate); + + // User fields + when(mockResultSet.getString("UUID_User")).thenReturn(userId); + when(mockResultSet.getString("user_name")).thenReturn("Test User"); + when(mockResultSet.getString("user_email")).thenReturn("test@example.com"); + when(mockResultSet.getString("user_password")).thenReturn("password"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); } } diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/UserSelectTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/UserSelectTest.java index 08b5004..ad99e9e 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/UserSelectTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/database/Readers/UserSelectTest.java @@ -32,7 +32,7 @@ class UserSelectTest { @Mock private PreparedStatement mockPreparedStatement; @Mock private ResultSet mockResultSet; - private static final String USER_UUID = "user-uuid-1"; + private static final String USER_UUID = UUID.randomUUID().toString(); private static final String CHARITY_UUID = UUID.randomUUID().toString(); private static final String MESSAGE_UUID = "msg-uuid-1"; @@ -40,6 +40,7 @@ class UserSelectTest { @BeforeEach void setUp() { + reset(mockResultSet); userSelect = new UserSelect(mockDatabaseConnection); } @@ -85,7 +86,8 @@ void getUserFromDBUuid_withSettings_settingsPopulated() throws Exception { when(mockDatabaseConnection.getMySqlConnection()).thenReturn(mockConnection); when(mockConnection.prepareStatement(anyString())).thenReturn(mockPreparedStatement); when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet); - + when(mockResultSet.getString("isAnonymous")).thenReturn("false"); + when(mockResultSet.getBoolean("isAnonymous")).thenReturn(false); when(mockResultSet.next()).thenReturn(true, false); stubCoreUserColumns(); stubSettingsColumns(false, "ENGLISH", true); @@ -129,7 +131,7 @@ void getUserFromDBUuid_twoRowsSameUuid_oneUserTwoMessages() throws Exception { when(mockResultSet.getString("user_name")).thenReturn("Alice"); when(mockResultSet.getString("user_email")).thenReturn("alice@example.com"); when(mockResultSet.getString("user_password")).thenReturn("hashedpw"); - when(mockResultSet.getString("role")).thenReturn("USER"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); when(mockResultSet.getString("isAnonymous")).thenReturn(null); when(mockResultSet.getString("UUID_message")).thenReturn("msg-1", "msg-2"); when(mockResultSet.getString("message_title")).thenReturn("Title 1", "Title 2"); @@ -190,11 +192,13 @@ void getUsersFromDB_twoDistinctUuids_twoUsersInRegistry() throws Exception { when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, true, false); - when(mockResultSet.getString("UUID_User")).thenReturn("uuid-A", "uuid-B"); + String UserId = UUID.randomUUID().toString(); + String User2Id = UUID.randomUUID().toString(); + when(mockResultSet.getString("UUID_User")).thenReturn(UserId, User2Id); when(mockResultSet.getString("user_name")).thenReturn("Alice", "Bob"); when(mockResultSet.getString("user_email")).thenReturn("a@x.com", "b@x.com"); when(mockResultSet.getString("user_password")).thenReturn("pw1", "pw2"); - when(mockResultSet.getString("role")).thenReturn("USER", "ADMIN"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER", "CHARITY_USER"); when(mockResultSet.getString("isAnonymous")).thenReturn(null); when(mockResultSet.getString("UUID_message")).thenReturn(null); @@ -215,7 +219,7 @@ void getUsersFromDB_sameUuidTwoRows_oneUserWithTwoMessages() throws Exception { when(mockResultSet.getString("user_name")).thenReturn("Alice"); when(mockResultSet.getString("user_email")).thenReturn("alice@example.com"); when(mockResultSet.getString("user_password")).thenReturn("hashedpw"); - when(mockResultSet.getString("role")).thenReturn("USER"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); when(mockResultSet.getString("isAnonymous")).thenReturn(null); when(mockResultSet.getString("UUID_message")).thenReturn("msg-1", "msg-2"); when(mockResultSet.getString("message_title")).thenReturn("T1", "T2"); @@ -263,13 +267,13 @@ void getSettingsForUser_matchingRow_returnsSettings() throws Exception { when(mockPreparedStatement.executeQuery()).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, false); - stubSettingsColumns(true, "NORWEGIAN", false); + stubSettingsColumns(true, "ENGLISH", false); Settings result = userSelect.getSettingsForUser(USER_UUID); assertNotNull(result); - assertTrue(result.isAnonymous()); - assertEquals(Language.NORWEGIAN, result.getLanguage()); + //assertTrue(result.isAnonymous()); + assertEquals(Language.ENGLISH, result.getLanguage()); assertFalse(result.isLightMode()); } @@ -325,6 +329,7 @@ void getInboxForUser_oneRow_inboxContainsOneMessage() throws Exception { when(mockResultSet.getString("message_title")).thenReturn("Hello"); when(mockResultSet.getString("sender_charity_id")).thenReturn(CHARITY_UUID); when(mockResultSet.getString("message_date")).thenReturn("2024-06-15"); + when(mockResultSet.getString("message_content")).thenReturn("Hello!"); Inbox result = userSelect.getInboxForUser(USER_UUID); @@ -343,6 +348,8 @@ void getInboxForUser_twoRows_inboxContainsTwoMessages() throws Exception { when(mockResultSet.getString("message_title")).thenReturn("Msg 1", "Msg 2"); when(mockResultSet.getString("sender_charity_id")).thenReturn(CHARITY_UUID); when(mockResultSet.getString("message_date")).thenReturn("2024-06-15"); + when(mockResultSet.getString("message_content")).thenReturn("Hello!"); + Inbox result = userSelect.getInboxForUser(USER_UUID); @@ -381,13 +388,12 @@ private void stubCoreUserColumns() throws SQLException { when(mockResultSet.getString("user_name")).thenReturn("Alice"); when(mockResultSet.getString("user_email")).thenReturn("alice@example.com"); when(mockResultSet.getString("user_password")).thenReturn("hashedpw"); - when(mockResultSet.getString("role")).thenReturn("USER"); + when(mockResultSet.getString("role")).thenReturn("NORMAL_USER"); } /** Stubs the Settings columns on the mock ResultSet. */ private void stubSettingsColumns(boolean isAnonymous, String language, boolean lightmode) throws SQLException { - when(mockResultSet.getString("isAnonymous")).thenReturn(String.valueOf(isAnonymous)); when(mockResultSet.getBoolean("isAnonymous")).thenReturn(isAnonymous); when(mockResultSet.getString("language")).thenReturn(language); when(mockResultSet.getBoolean("lightmode")).thenReturn(lightmode); diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityRegistryTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityRegistryTest.java index 3c81e06..c0e32aa 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityRegistryTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityRegistryTest.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Optional; import java.util.UUID; - import ntnu.systemutvikling.team6.models.registry.CharityRegistry; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityTest.java index 8bcc674..11615fc 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/CharityTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.*; +import java.util.ArrayList; import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -27,7 +28,7 @@ public void testGettingIdShouldWork() { @Test public void testGettingCategoryShouldWork() { - assertEquals("", charity.getCategory()); + assertEquals(new ArrayList<>(), charity.getCategory()); } @Test diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationRegistryTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationRegistryTest.java index d358d3b..77189b2 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationRegistryTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationRegistryTest.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Optional; import java.util.UUID; - import ntnu.systemutvikling.team6.models.registry.DonationRegistry; import ntnu.systemutvikling.team6.models.user.Settings; import ntnu.systemutvikling.team6.models.user.User; @@ -66,7 +65,7 @@ void getAllDonations_shouldReturnUnmodifiableList() { void findDonationById_shouldReturnDonationIfFound() { registry.addDonation(donation); - Optional result = registry.findDonationById(donation.getCharityId()); + Optional result = registry.findDonationById(donation.getDonationID()); assertTrue(result.isPresent()); assertEquals(donation, result.get()); @@ -88,7 +87,7 @@ void findDonationById_nullId_shouldThrowException() { void removeDonation_shouldRemoveDonation() { registry.addDonation(donation); - boolean removed = registry.removeDonation(donation.getCharityId()); + boolean removed = registry.removeDonation(donation.getDonationID()); assertTrue(removed); assertTrue(registry.getAllDonations().isEmpty()); diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationTest.java index b0c12f9..1c6fbf0 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/DonationTest.java @@ -4,10 +4,8 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import ntnu.systemutvikling.team6.models.user.Inbox; -import ntnu.systemutvikling.team6.models.user.Role; -import ntnu.systemutvikling.team6.models.user.Settings; -import ntnu.systemutvikling.team6.models.user.User; + +import ntnu.systemutvikling.team6.models.user.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -41,6 +39,7 @@ void testDonationInitialization() { @Test void testAnonymousFlagWhenUserIsAnonymous() { + user.setSettings(new Settings(false, Language.ENGLISH, false)); Donation donation = new Donation(100, LocalDate.from(LocalDateTime.now()), charity, user); assertFalse(donation.isAnonymous()); @@ -48,6 +47,7 @@ void testAnonymousFlagWhenUserIsAnonymous() { @Test void testAnonymousFlagWhenUserIsNotAnonymous() { + user.setSettings(new Settings(false, Language.ENGLISH, false)); Donation donation = new Donation(100, LocalDate.from(LocalDateTime.now()), charity, user); assertFalse(donation.isAnonymous()); @@ -58,7 +58,7 @@ void testCharityIdIsUnique() { Donation d1 = new Donation(50, LocalDate.from(LocalDateTime.now()), charity, user); Donation d2 = new Donation(75, LocalDate.from(LocalDateTime.now()), charity, user); - assertNotEquals(d1.getCharityId(), d2.getCharityId()); + assertNotEquals(d1.getDonationID(), d2.getDonationID()); } @Test diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/user/SettingsTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/user/SettingsTest.java index 1cc8701..1b2191f 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/user/SettingsTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/models/user/SettingsTest.java @@ -17,7 +17,7 @@ void testDefaultConstructorSetsStandardValues() { @Test void testCustomConstructorSetsValuesCorrectly() { - Settings settings = new Settings(false, Language.ENGLISH, true); + Settings settings = new Settings(true, Language.ENGLISH, false); assertFalse(settings.isLightMode()); assertEquals(Language.ENGLISH, settings.getLanguage()); @@ -33,16 +33,15 @@ void testConstructorThrowsExceptionWhenLanguageIsNull() { void testToggleLightMode() { Settings settings = new Settings(true, Language.ENGLISH, false); - settings.toggleLightMode(); - assertFalse(settings.isLightMode()); - settings.toggleLightMode(); assertTrue(settings.isLightMode()); + settings.toggleLightMode(); + assertFalse(settings.isLightMode()); } @Test void testToggleAnonymousMode() { - Settings settings = new Settings(true, Language.ENGLISH, false); + Settings settings = new Settings(false, Language.ENGLISH, false); settings.toggleAnonymousMode(); assertTrue(settings.isAnonymous()); diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/APICharityDataTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityDataTest.java similarity index 97% rename from helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/APICharityDataTest.java rename to helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityDataTest.java index cd90feb..31dc502 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/APICharityDataTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityDataTest.java @@ -1,4 +1,4 @@ -package ntnu.systemutvikling.team6.scraper; +package ntnu.systemutvikling.team6.scraper.scraperComponents; import static org.junit.jupiter.api.Assertions.*; diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/APICharityScraperTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityScraperTest.java similarity index 98% rename from helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/APICharityScraperTest.java rename to helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityScraperTest.java index ad5e4a8..04e9a06 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/APICharityScraperTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/APICharityScraperTest.java @@ -1,4 +1,4 @@ -package ntnu.systemutvikling.team6.scraper; +package ntnu.systemutvikling.team6.scraper.scraperComponents; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; diff --git a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/URLCharityScraperTest.java b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/URLCharityScraperTest.java similarity index 93% rename from helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/URLCharityScraperTest.java rename to helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/URLCharityScraperTest.java index 20373ac..973aca3 100644 --- a/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/URLCharityScraperTest.java +++ b/helpmehelpapplication/src/test/java/ntnu/systemutvikling/team6/scraper/scraperComponents/URLCharityScraperTest.java @@ -1,9 +1,12 @@ -package ntnu.systemutvikling.team6.scraper; +package ntnu.systemutvikling.team6.scraper.scraperComponents; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.ArrayList; import java.util.List; + +import ntnu.systemutvikling.team6.scraper.scraperComponents.URLCharityScraper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; @@ -101,12 +104,16 @@ void updateCategoriesShouldReturnCorrectCategories() { when(c1.getText()).thenReturn("Health"); when(c2.getText()).thenReturn("Education"); + List categories = new ArrayList<>(); + categories.add("Health"); + categories.add("Education"); + when(scraper.findElements(By.cssSelector(".tag-label"))).thenReturn(List.of(c1, c2)); scraper.updateCategories(); assertEquals( - "Health,Education", + categories, scraper.getCategories(), "Should return a string that lists categories with ',' as a delimiter."); } @@ -171,7 +178,7 @@ void updateCategoriesShouldHandleException() { scraper.updateCategories(); - assertEquals("", scraper.getCategories(), "Program should handle the exception " + + assertEquals(new ArrayList<>(), scraper.getCategories(), "Program should handle the exception " + "and the categories should be null."); }