Skip to content

Commit

Permalink
Merge pull request AY2324S2-CS2103T-T16-2#127 from NewtonKoh/UI-test
Browse files Browse the repository at this point in the history
Add comprehensive UI tests
  • Loading branch information
NewtonKoh authored Apr 14, 2024
2 parents 67b7567 + 4281192 commit 89fa469
Show file tree
Hide file tree
Showing 7 changed files with 472 additions and 10 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ jobs:
working-directory: ${{ github.workspace }}/.github
run: ./run-checks.sh

- name: Set up Xvfb
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y xvfb
Xvfb :99 -screen 0 1280x1024x24 &
echo "DISPLAY=:99" >> $GITHUB_ENV
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1

Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ dependencies {
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: jUnitVersion

testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: jUnitVersion
testImplementation 'org.testfx:testfx-core:4.0.16-alpha'
testImplementation 'org.testfx:testfx-junit5:4.0.16-alpha'
}

shadowJar {
Expand Down
10 changes: 0 additions & 10 deletions src/main/java/seedu/address/ui/MiniPersonCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import seedu.address.model.person.Person;

Expand All @@ -25,14 +24,9 @@ public class MiniPersonCard extends UiPart<Region> {
*/

public final Person person;

@FXML
private HBox cardPane;
@FXML
private Label name;
@FXML
private Label id;
@FXML
private FlowPane tags;

/**
Expand All @@ -46,8 +40,4 @@ public MiniPersonCard(Person person) {
.sorted(Comparator.comparing(tag -> tag.tagName))
.forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
}

public HBox getCardPane() {
return cardPane;
}
}
168 changes: 168 additions & 0 deletions src/test/java/seedu/address/ui/DisplayCardTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package seedu.address.ui;

import static org.testfx.api.FxAssert.verifyThat;
import static seedu.address.logic.commands.CommandTestUtil.REMARK_STUB;
import static seedu.address.logic.commands.CommandTestUtil.VALID_DAY_AVAILABLE_MONDAY;
import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_ADDRESS_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_ADDRESS_ICON_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_BIRTHDAY_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_BIRTHDAY_ICON_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_DAY_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_DAY_ICON_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_EMAIL_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_EMAIL_ICON_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_MONEY_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_MONEY_ICON_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_NAME_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_PHONE_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_PHONE_ICON_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_REMARK_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_TAG_FX_CODE;
import static seedu.address.ui.UiTestUtil.DISPLAY_CARD_TAG_ICON_FX_CODE;

import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
import org.testfx.matcher.base.NodeMatchers;

import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
import seedu.address.model.person.Day;
import seedu.address.model.person.Person;
import seedu.address.model.tag.Tag;
import seedu.address.testutil.PersonBuilder;

public class DisplayCardTest extends ApplicationTest {

private DisplayCard displayCard;
private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
private Person testPerson;

@Override
public void start(Stage stage) {
// Setup a person with comprehensive details for testing
Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased());
testPerson = new PersonBuilder(firstPerson)
.withRemark(REMARK_STUB)
.withDaysAvailable(VALID_DAY_AVAILABLE_MONDAY)
.build();

displayCard = new DisplayCard(testPerson);

UiTestUtil.setUpSystem();

// Set up the scene
Scene scene = new Scene(displayCard.getRoot());
stage.setScene(scene);
stage.show();
}

@Test
public void execute_displayAttributesCorrectText_success() {
verifyThat(DISPLAY_CARD_NAME_FX_CODE, (Label label) -> {
return label.getText().equals(testPerson.getName().toString());
});
verifyThat(DISPLAY_CARD_PHONE_FX_CODE, (Label label) -> {
return label.getText().equals(testPerson.getPhone().toString());
});
verifyThat(DISPLAY_CARD_ADDRESS_FX_CODE, (Label label) -> {
return label.getText().equals(testPerson.getAddress().toString());
});
verifyThat(DISPLAY_CARD_EMAIL_FX_CODE, (Label label) -> {
return label.getText().equals(testPerson.getEmail().toString());
});
verifyThat(DISPLAY_CARD_REMARK_FX_CODE, (Label label) -> {
return label.getText().equals(testPerson.getRemark().toString());
});
verifyThat(DISPLAY_CARD_BIRTHDAY_FX_CODE, (Label label) -> {
return label.getText().equals(testPerson.getBirthday().toString());
});
}

@Test
public void execute_tagCountMatchesPersonTags_success() {

verifyThat(DISPLAY_CARD_TAG_FX_CODE, (FlowPane flowPane) -> {
return flowPane.getChildren().size() == testPerson.getTags().size();
});
}

@Test
public void execute_tagNamesDisplayCorrectly_success() {

verifyThat(DISPLAY_CARD_TAG_FX_CODE, (FlowPane flowPane) -> {
if (testPerson.getTags().size() == 0) {
return true;
}
for (int i = 0; i < testPerson.getTags().size(); ++i) {
if (!((Label) flowPane.getChildren().get(i)).getText()
.equals(((Tag) testPerson.getTags().toArray()[i]).tagName)) {
return false;
}
}
return true;
});
}

@Test
public void execute_daysAvailableCountMatchesPersonDays_success() {

verifyThat(DISPLAY_CARD_DAY_FX_CODE, (FlowPane flowPane) -> {
return flowPane.getChildren().size() == testPerson.getDaysAvailable().size();
});
}

@Test
public void execute_daysAvailableDisplayCorrectly_success() {

verifyThat(DISPLAY_CARD_DAY_FX_CODE, (FlowPane flowPane) -> {
if (testPerson.getDaysAvailable().size() == 0) {
return true;
}
for (int i = 0; i < testPerson.getDaysAvailable().size(); ++i) {
if (!((Label) flowPane.getChildren().get(i)).getText()
.equals(((Day) testPerson.getDaysAvailable().toArray()[i]).getShortForm())) {
return false;
}
}
return true;
});
}

@Test
public void execute_moneyOwedMessageDisplayCorrectly_success() {
verifyThat(DISPLAY_CARD_MONEY_FX_CODE, (Label label) -> {
return label.getText().equals(testPerson.getMoneyOwed().getMessage());
});
}

@Test
public void execute_iconsVisibilityCorrect_success() {
verifyThat(DISPLAY_CARD_TAG_ICON_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_DAY_ICON_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_PHONE_ICON_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_ADDRESS_ICON_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_EMAIL_ICON_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_BIRTHDAY_ICON_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_MONEY_ICON_FX_CODE, NodeMatchers.isVisible());
}

@Test
public void execute_visibilityOfElementsCorrectVisibility_success() {
verifyThat(DISPLAY_CARD_NAME_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_PHONE_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_ADDRESS_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_EMAIL_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_REMARK_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_BIRTHDAY_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_MONEY_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_TAG_FX_CODE, NodeMatchers.isVisible());
verifyThat(DISPLAY_CARD_DAY_FX_CODE, NodeMatchers.isVisible());
}
}
149 changes: 149 additions & 0 deletions src/test/java/seedu/address/ui/HomeCardTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package seedu.address.ui;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.testfx.api.FxAssert.verifyThat;
import static org.testfx.matcher.control.LabeledMatchers.hasText;
import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
import static seedu.address.ui.UiTestUtil.CHART_BAR_GAP;
import static seedu.address.ui.UiTestUtil.CHART_CATEGORY_GAP;
import static seedu.address.ui.UiTestUtil.CHART_CREDIT_BAR_INDEX;
import static seedu.address.ui.UiTestUtil.CHART_DEBT_BAR_INDEX;
import static seedu.address.ui.UiTestUtil.CHART_LEGEND_VISIBLE;
import static seedu.address.ui.UiTestUtil.DATE_PATTERN;
import static seedu.address.ui.UiTestUtil.HOME_CARD_AVAILABLE_LIST_FX_CODE;
import static seedu.address.ui.UiTestUtil.HOME_CARD_CHART_FX_CODE;
import static seedu.address.ui.UiTestUtil.HOME_CARD_CONTACT_FX_CODE;
import static seedu.address.ui.UiTestUtil.HOME_CARD_DATE_FX_CODE;
import static seedu.address.ui.UiTestUtil.HOME_CARD_SECOND_FX_CODE;
import static seedu.address.ui.UiTestUtil.HOME_CARD_TIME_FX_CODE;
import static seedu.address.ui.UiTestUtil.SECOND_PATTERN;
import static seedu.address.ui.UiTestUtil.SERIES_SIZE;
import static seedu.address.ui.UiTestUtil.TIME_PATTERN;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;

import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
import seedu.address.model.person.Day;
import seedu.address.model.person.Person;

public class HomeCardTest extends ApplicationTest {

private HomeCard homeCard;
private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());

@Override
public void start(Stage stage) {
homeCard = new HomeCard(model.getFilteredPersonList());
StackPane root = new StackPane(homeCard.getRoot());

UiTestUtil.setUpSystem();

stage.setScene(new Scene(root));
stage.show();
}

@Test
public void execute_timeUpdates_success() {
// This test assumes the setUpTimeline updates a label to the current time
String expectedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(TIME_PATTERN));
String alternateTime = LocalDateTime.now().minusSeconds(1).format(DateTimeFormatter.ofPattern(TIME_PATTERN));
verifyThat(HOME_CARD_TIME_FX_CODE, (Label label) -> {
return label.getText().equals(expectedTime) || label.getText().equals(alternateTime);
});
}

@Test
public void execute_dateUpdates_success() {
// This test assumes the setUpTimeline updates a label to the current time
String expectedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DATE_PATTERN));
String alternateTime = LocalDateTime.now().minusSeconds(1).format(DateTimeFormatter.ofPattern(DATE_PATTERN));
verifyThat(HOME_CARD_DATE_FX_CODE, (Label label) -> {
return label.getText().equals(expectedTime) || label.getText().equals(alternateTime);
});
}

@Test
public void execute_secondsUpdate_success() {
// This test assumes the setUpTimeline updates a label to the current time
String expectedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(SECOND_PATTERN));
String alternateTime = LocalDateTime.now().minusSeconds(1).format(DateTimeFormatter.ofPattern(SECOND_PATTERN));
verifyThat(HOME_CARD_SECOND_FX_CODE, (Label label) -> {
return label.getText().equals(expectedTime) || label.getText().equals(alternateTime);
});
}

@Test
public void execute_moneyChartInitialization_success() {
// This test ensures the chart is populated with correct data values after initialization
verifyThat(HOME_CARD_CHART_FX_CODE, (BarChart<String, Number> chart) -> {
return chart.getData().size() == SERIES_SIZE; // Confirm chart has one data series
});
}

@Test
public void execute_availableTodayListPopulation_success() {
// Assumes you want to check if the list correctly displays only those available today
Day today = Day.valueOf(LocalDate.now().getDayOfWeek().name());
verifyThat(HOME_CARD_AVAILABLE_LIST_FX_CODE, (ListView<Person> listView) -> {
return listView.getItems().stream().allMatch(person -> person.getDaysAvailable().contains(today));
});
}

@Test
public void execute_homeCardInitialization_success() {
// Verify that contact count label is correctly set
verifyThat(HOME_CARD_CONTACT_FX_CODE, hasText(Integer.toString(model.getFilteredPersonList().size())));
}

@Test
public void execute_totalDebtComputation_success() {
double expectedTotalDebt = model.getFilteredPersonList().stream()
.filter(person -> person.getMoneyOwed().userOwesMoney())
.mapToDouble(person -> person.getMoneyOwed().getAbsoluteAmount())
.sum();

assertEquals(expectedTotalDebt, homeCard.getTotalDebt());
}

@Test
public void execute_totalCreditComputation_success() {
double expectedTotalCredit = model.getFilteredPersonList().stream()
.filter(person -> !person.getMoneyOwed().userOwesMoney())
.mapToDouble(person -> person.getMoneyOwed().getAbsoluteAmount())
.sum();

assertEquals(expectedTotalCredit, homeCard.getTotalCredit());
}

@Test
public void execute_chartConfiguration_success() {
verifyThat(HOME_CARD_CHART_FX_CODE, (BarChart<String, Number> chart) -> {
return chart.getCategoryGap() == CHART_CATEGORY_GAP
&& chart.getBarGap() == CHART_BAR_GAP
&& chart.isLegendVisible() == CHART_LEGEND_VISIBLE;
});
}

@Test
public void execute_moneyChartValues_success() {
verifyThat("#chart", (BarChart<String, Number> chart) -> {
XYChart.Series<String, Number> series = chart.getData().get(0);
return series.getData().get(CHART_DEBT_BAR_INDEX).getYValue().equals(homeCard.getTotalDebt())
&& series.getData().get(CHART_CREDIT_BAR_INDEX).getYValue().equals(homeCard.getTotalCredit());
});
}
}
Loading

0 comments on commit 89fa469

Please sign in to comment.