Compare commits

..
Author SHA1 Message Date
Elias Csomor 76197a19df extending tests and adding integration test
and better precision when comparing results
2022-12-10 12:48:06 +01:00
11 changed files with 138 additions and 74 deletions
@@ -22,8 +22,6 @@ public class TutorialController {
public ImageView imgAddNewPlant;
public ImageView imgTaskList;
public ImageView imgSelectDate;
public ImageView imgAddTaskButton;
public ImageView imgDetailDeleteButtons;
private int page = 0;
@@ -32,17 +30,10 @@ public class TutorialController {
switchViews();
setButtonAbilities();
Image addNewPlantImage = new Image(String.valueOf(PlantsController.class.getResource("add-new-plant.png")));
Image selectSowHarvestImage = new Image(String.valueOf(PlantsController.class.getResource("select-sow-harvest.png")));
Image scheduleImage = new Image(String.valueOf(PlantsController.class.getResource("schedule.png")));
Image detailDeleteButtonsImage = new Image(String.valueOf(PlantsController.class.getResource("details-delete.png")));
Image addTaskImage = new Image(String.valueOf(PlantsController.class.getResource("add-task.png")));
imgAddNewPlant.setImage(addNewPlantImage);
imgSelectDate.setImage(selectSowHarvestImage);
imgDetailDeleteButtons.setImage(detailDeleteButtonsImage);
imgAddTaskButton.setImage(addTaskImage);
imgTaskList.setImage(scheduleImage);
Image placeholder = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png")));
imgAddNewPlant.setImage(placeholder);
imgSelectDate.setImage(placeholder);
imgTaskList.setImage(placeholder);
}
public void viewNextPage() {
@@ -89,7 +89,7 @@
<Insets bottom="10.0" />
</VBox.margin>
</ListView>
<Button styleClass="button-class" fx:id="addTask_button" mnemonicParsing="false" onAction="#addTask" prefHeight="25.0" prefWidth="120.0" VBox.vgrow="NEVER" text="Add Task">
<Button styleClass="button-class" fx:id="addTask_button" mnemonicParsing="false" onAction="#addTask" prefHeight="25.0" prefWidth="45.0" VBox.vgrow="NEVER">
<VBox.margin>
<Insets />
</VBox.margin>
@@ -14,7 +14,7 @@
<?import javafx.scene.text.Text?>
<?import javafx.scene.text.TextFlow?>
<BorderPane maxHeight="470.0" maxWidth="724.0" minHeight="470.0" minWidth="724.0" prefHeight="470.0" prefWidth="724.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.TutorialController">
<BorderPane maxHeight="470.0" maxWidth="724.0" minHeight="470.0" minWidth="724.0" prefHeight="470.0" prefWidth="724.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.TutorialController">
<bottom>
<HBox alignment="CENTER" prefHeight="0.0" prefWidth="724.0" BorderPane.alignment="CENTER">
<children>
@@ -22,9 +22,9 @@
<Separator prefWidth="50.0" visible="false" HBox.hgrow="ALWAYS" />
<ButtonBar prefHeight="40.0" prefWidth="200.0">
<buttons>
<Button cancelButton="true" contentDisplay="CENTER" graphicTextGap="5.0" mnemonicParsing="false" onAction="#closeTutorial" styleClass="button-class" text="Close" />
<Button fx:id="previousPageButton" mnemonicParsing="false" onAction="#viewPreviousPage" styleClass="button-class" text="Previous" />
<Button fx:id="nextPageButton" defaultButton="true" mnemonicParsing="false" onAction="#viewNextPage" styleClass="button-class" text="Next" />
<Button styleClass="button-class" cancelButton="true" contentDisplay="CENTER" graphicTextGap="5.0" mnemonicParsing="false" text="Close" onAction="#closeTutorial"/>
<Button styleClass="button-class" fx:id="previousPageButton" mnemonicParsing="false" text="Previous" onAction="#viewPreviousPage"/>
<Button styleClass="button-class" fx:id="nextPageButton" defaultButton="true" mnemonicParsing="false" text="Next" onAction="#viewNextPage" />
</buttons>
</ButtonBar>
</children>
@@ -38,7 +38,7 @@
<children>
<VBox layoutX="30.0" layoutY="26.0" opacity="0.0" prefHeight="200.0" prefWidth="100.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Adding Crops">
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Managing Your Crops">
<font>
<Font size="24.0" />
</font>
@@ -75,7 +75,7 @@
</children>
</TextFlow>
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
<ImageView fx:id="imgSelectDate" fitHeight="150.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
<ImageView fx:id="imgSelectDate" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
</children>
@@ -83,50 +83,7 @@
<Insets />
</opaqueInsets>
</VBox>
<VBox layoutX="30.0" layoutY="30.0" prefHeight="200.0" prefWidth="100.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Managing Your Crops">
<font>
<Font size="24.0" />
</font>
</Text>
<Separator prefWidth="200.0">
<VBox.margin>
<Insets bottom="15.0" top="10.0" />
</VBox.margin>
</Separator>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Once you've added a crop to your garden, it will be displayed in the &quot;My Garden&quot; tab.">
<VBox.margin>
<Insets bottom="20.0" />
</VBox.margin>
</Text>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<TextFlow lineSpacing="4.0" prefHeight="200.0" prefWidth="500.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="On the right hand side of the listing, you'll see two buttons.&#10;&#10;Button with the &quot;trash can&quot; icon lets you remove a crop from your garden plan. This will also delete all associated tasks.&#10;&#10;The button on the left will display the details of the crop in a new window." />
</children>
</TextFlow>
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
<ImageView fitHeight="70.0" fitWidth="100.0" pickOnBounds="true" preserveRatio="true" fx:id="imgDetailDeleteButtons"/>
</children></HBox>
<HBox layoutX="10.0" layoutY="105.0" prefHeight="100.0" prefWidth="200.0">
<children>
<TextFlow lineSpacing="4.0" prefHeight="200.0" prefWidth="500.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Here, you can also add your own custom tasks, by clicking the &quot;Add Task&quot; button.&#10;In the subsequently shown dialog, you can enter the corresponding details.&#10;&#10;Note: If you want to make a task recurring, you need to set both an interval (in days) AND an end date, so the task won't repeat for all eternity." />
</children>
</TextFlow>
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
<ImageView fitHeight="150.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" fx:id="imgAddTaskButton"/>
</children>
</HBox>
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
</VBox>
<VBox opacity="0.0" prefHeight="200.0" prefWidth="100.0">
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Managing Your Tasks">
<font>
@@ -154,9 +111,19 @@
</HBox.margin>
</TextFlow>
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
<ImageView fx:id="imgTaskList" fitHeight="200.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
<ImageView fx:id="imgTaskList" fitHeight="98.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
</children>
</HBox>
<HBox prefHeight="100.0" prefWidth="200.0">
<children>
<TextFlow lineSpacing="4.0" prefHeight="200.0" prefWidth="500.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="You can also add your own custom tasks, by clicking the &quot;Add Task&quot; button.&#10;In the subsequently shown dialog, you can enter the corresponding details.&#10;&#10;Note: If you want to make a task recurring, you need to set both an interval (in days) AND an end date, so the task won't repeat for all eternity." />
</children>
</TextFlow>
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
</children></HBox>
</children>
<opaqueInsets>
<Insets />
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

@@ -1,7 +1,12 @@
package ch.zhaw.gartenverwaltung.io;
import ch.zhaw.gartenverwaltung.models.GardenSchedule;
import ch.zhaw.gartenverwaltung.models.PlantNotFoundException;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Task;
import javafx.application.Platform;
import org.junit.jupiter.api.*;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
@@ -13,6 +18,7 @@ import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -27,6 +33,22 @@ public class JsonTaskListTest {
private final URL dbDataSource = this.getClass().getResource("test-taskdb.json");
private final URL testFile = this.getClass().getResource("template-taskdb.json");
@BeforeAll
static void setUpAll() {
try{
Platform.startup(()->{});
}catch (IllegalStateException ise){
//ignore double launches
}
}
@AfterAll
static void tearDownAll() {
//Dont do: Platform.exit();
}
@BeforeEach
void connectToDb() throws URISyntaxException, IOException {
assertNotNull(testFile);
@@ -35,6 +57,10 @@ public class JsonTaskListTest {
testDatabase = new JsonTaskList(dbDataSource);
}
private void reloadDb() {
testDatabase = new JsonTaskList(dbDataSource);
}
@Test
@DisplayName("Check if results are retrieved completely")
void getTasks() {
@@ -47,7 +73,8 @@ public class JsonTaskListTest {
throw new RuntimeException(e);
}
Assertions.assertEquals(3, taskList.size());
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
Assertions.assertEquals(Arrays.asList(1L, 2L, 5L), ids);
}
@@ -65,7 +92,8 @@ public class JsonTaskListTest {
throw new RuntimeException(e);
}
Assertions.assertEquals(4, taskList.size());
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
Assertions.assertEquals(Arrays.asList(1L, 2L, 5L, 9L), ids);
} catch (IOException e) {
throw new RuntimeException(e);
@@ -83,7 +111,8 @@ public class JsonTaskListTest {
taskList = testDatabase.getTaskList(LocalDate.parse("2022-04-30", formatter),
LocalDate.parse("2022-05-31", formatter));
Assertions.assertEquals(2, taskList.size());
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
Assertions.assertEquals(Arrays.asList(1L, 5L), ids);
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -100,8 +129,8 @@ public class JsonTaskListTest {
throw new RuntimeException(e);
}
Assertions.assertEquals(6, taskList.size());
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
Assertions.assertEquals(Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L), ids);
}
@@ -116,10 +145,20 @@ public class JsonTaskListTest {
}
Assertions.assertEquals(0, taskList.size());
try {
taskList = testDatabase.getTaskForCrop(1);
} catch (IOException e) {
throw new RuntimeException(e);
}
List<Long> ids = (taskList.stream().map( task -> task.getId().orElse(0L)).toList());
Assertions.assertEquals(Arrays.asList(7L, 8L), ids);
}
@Test
void testDefaultConstructor(){
void testDefaultConstructor() {
JsonTaskList db = new JsonTaskList();
try {
assertNotNull(db.getTaskForCrop(0));
@@ -138,6 +177,43 @@ public class JsonTaskListTest {
} catch (IOException e) {
throw new RuntimeException(e);
}
verify(mockObs, times(1)).onChange(ArgumentMatchers.anyList());
ArgumentCaptor<List<Task>> captor = ArgumentCaptor.forClass(List.class);
verify(mockObs, times(1)).onChange(captor.capture());
List<Long> ids = captor.getValue().stream().map(t -> t.getId().orElse(0L)).toList();
Assertions.assertEquals(Arrays.asList(7L, 8L), ids);
}
@Test
@Tag("IntegrationTest")
void testComplete() {
JsonPlantList plantList = new JsonPlantList();
try {
testDatabase.removeTasksForCrop(0);
testDatabase.removeTasksForCrop(1);
} catch (IOException e) {
throw new RuntimeException(e);
}
GardenSchedule gardenSchedule = null;
try {
gardenSchedule = new GardenSchedule(testDatabase, plantList);
} catch (IOException e) {
throw new RuntimeException(e);
}
Crop crop = new Crop(3L, LocalDate.parse("2022-12-01", formatter));
try {
gardenSchedule.planTasksForCrop(crop);
reloadDb();
List<Task> tasks = gardenSchedule.getTaskList();
List<String> tasknames = (tasks.stream().map( task -> task.getName().substring(0,3).toLowerCase()).toList());
Assertions.assertEquals(Arrays.asList("ger","wat","hil","har"), tasknames);
} catch (IOException | PlantNotFoundException | HardinessZoneNotSetException e) {
throw new RuntimeException(e);
}
}
}
@@ -34,12 +34,17 @@ class GardenScheduleTest {
@BeforeAll
static void setUpAll() {
try{
Platform.startup(()->{});
}catch (IllegalStateException ise){
//ignore double launches
}
}
@AfterAll
static void tearDownAll() {
Platform.exit();
//Dont do: Platform.exit();
}
@BeforeEach
@@ -234,5 +239,8 @@ class GardenScheduleTest {
testTaskList.getTaskList(LocalDate.MIN,LocalDate.MAX).get(0);
}
@Test
void testPlantNotFoundException() throws HardinessZoneNotSetException, IOException {
assertThrowsExactly(PlantNotFoundException.class, () -> { model.planTasksForCrop(new Crop(0, exampleStartDate)); });
}
}
@@ -64,5 +64,27 @@
"endDate" : "2022-09-01",
"interval" : 0,
"cropId" : 0
},
{
"id" : 7,
"name" : "sow plant",
"description": "Plant the seeds, crops in de bed.",
"startDate" : "2022-11-01",
"nextExecution": "2022-11-01",
"nextNotification": "2022-11-01",
"endDate" : "2022-11-01",
"interval" : 0,
"cropId" : 1
},
{
"id" : 8,
"name" : "harvest plant",
"description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ",
"startDate" : "2022-12-01",
"nextExecution": "2022-12-01",
"nextNotification": "2022-12-01",
"endDate" : "2022-12-01",
"interval" : 0,
"cropId" : 1
}
]