Skip to content

Commit

Permalink
Merge pull request #76 from Group-5/fix/testcoverage
Browse files Browse the repository at this point in the history
Merge Fix/testcoverage into release/v2.0.0
  • Loading branch information
lucych authored Apr 21, 2026
2 parents a6982e8 + b317fbd commit 9f9fb18
Show file tree
Hide file tree
Showing 10 changed files with 285 additions and 55 deletions.
6 changes: 3 additions & 3 deletions src/main/java/edu/group5/app/model/AppState.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class AppState {
private User currentUser;
private BigDecimal currentDonationAmount;
private Organization currentOrganization;
private String currentDonation;
private String currentPaymentMethod;

/**
* Gets the current user of the application.
Expand Down Expand Up @@ -73,14 +73,14 @@ public void setCurrentDonationAmount(BigDecimal amount) {
* @return the current payment method
*/
public String getCurrentPaymentMethod() {
return this.currentDonation;
return this.currentPaymentMethod;
}

/**
* Sets the current payment method.
* @param paymentMethod the payment method to set as the current payment method
*/
public void setCurrentPaymentMethod(String paymentMethod){
this.currentDonation = paymentMethod;
this.currentPaymentMethod = paymentMethod;
}
}
8 changes: 0 additions & 8 deletions src/main/java/edu/group5/app/model/Repository.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,4 @@ protected Repository(Map<K, V> content) {
ParameterValidator.objectChecker(content, "content");
this.content = content;
}

/**
* Gets the content of the repository.
* @return the content of the repository
*/
public Map<K, V> getContent() {
return content;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,38 +40,53 @@ public String fetchDescription(String pageUrl) {
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
.timeout(5000).get();

Element section = doc.selectFirst("section.information");
if (section != null) {
section.select("div.extra-info").remove();
section.select("a.read-more").remove();

// Extract all <p> tags and <div> elements as separate paragraphs
String description = section.select("p, div").stream()
.filter(el -> el.tagName().equals("p") || el.select("p").isEmpty())
.filter(el -> !el.hasClass("extra-info") && !el.hasClass("logo"))
.map(Element::text)
.map(text -> text.replace("Les mer", "").trim())
.filter(text -> !text.isBlank())
.collect(Collectors.joining("\n\n"));

// Fallback: if no paragraphs found, get all text from section
if (description.isBlank()) {
description = section.text().trim();
}
description = description.replace("Les mer", "").trim();

// Only cache and return if we found something meaningful
if (!description.isBlank()) {
descriptionCache.put(pageUrl, description);
return description;
}
String description = parseDescription(doc);
if (!description.isBlank()) {
descriptionCache.put(pageUrl, description);
return description;
}
} catch (Exception e) {
System.out.println("Could not get description for: " + pageUrl);
}
return null;
}

/**
* Parses the description from a Document by extracting text content
* from {@code <section class="information">}.
*
* @param doc the Document to parse
* @return the description text, or empty string if not found
*/
protected String parseDescription(Document doc) {
Element section = doc.selectFirst("section.information");
if (section != null) {
section.select("div.extra-info").remove();
section.select("a.read-more").remove();

// Extract all <p> tags and <div> elements as separate paragraphs
String description = section.select("p, div").stream()
.filter(el -> el.tagName().equals("p") || el.select("p").isEmpty())
.filter(el -> !el.hasClass("extra-info") && !el.hasClass("logo"))
.map(Element::text)
.map(text -> text.replace("Les mer", "").trim())
.filter(text -> !text.isBlank())
.collect(Collectors.joining("\n\n"));

// Fallback: if no paragraphs found, get all text from section
if (description.isBlank()) {
description = section.text().trim();
}
description = description.replace("Les mer", "").trim();

// Only return if we found something meaningful
if (!description.isBlank()) {
return description;
}
}
return "";
}

/**
* Fetches the logo URL for the given page by scraping the {@code div.logo img}
* element. Results are cached so each URL is only fetched once.
Expand All @@ -88,10 +103,9 @@ public String fetchLogoUrl(String pageUrl) {
Document doc = Jsoup.connect(pageUrl)
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
.timeout(5000).get();
Element img = doc.selectFirst("div.logo img");

if (img != null) {
String logoUrl = img.absUrl("src");
String logoUrl = parseLogoUrl(doc);
if (!logoUrl.isBlank()) {
logoCache.put(pageUrl, logoUrl);
return logoUrl;
}
Expand All @@ -100,4 +114,20 @@ public String fetchLogoUrl(String pageUrl) {
}
return null;
}

/**
* Parses the logo URL from a Document by extracting the image src
* from {@code div.logo img}.
*
* @param doc the Document to parse
* @return the absolute logo URL, or empty string if not found
*/
protected String parseLogoUrl(Document doc) {
Element img = doc.selectFirst("div.logo img");
if (img != null) {
String logoUrl = img.absUrl("src");
return logoUrl.isBlank() ? "" : logoUrl;
}
return "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private StackPane createImageContainer() {
// Load image in background thread to avoid blocking UI
new Thread(() -> {
try {
Image image = new Image(org.logoUrl(), 120, 120, true, true);
Image image = new Image(org.logoUrl(), 350, 350, true, true);
Platform.runLater(() -> {
ImageView logo = new ImageView(image);
logo.setId("logo");
Expand Down
69 changes: 69 additions & 0 deletions src/test/java/edu/group5/app/model/AppStateTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package edu.group5.app.model;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.math.BigDecimal;

import org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import edu.group5.app.model.organization.Organization;
import edu.group5.app.model.user.Customer;
import edu.group5.app.model.user.User;

public class AppStateTest {
private User nullUser;
private BigDecimal nullDonationAmount;
private Organization nullOrganization;
private String nullPaymentMethod;

private User currentTestUser;
private BigDecimal currentTestDonationAmount;
private Organization currentTestOrganization;
private String currentTestPaymentMethod;

@BeforeEach
void setUp() {
nullUser = null;
nullDonationAmount = null;
nullOrganization = null;
nullPaymentMethod = null;

currentTestUser = new Customer(1, "Bob",
"Builder", "testuser@example.com",
"password123");

currentTestDonationAmount = BigDecimal.ZERO;

currentTestOrganization = new Organization(1738, "TestOrg",
true, "https://testorg.example.com", true,
"A test organization", "https://testorg.example.com/logo.png");

currentTestPaymentMethod = "Credit Card";
}

@Test
void gettersAndSetters_WorkCorrectly() {
AppState appState = new AppState();

// Test current user
assertEquals(nullUser, appState.getCurrentUser());
appState.setCurrentUser(currentTestUser);
assertEquals(currentTestUser, appState.getCurrentUser());

// Test current donation amount
assertEquals(nullDonationAmount, appState.getCurrentDonationAmount());
appState.setCurrentDonationAmount(currentTestDonationAmount);
assertEquals(currentTestDonationAmount, appState.getCurrentDonationAmount());

// Test current organization
assertEquals(nullOrganization, appState.getCurrentOrganization());
appState.setCurrentOrganization(currentTestOrganization);
assertEquals(currentTestOrganization, appState.getCurrentOrganization());

// Test current payment method
assertEquals(nullPaymentMethod, appState.getCurrentPaymentMethod());
appState.setCurrentPaymentMethod(currentTestPaymentMethod);
assertEquals(currentTestPaymentMethod, appState.getCurrentPaymentMethod());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

Expand Down Expand Up @@ -61,6 +61,33 @@ void testConstructorThrowsIfOrganizationRepositoryIsNull() {
assertEquals("OrganizationRepository can't be null", exception.getMessage());
}

@Test
void getUserDonationsReturnsEmptyMapIfNoDonations() {
assertTrue(donationService.getUserDonations(customer.getUserId()).isEmpty());
}

@Test
void getOrganizationDonationsReturnsMapOfDonations() {
Donation donation1 = new Donation(1, customer.getUserId(),
101, new BigDecimal("20.00"), Timestamp.from(Instant.now()), "Card");
Donation donation2 = new Donation(2, customer.getUserId(),
101, new BigDecimal("30.00"), Timestamp.from(Instant.now()), "PayPal");
donationRepository.addContent(donation1);
donationRepository.addContent(donation2);

Map<Integer, Donation> donations = donationService.getOrganizationDonations(101);
assertEquals(2, donations.size());
assertTrue(donations.containsKey(1));
assertTrue(donations.containsKey(2));
assertEquals(donation1, donations.get(1));
assertEquals(donation2, donations.get(2));
}

@Test
void getOrganizationDonationsReturnsEmptyMapIfNoDonations() {
assertTrue(donationService.getOrganizationDonations(1).isEmpty());
}

@Test
void donateReturnsFalseIfCustomerNull() {
boolean result = donationService.donate(null,
Expand Down
12 changes: 10 additions & 2 deletions src/test/java/edu/group5/app/model/donation/DonationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,19 @@ void testIfThrowsExceptionWhenOrganizationIdIsNotPositive() {
amount1, date1, paymentMethod1);
}
@Test
void testIfThrowsExceptionWhenAmountIsNotPositive() {
void testIfThrowsExceptionWhenAmountIsNegative() {
expectedMessage = "Amount must be positive and not null";
exceptionTest(donationId1, userId1, organizationId1,
new BigDecimal("0.00"), date1, paymentMethod1);
new BigDecimal("-1.00"), date1, paymentMethod1);
}

@Test
void testIfThrowsExceptionWhenAmountIsNull() {
expectedMessage = "Amount must be positive and not null";
exceptionTest(donationId1, userId1, organizationId1,
null, date1, paymentMethod1);
}

@Test
void testIfThrowsExceptionWhenDateIsNull() {
expectedMessage = "Date must not be null";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,30 @@ void constructor_ThrowsWhenContentIsNull() {
constructorTest(null, "Input data can't be null");
}

@Test
void constructor_SkipsOrganizationWithMissingOrgNumber() {
Object[] content = new Object[] {
Map.of(
"name", "Good Org",
"status", "approved",
"url", "org.com",
"is_pre_approved", true
),
Map.of(
"org_number", "999",
"name", "Bad Org",
"status", "approved",
"url", "org.com",
"is_pre_approved", true
)
};

OrganizationRepository repo = new OrganizationRepository(content, scraper);

assertEquals(1, repo.findByOrgNumber(999) != null ? 1 : 0);
assertNull(repo.findByOrgNumber(1));
}

@Test
void constructor_ThrowsWhenScraperIsNull() {
Object[] content = new Object[] {
Expand Down
Loading

0 comments on commit 9f9fb18

Please sign in to comment.