diff --git a/pom.xml b/pom.xml index 7a55551..f9a8b88 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,12 @@ slf4j-simple 2.0.9 + + com.h2database + h2 + 2.2.224 + runtime + diff --git a/src/main/java/edu/group5/app/App.java b/src/main/java/edu/group5/app/App.java index 0920d27..b02e9bc 100644 --- a/src/main/java/edu/group5/app/App.java +++ b/src/main/java/edu/group5/app/App.java @@ -1,16 +1,11 @@ package edu.group5.app; -import java.util.HashMap; - import edu.group5.app.control.MainController; -import edu.group5.app.control.OrgApiWrapper; import edu.group5.app.view.MainView; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Stage; -import tools.jackson.core.type.TypeReference; -import tools.jackson.databind.ObjectMapper; /** * Hello world! @@ -30,17 +25,4 @@ public void start(Stage stage) { stage.setScene(scene); stage.show(); } - - static void main(String[] args) throws InterruptedException { - OrgApiWrapper orgWrap = new OrgApiWrapper("https://app.innsamlingskontrollen.no/api/public/v1/all"); - System.out.println(); - System.out.println(); - orgWrap.importData(); - Object[] imports = orgWrap.getData(); - ObjectMapper objectMapper = new ObjectMapper(); - HashMap map = objectMapper.convertValue(imports[0], new TypeReference>() { - }); - System.out.println(map.get("org_number")); - launch(args); - } } diff --git a/src/main/java/edu/group5/app/control/wrapper/DbWrapper.java b/src/main/java/edu/group5/app/control/wrapper/DbWrapper.java new file mode 100644 index 0000000..65196dc --- /dev/null +++ b/src/main/java/edu/group5/app/control/wrapper/DbWrapper.java @@ -0,0 +1,232 @@ +package edu.group5.app.control.wrapper; + +import java.math.BigDecimal; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class DbWrapper { + protected Connection connection; + private static final String CONNECTION_TYPE = "jdbc:h2:"; + private static final String DB_SCRIPT = "INIT=RUNSCRIPT FROM 'classpath:"; + private String connectionString; + private List users; + private List donations; + private Logger logger = Logger.getLogger(DbWrapper.class.getName()); + + public DbWrapper(boolean test) { + if (test) { + this.connectionString = CONNECTION_TYPE + "mem:test;" + DB_SCRIPT + "test_init.sql'"; + } else { + this.connectionString = CONNECTION_TYPE + "file:./help-me-help;" + DB_SCRIPT + "init.sql'"; + } + this.logger.info("connectionString constructed"); + } + + public boolean connect() { + try { + this.connection = DriverManager.getConnection(this.connectionString); + if (this.connection.isValid(0)) { + this.logger.info("Database connected"); + return true; + } else { + this.logger.warning("Failed to connect to database"); + return false; + } + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Failed to connect to database due to exception", e); + return false; + } + } + + public boolean disconnect() { + try{ this.connection.close(); } catch (Exception e) {}; + try { + return this.connection.isClosed(); + } catch (Exception e) { + this.logger.log(Level.WARNING, "Failed to check if connection is closed due to exception", e); + return false; + } + } + + private void close(ResultSet results, PreparedStatement ps) { + try { results.close(); } catch (Exception e) {} + try { ps.close(); } catch (Exception e) {} + this.logger.info("results and ps closed"); + } + + public List importUsers() { + PreparedStatement ps = null; + ResultSet results = null; + try{ + ps = this.connection.prepareStatement("SELECT * FROM users"); + results = ps.executeQuery(); + List data = new ArrayList(); + while (results.next()) { + data.add( + new Object[] { + results.getInt("user_id"), + results.getString("role"), + results.getString("first_name"), + results.getString("last_name"), + results.getString("email"), + results.getString("password_hash") + }); + } + this.users = data; + this.logger.info("Users imported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(results, ps); + } + return this.users; + } + + public int exportUsers(List data) { + this.importUsers(); + + if (data == null) { + throw new IllegalArgumentException("data can't be null"); + } + if (data.get(0).length != 6) { + throw new IllegalArgumentException("data's arrays must have a length of 6"); + } + if (data.stream().anyMatch(i -> Arrays.asList(i).contains(null))) { + throw new IllegalArgumentException("One or more rows in data contains null values"); + } + if (this.users.size() > 0) { + if ((int) data.getLast()[0] <= (int) this.users.getLast()[0]) { + throw new IllegalArgumentException("data can't contain existing rows"); + } + } + Set ids = new HashSet<>(); + if (data.stream().anyMatch(i -> !ids.add(i[0]))) { + throw new IllegalArgumentException("data can't contain duplicate rows"); + } + + + PreparedStatement ps = null; + int rowsAffected = 0; + try { + ps = this.connection.prepareStatement( + "INSERT INTO users (user_id, role, first_name, last_name, email, password_hash) VALUES (?, ?, ?, ?, ?, ?)"); + for (Object[] row : data) { + try { + ps.setInt(1, (int) row[0]); + for (int i = 1; i < row.length; i++) { + ps.setString(i + 1, (String) row[i]); + } + } catch (Exception e) { + throw new IllegalArgumentException("One or more rows in data contains a wrong datatype"); + } + rowsAffected += ps.executeUpdate(); + } + this.logger.info("Users exported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(null, ps); + } + return rowsAffected; + } + + private List importDonations() { + return this.importDonations(0, true); + } + + public List importDonations(int user_id) { + return this.importDonations(user_id, false); + } + + private List importDonations(int user_id, boolean all) { + PreparedStatement ps = null; + ResultSet results = null; + try{ + if (all) { + ps = this.connection.prepareStatement("SELECT * FROM donations"); + } else { + ps = this.connection.prepareStatement("SELECT * FROM donations WHERE user_id = ?"); + ps.setInt(1, user_id); + } + results = ps.executeQuery(); + List data = new ArrayList(); + while (results.next()) { + data.add( + new Object[] { + results.getInt(1), + results.getInt(2), + results.getInt(3), + results.getBigDecimal(4), + results.getTimestamp(5), + results.getString(6) + }); + } + this.donations = data; + this.logger.info("Donations imported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(results, ps); + } + return this.donations; + } + + public int exportDonations(List data) { + this.importDonations(); + + if (data == null) { + throw new IllegalArgumentException("data can't be null"); + } + if (data.get(0).length != 6) { + throw new IllegalArgumentException("data's arrays must have a length of 6"); + } + if (data.stream().anyMatch(i -> Arrays.asList(i).contains(null))) { + throw new IllegalArgumentException("One or more rows in data contains null values"); + } + if (this.donations.size() > 0 && (int) data.getLast()[0] <= (int) this.donations.getLast()[0]) { + throw new IllegalArgumentException("data can't contain existing rows"); + } + Set ids = new HashSet<>(); + if (data.stream().anyMatch(i -> !ids.add(i[0]))) { + throw new IllegalArgumentException("data can't contain duplicate rows"); + } + + PreparedStatement ps = null; + int rowsAffected = 0; + try { + ps = this.connection.prepareStatement( + "INSERT INTO donations (donation_id, user_id, organization_id, amount, dating, payment_method) VALUES (?, (SELECT user_id FROM users WHERE user_id = ?), ?, ?, ?, ?)"); + for (Object[] row : data) { + try { + for (int i = 0; i < 3; i++) { + ps.setInt(i + 1, (int) row[i]); + } + ps.setBigDecimal(4, (BigDecimal) row[3]); + ps.setTimestamp(5, (Timestamp) row[4]); + ps.setString(6, (String) row[5]); + } catch (Exception e) { + throw new IllegalArgumentException("One or more rows in data contains a wrong datatype"); + } + rowsAffected += ps.executeUpdate(); + } + this.logger.info("Donations exported"); + } catch (SQLException e) { + this.logger.log(Level.SEVERE, "Unexpected SQL exception", e); + } finally { + this.close(null, ps); + } + return rowsAffected; + } + +} diff --git a/src/main/java/edu/group5/app/control/OrgApiWrapper.java b/src/main/java/edu/group5/app/control/wrapper/OrgApiWrapper.java similarity index 85% rename from src/main/java/edu/group5/app/control/OrgApiWrapper.java rename to src/main/java/edu/group5/app/control/wrapper/OrgApiWrapper.java index 24c82ee..39ac283 100644 --- a/src/main/java/edu/group5/app/control/OrgApiWrapper.java +++ b/src/main/java/edu/group5/app/control/wrapper/OrgApiWrapper.java @@ -1,4 +1,4 @@ -package edu.group5.app.control; +package edu.group5.app.control.wrapper; import java.io.IOException; import java.net.URI; @@ -17,7 +17,8 @@ public class OrgApiWrapper extends Wrapper { private HttpRequest request; /** - * The constructor, which takes a url String and constructs a URI and HttpRequest object from it. + * The constructor, which takes a url String and constructs a URI and + * HttpRequest object from it. * If the url is invalid, it will throw a fitting exception. * * @param urlString A string of the URL that's being connected to. @@ -44,11 +45,13 @@ public OrgApiWrapper(String urlString) { /** * A method for importing data from the wrapped API. * - * @return Returns a boolean, which indicates if the import was successful. Will be False if, for - * example, there is no internet connection. + * @return Returns a boolean, which indicates if the import was successful. Will + * be False if, for + * example, there is no internet connection. * - * @throws InterruptedException This exception is thrown whenever the program is interrupted, like - * by ctrl + c. + * @throws InterruptedException This exception is thrown whenever the program is + * interrupted, like + * by ctrl + c. */ @Override public boolean importData() throws InterruptedException { @@ -67,7 +70,8 @@ public boolean importData() throws InterruptedException { /** * A method for accessing the imported data. * - * @return Returns an array with HashMaps, which is how data is structured in the API. + * @return Returns an array with HashMaps, which is how data is structured in + * the API. */ @Override public Object[] getData() { diff --git a/src/main/java/edu/group5/app/control/Wrapper.java b/src/main/java/edu/group5/app/control/wrapper/Wrapper.java similarity index 66% rename from src/main/java/edu/group5/app/control/Wrapper.java rename to src/main/java/edu/group5/app/control/wrapper/Wrapper.java index ea55179..992b7a9 100644 --- a/src/main/java/edu/group5/app/control/Wrapper.java +++ b/src/main/java/edu/group5/app/control/wrapper/Wrapper.java @@ -1,4 +1,4 @@ -package edu.group5.app.control; +package edu.group5.app.control.wrapper; /** * An abstract class for all Wrappers of datasets. @@ -9,13 +9,16 @@ protected Wrapper() { } /** - * An abstract method for importing data from the dataset that child methods wrap. + * An abstract method for importing data from the dataset that child methods + * wrap. * - * @return Returns a boolean, which indicates if the import was successful. Will be False if, for - * example, there is no internet connection. + * @return Returns a boolean, which indicates if the import was successful. Will + * be False if, for + * example, there is no internet connection. * - * @throws InterruptedException This exception is thrown whenever the program is interrupted, like - * by ctrl + c. + * @throws InterruptedException This exception is thrown whenever the program is + * interrupted, like + * by ctrl + c. */ public abstract boolean importData() throws InterruptedException; diff --git a/src/main/resources/init.sql b/src/main/resources/init.sql new file mode 100644 index 0000000..8b99314 --- /dev/null +++ b/src/main/resources/init.sql @@ -0,0 +1,23 @@ +CREATE TABLE IF NOT EXISTS +users ( + user_id INT PRIMARY KEY, + role VARCHAR(32) NOT NULL, + first_name VARCHAR(32) NOT NULL, + last_name VARCHAR(32) NOT NULL, + email VARCHAR(32) NOT NULL, + password_hash VARCHAR(72) NOT NULL +); + +CREATE TABLE IF NOT EXISTS +donations ( + donation_id INT PRIMARY KEY, + user_id INT NOT NULL, + organization_id INT NOT NULL, + amount DECIMAL(32, 16) NOT NULL, + dating TIMESTAMP NOT NULL, + payment_method VARCHAR(32) NOT NULL, + CONSTRAINT fk_user + FOREIGN KEY (user_id) + REFERENCES users(user_id) +); + diff --git a/src/main/resources/test_init.sql b/src/main/resources/test_init.sql new file mode 100644 index 0000000..00670e8 --- /dev/null +++ b/src/main/resources/test_init.sql @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS users, donations; + +CREATE TABLE IF NOT EXISTS +users ( + user_id INT PRIMARY KEY, + role VARCHAR(32) NOT NULL, + first_name VARCHAR(32) NOT NULL, + last_name VARCHAR(32) NOT NULL, + email VARCHAR(32) NOT NULL, + password_hash VARCHAR(72) NOT NULL +); + +CREATE TABLE IF NOT EXISTS +donations ( + donation_id INT PRIMARY KEY, + user_id INT NOT NULL, + organization_id INT NOT NULL, + amount DECIMAL(32, 16) NOT NULL, + dating TIMESTAMP NOT NULL, + payment_method VARCHAR(32) NOT NULL, + CONSTRAINT fk_user + FOREIGN KEY (user_id) + REFERENCES users(user_id) +); diff --git a/src/test/java/edu/group5/app/control/WrapperTest.java b/src/test/java/edu/group5/app/control/WrapperTest.java deleted file mode 100644 index d626fd7..0000000 --- a/src/test/java/edu/group5/app/control/WrapperTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package edu.group5.app.control; - -public class WrapperTest { - -} diff --git a/src/test/java/edu/group5/app/control/wrapper/DbWrapperDonationsTest.java b/src/test/java/edu/group5/app/control/wrapper/DbWrapperDonationsTest.java new file mode 100644 index 0000000..f31d57c --- /dev/null +++ b/src/test/java/edu/group5/app/control/wrapper/DbWrapperDonationsTest.java @@ -0,0 +1,199 @@ +package edu.group5.app.control.wrapper; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class DbWrapperDonationsTest { + private Object[] johnDonation; + private List users; + private Object[] janeDonation; + private Object[] cutoffDonation; + private Object[] freakyDonation; + private Object[] repeatingDonation; + private List donations; + private List donations2; + private List donations3; + private List repeatedDonations; + private List wrongFormatDonations; + private List wrongDatatypeDonations; + private List nullList; + + private static final int PRECISION = 5; + + private DbWrapper db; + + @BeforeEach + void init() { + this.db = new DbWrapper(true); + String[] firstNames = new String[] { "John", "Jane", "Cutoff", "Freaky", "Repeating" }; + String[] lastNames = new String[] { "Doe", "Doe", "Joh", "Bill", "JoeJoe" }; + this.users = new ArrayList(); + for (int i = 0; i < 5; i++) { + Object[] row = new Object[6]; + row[0] = i + 1; + row[1] = "Customer"; + row[2] = firstNames[i]; + row[3] = lastNames[i]; + row[4] = firstNames[i] + lastNames[i] + "@email.com"; + row[5] = "password"; + users.add(row); + } + + this.johnDonation = new Object[] { 1, 1, 39, new BigDecimal(20.02), new Timestamp(new Date().getTime()), + "Paypal" }; + this.donations = new ArrayList(); + this.donations.add(this.johnDonation); + + this.janeDonation = new Object[] { 2, 2, 39, new BigDecimal(20.00), new Timestamp(new Date().getTime()), + "Visa debit card" }; + this.donations2 = new ArrayList(); + this.donations2.add(this.johnDonation); + this.donations2.add(this.janeDonation); + + this.donations3 = new ArrayList(); + this.donations3.add(this.janeDonation); + + this.repeatingDonation = new Object[] { 3, 3, 333, new BigDecimal(18181818.18), + new Timestamp(new Date().getTime()), "Klarna installations payment" }; + this.repeatedDonations = new ArrayList(); + this.repeatedDonations.add(this.repeatingDonation); + this.repeatedDonations.add(this.repeatingDonation); + + this.cutoffDonation = new Object[] { 4, 4, 21 }; + this.wrongFormatDonations = new ArrayList(); + this.wrongFormatDonations.add(cutoffDonation); + + this.freakyDonation = new Object[] { 5, 5, "Freaks4Education", "lots", false, new String[6] }; + this.wrongDatatypeDonations = new ArrayList(); + this.wrongDatatypeDonations.add(freakyDonation); + + Object[] nullRow = new Object[] {null, null, null, null, null, null}; + this.nullList = new ArrayList(); + this.nullList.add(nullRow); + + this.db.connect(); + this.db.exportUsers(users); + } + + private static boolean donationEquals(Object[] array1, Object[] array2) { + Object[] tempArray1 = array1.clone(); + tempArray1[3] = ((BigDecimal) tempArray1[3]).setScale(2, RoundingMode.HALF_UP); + Object[] tempArray2 = array2.clone(); + tempArray2[3] = ((BigDecimal) tempArray2[3]).setScale(2, RoundingMode.HALF_UP); + return Arrays.equals(tempArray1, tempArray2); + } + + @Test + public void importDonationsIsOnlyExportDonationsTest() { + assertDoesNotThrow(() -> { + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 0); + assertTrue(this.db.exportDonations(this.donations) == 1); + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 1); + assertTrue(donationEquals(this.donations.get(0), this.db.importDonations((int) this.users.get(0)[0]).get(0))); + assertTrue(this.db.disconnect()); + }); + } + + @Test + public void nullDataInExportDonationsThrowsExpectedException() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportDonations(null); + }); + assertTrue(this.db.disconnect()); + assertEquals("data can't be null", exception.getMessage()); + } + + @Test + public void wronglyFormattedDonationsThrowsExpectedException() { + assertTrue(this.db.importDonations((int) this.users.get(2)[0]).size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportDonations(this.wrongFormatDonations); + }); + assertTrue(this.db.importDonations((int) this.users.get(2)[0]).size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("data's arrays must have a length of 6", exception.getMessage()); + } + + @Test + public void wronglyDatatypedDonationsThrowsExpectedException() { + assertTrue(this.db.importDonations((int) this.users.get(3)[0]).size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportDonations(this.wrongDatatypeDonations); + }); + assertTrue(this.db.importDonations((int) this.users.get(3)[0]).size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("One or more rows in data contains a wrong datatype", exception.getMessage()); + } + + @Test + public void addingSameDonationTwiceThrowsExpectedException() { + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 0); + assertEquals(1, this.db.exportDonations(this.donations)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportDonations(this.donations); + }); + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 1); + assertTrue(this.db.disconnect()); + assertEquals("data can't contain existing rows", exception.getMessage()); + } + + @Test + public void addingSameDonationTwiceThrowsExpectedException2() { + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 0); + assertTrue(this.db.importDonations((int) this.users.get(1)[0]).size() == 0); + assertEquals(2, this.db.exportDonations(this.donations2)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportDonations(this.donations); + }); + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 1); + assertTrue(this.db.importDonations((int) this.users.get(1)[0]).size() == 1); + assertTrue(this.db.disconnect()); + assertEquals("data can't contain existing rows", exception.getMessage()); + } + + @Test + public void addingDifferentDonationsThrowsNoException() { + assertDoesNotThrow(() -> { + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 0); + assertTrue(this.db.importDonations((int) this.users.get(1)[0]).size() == 0); + assertEquals(1, this.db.exportDonations(this.donations)); + assertEquals(1, this.db.exportDonations(this.donations3)); + assertTrue(this.db.importDonations((int) this.users.get(0)[0]).size() == 1); + assertTrue(this.db.importDonations((int) this.users.get(1)[0]).size() == 1); + assertTrue(this.db.disconnect()); + }); + } + + @Test + public void addingDonationListWithDuplicateIdsThrowsExpectedException() { + assertTrue(this.db.importDonations((int) this.users.get(4)[0]).size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportDonations(this.repeatedDonations); + }); + assertTrue(this.db.importDonations((int) this.users.get(4)[0]).size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("data can't contain duplicate rows", exception.getMessage()); + } + + @Test + public void addingDonationListWithNullInRowThrowsExpectedException() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportDonations(this.nullList); + }); + assertTrue(this.db.disconnect()); + assertEquals("One or more rows in data contains null values", exception.getMessage()); + } +} diff --git a/src/test/java/edu/group5/app/control/wrapper/DbWrapperUserTest.java b/src/test/java/edu/group5/app/control/wrapper/DbWrapperUserTest.java new file mode 100644 index 0000000..10c514f --- /dev/null +++ b/src/test/java/edu/group5/app/control/wrapper/DbWrapperUserTest.java @@ -0,0 +1,191 @@ +package edu.group5.app.control.wrapper; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigDecimal; +import java.util.Date; +import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import javafx.util.converter.BigDecimalStringConverter; + +public class DbWrapperUserTest { + private Object[] johnDoe; + private Object[] janeDoe; + private Object[] cutoffJoh; + private Object[] freakyBill; + private Object[] repeatingJoeJoe; + private List users; + private List users2; + private List users3; + private List repeatedUsers; + private List wrongFormatUsers; + private List wrongDatatypeUsers; + private List nullList; + + private DbWrapper db; + + @BeforeEach + void init() { + this.db = new DbWrapper(true); + this.johnDoe = new Object[] { 1, "Customer", "John", "Doe", "johndoe@email.com", "password" }; + this.users = new ArrayList(); + this.users.add(this.johnDoe); + + this.janeDoe = new Object[] { 2, "Customer", "Jane", "Doe", "janedoe@email.com", "qwerty" }; + this.users2 = new ArrayList(); + this.users2.add(this.johnDoe); + this.users2.add(this.janeDoe); + + this.users3 = new ArrayList(); + this.users3.add(this.janeDoe); + + this.repeatingJoeJoe = new Object[] { 3, "Customer", "Repeating", "JoeJoe", "repeatingjjoe@email.com", + "passwordpassword" }; + this.repeatedUsers = new ArrayList(); + this.repeatedUsers.add(this.repeatingJoeJoe); + this.repeatedUsers.add(this.repeatingJoeJoe); + + this.cutoffJoh = new Object[] { 4, "Customer", "Cutoff", "Joh" }; + this.wrongFormatUsers = new ArrayList(); + this.wrongFormatUsers.add(cutoffJoh); + + this.freakyBill = new Object[] { 5, "Customer", 6.1805011125, "Bill", true, false }; + this.wrongDatatypeUsers = new ArrayList(); + this.wrongDatatypeUsers.add(freakyBill); + + Object[] nullRow = new Object[] {null, null, null, null, null, null}; + this.nullList = new ArrayList(); + this.nullList.add(nullRow); + } + + @Test + public void nonTestDbWrapperThrowsNoException() { + assertDoesNotThrow(() -> new DbWrapper(false)); + } + + @Test + public void importUsersIsOnlyExportUsersTest() { + assertDoesNotThrow(() -> { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + assertTrue(this.db.exportUsers(this.users) == 1); + assertTrue(this.db.importUsers().size() == 1); + assertTrue(Arrays.equals(this.db.importUsers().get(0), this.johnDoe)); + assertTrue(this.db.disconnect()); + }); + } + + @Test + public void nullDataInExportUsersThrowsExpectedException() { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportUsers(null); + }); + assertTrue(this.db.importUsers().size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("data can't be null", exception.getMessage()); + } + + @Test + public void wronglyFormattedUsersThrowsExpectedException() { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportUsers(this.wrongFormatUsers); + }); + assertTrue(this.db.importUsers().size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("data's arrays must have a length of 6", exception.getMessage()); + } + + @Test + public void wronglyDatatypedUsersThrowsExpectedException() { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportUsers(this.wrongDatatypeUsers); + }); + assertTrue(this.db.importUsers().size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("One or more rows in data contains a wrong datatype", exception.getMessage()); + } + + @Test + public void addingSameUserTwiceThrowsExpectedException() { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + assertEquals(1, this.db.exportUsers(this.users)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportUsers(this.users); + }); + assertTrue(this.db.importUsers().size() == 1); + assertTrue(this.db.disconnect()); + assertEquals("data can't contain existing rows", exception.getMessage()); + } + + @Test + public void addingSameUserTwiceThrowsExpectedException2() { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + assertEquals(2, this.db.exportUsers(this.users2)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportUsers(this.users); + }); + assertTrue(this.db.importUsers().size() == 2); + assertTrue(this.db.disconnect()); + assertEquals("data can't contain existing rows", exception.getMessage()); + } + + @Test + public void addingDifferentUsersThrowsNoException() { + assertDoesNotThrow(() -> { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + assertEquals(1, this.db.exportUsers(this.users)); + assertEquals(1, this.db.exportUsers(this.users3)); + assertTrue(this.db.importUsers().size() == 2); + assertTrue(this.db.disconnect()); + }); + } + + @Test + public void addingUserListWithDuplicateIdsThrowsExpectedException() { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportUsers(this.repeatedUsers); + }); + assertTrue(this.db.importUsers().size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("data can't contain duplicate rows", exception.getMessage()); + } + + @Test + public void addingUserListWithNullInRowThrowsExpectedException() { + assertTrue(this.db.connect()); + assertTrue(this.db.importUsers().size() == 0); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + this.db.exportUsers(this.nullList); + }); + assertTrue(this.db.importUsers().size() == 0); + assertTrue(this.db.disconnect()); + assertEquals("One or more rows in data contains null values", exception.getMessage()); + } + + +} diff --git a/src/test/java/edu/group5/app/control/OrgApiWrapperTest.java b/src/test/java/edu/group5/app/control/wrapper/OrgApiWrapperTest.java similarity index 92% rename from src/test/java/edu/group5/app/control/OrgApiWrapperTest.java rename to src/test/java/edu/group5/app/control/wrapper/OrgApiWrapperTest.java index 53f08d7..23b30ec 100644 --- a/src/test/java/edu/group5/app/control/OrgApiWrapperTest.java +++ b/src/test/java/edu/group5/app/control/wrapper/OrgApiWrapperTest.java @@ -1,4 +1,4 @@ -package edu.group5.app.control; +package edu.group5.app.control.wrapper; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -30,7 +30,8 @@ void init() { } /** - * Checks if inputting null as the urlString throws the expected exception during construction. + * Checks if inputting null as the urlString throws the expected exception + * during construction. */ @Test public void nullUrlThrowsException() { @@ -40,7 +41,8 @@ public void nullUrlThrowsException() { } /** - * Checks if inputting an empty urlString throws the expected exception during construction. + * Checks if inputting an empty urlString throws the expected exception during + * construction. */ @Test public void emptyUrlThrowsException() { @@ -50,7 +52,8 @@ public void emptyUrlThrowsException() { } /** - * Checks if an invalid urlString throws the expected exception during construction. + * Checks if an invalid urlString throws the expected exception during + * construction. */ @Test public void faultyUrlThrowsException() { @@ -60,8 +63,8 @@ public void faultyUrlThrowsException() { } // /** - // * Checks if import returns False when there's no internet connection. - // */ + // * Checks if import returns False when there's no internet connection. + // */ // @Test // public void noConnectionReturnsFalseImport() { // assertDoesNotThrow(() -> {