Skip to content
Snippets Groups Projects
Commit 3eb32253 authored by Hallvard Trætteberg's avatar Hallvard Trætteberg
Browse files

Flere UI-tester, samt noen fikser.

parent 70d4c3c0
No related branches found
No related tags found
No related merge requests found
......@@ -26,6 +26,11 @@ public class TodoItem {
this.checked = checked;
}
/**
* Copies all properties of other TodoItem into this TodoItem.
*
* @param other the other TodoItem, from which properties are copied
*/
public void set(TodoItem other) {
this.checked = other.checked;
this.text = other.text;
......@@ -47,4 +52,12 @@ public class TodoItem {
set(other);
return this;
}
public TodoItem withChecked(boolean checked) {
return new TodoItem().as(this).checked(checked);
}
public TodoItem withText(String text) {
return new TodoItem().as(this).text(text);
}
}
......@@ -18,11 +18,9 @@ public class TodoList implements Iterable<TodoItem> {
}
/**
* Adds the provided TodoItem to this TodoList.
* If the TodoItem is not an instance of TodoListItem,
* its contents is copied in to a new TodoListItem and that is added instead.
* Adds the provided TodoItems to this TodoList.
*
* @param item the TodoItem to add
* @param items the TodoItems to add
*/
public void addTodoItems(TodoItem...items) {
for (TodoItem item : items) {
......@@ -90,6 +88,13 @@ public class TodoList implements Iterable<TodoItem> {
return items.indexOf(item);
}
/**
* Moves the provided TodoItem to a new position given by newIndex.
* Items in-betweem the old and new positions are shifted.
*
* @param item the item to move
* @param newIndex the new position
*/
public void moveTodoItem(TodoItem item, int newIndex) {
items.remove(item);
items.add(newIndex, item);
......
......@@ -30,11 +30,13 @@ public class TodoListItem extends TodoItem {
}
}
@Override
public void set(TodoItem other) {
boolean oldChecked = isChecked();
String oldText = getText();
super.set(other);
if (oldChecked != other.isChecked() || oldText != other.getText() || oldText != null && !(oldText.equals(other.getText()))) {
if (oldChecked != other.isChecked() || oldText != other.getText()
|| oldText != null && !(oldText.equals(other.getText()))) {
todoList.fireTodoListChanged(this);
}
}
......
......@@ -66,7 +66,7 @@ public class TodoController {
}
}
if (reader == null && sampleTodoListResource != null) {
// try sample-todolist.json from resources source folder instead
// try sample todo list from resources instead
URL url = getClass().getResource(sampleTodoListResource);
if (url != null) {
try {
......@@ -109,8 +109,16 @@ public class TodoController {
// kobler data til list-controll
updateTodoListView();
updateTodoListButtons();
todoList.addTodoListListener(todoList -> updateTodoListView());
todoListView.setCellFactory(listView -> new TodoItemListCell());
todoList.addTodoListListener(todoList -> {
autoSaveTodoList();
updateTodoListView();
});
TodoItemListCellDragHandler dragHandler = new TodoItemListCellDragHandler(todoList);
todoListView.setCellFactory(listView -> {
TodoItemListCell listCell = new TodoItemListCell();
dragHandler.registerHandlers(listCell);
return listCell;
});
todoListView.getSelectionModel().selectedItemProperty()
.addListener((prop, oldValue, newValue) -> updateTodoListButtons());
todoListView.setEditable(true);
......@@ -135,7 +143,6 @@ public class TodoController {
TodoItem item = todoList.createTodoItem();
item.setText(newTodoItemText.getText());
todoList.addTodoItem(item);
saveTodoList();
}
@FXML
......@@ -143,7 +150,6 @@ public class TodoController {
TodoItem item = todoListView.getSelectionModel().getSelectedItem();
if (item != null) {
todoList.removeTodoItem(item);
saveTodoList();
}
}
......@@ -152,15 +158,13 @@ public class TodoController {
TodoItem item = todoListView.getSelectionModel().getSelectedItem();
if (item != null) {
item.setChecked(true);
saveTodoList();
}
}
void saveTodoList() {
void autoSaveTodoList() {
if (userTodoListPath != null) {
Path path = Paths.get(System.getProperty("user.home"), userTodoListPath);
try (Writer writer =
new FileWriter(path.toFile(), StandardCharsets.UTF_8)) {
try (Writer writer = new FileWriter(path.toFile(), StandardCharsets.UTF_8)) {
mapper.writerWithDefaultPrettyPrinter().writeValue(writer, todoList);
} catch (IOException e) {
System.err.println("Fikk ikke skrevet til todolist.json på hjemmeområdet");
......
......@@ -7,15 +7,8 @@ import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.TextField;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import todolist.core.TodoItem;
import todolist.core.TodoList;
import todolist.core.TodoListItem;
public class TodoItemListCell extends ListCell<TodoItem> {
......@@ -33,9 +26,6 @@ public class TodoItemListCell extends ListCell<TodoItem> {
super.updateItem(item, empty);
setText(null);
if (empty || item == null) {
setOnDragDetected(null);
setOnDragOver(null);
setOnDragDropped(null);
setGraphic(null);
} else {
// ensure we have created controls common for view and editor
......@@ -55,9 +45,6 @@ public class TodoItemListCell extends ListCell<TodoItem> {
if (isEditing()) {
configureEditor();
} else {
setOnDragDetected(this::handleDragStart);
setOnDragOver(this::handleDragOver);
setOnDragDropped(this::handleDragEnd);
configureViewer();
}
setGraphic(todoItemControl);
......@@ -113,37 +100,4 @@ public class TodoItemListCell extends ListCell<TodoItem> {
super.cancelEdit();
configureViewer();
}
private void handleDragStart(MouseEvent event) {
Dragboard dragboard = startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(getItem().getText());
dragboard.setContent(content);
event.consume();
}
private void handleDragOver(DragEvent event) {
if (event.getGestureSource() instanceof TodoItemListCell) {
event.acceptTransferModes(TransferMode.MOVE);
}
event.consume();
}
private void handleDragEnd(DragEvent event) {
boolean success = false;
if (event.getGestureSource() instanceof TodoItemListCell) {
TodoItem sourceItem = ((TodoItemListCell) event.getGestureSource()).getItem();
TodoItem targetItem = getItem();
TodoList todoList = ((TodoListItem) sourceItem).getTodoList();
if (todoList.indexOf(sourceItem) >= 0) {
int newIndex = todoList.indexOf(targetItem);
if (newIndex >= 0) {
todoList.moveTodoItem(sourceItem, newIndex);
success = true;
}
}
}
event.setDropCompleted(success);
event.consume();
}
}
package todolist.ui;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import todolist.core.TodoItem;
import todolist.core.TodoList;
public class TodoItemListCellDragHandler {
private final TodoList todoList;
public TodoItemListCellDragHandler(TodoList todoList) {
this.todoList = todoList;
}
/**
* Register this handler for the provided TodoItemListCell. Will attach dragDetected, dragOver and
* dragDropped handlers.
*
* @param listCell the TodoItemListCell
*/
public void registerHandlers(TodoItemListCell listCell) {
listCell.setOnDragDetected(this::handleDragStart);
listCell.setOnDragOver(this::handleDragOver);
listCell.setOnDragDropped(this::handleDragEnd);
}
private void handleDragStart(MouseEvent event) {
if (event.getSource() instanceof TodoItemListCell) {
TodoItemListCell listCell = (TodoItemListCell) event.getSource();
if (!listCell.isEmpty()) {
Dragboard dragboard = listCell.startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
content.putString(listCell.getItem().getText());
dragboard.setContent(content);
event.consume();
}
}
}
private void handleDragOver(DragEvent event) {
if (event.getGestureSource() instanceof TodoItemListCell
&& event.getSource() instanceof TodoItemListCell) {
TodoItemListCell listCell = (TodoItemListCell) event.getSource();
if (!listCell.isEmpty()) {
event.acceptTransferModes(TransferMode.MOVE);
}
}
event.consume();
}
private void handleDragEnd(DragEvent event) {
boolean success = false;
if (event.getGestureSource() instanceof TodoItemListCell
&& event.getGestureTarget() instanceof TodoItemListCell) {
TodoItem sourceItem = ((TodoItemListCell) event.getGestureSource()).getItem();
TodoItemListCell target = (TodoItemListCell) event.getGestureTarget();
if (todoList.indexOf(sourceItem) >= 0 && (!target.isEmpty())) {
int newIndex = todoList.indexOf(target.getItem());
if (newIndex >= 0) {
todoList.moveTodoItem(sourceItem, newIndex);
success = true;
}
}
}
event.setDropCompleted(success);
event.consume();
}
}
package todolist.ui;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.input.KeyCode;
import javafx.stage.Stage;
import todolist.core.TodoItem;
import todolist.core.TodoList;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
......@@ -19,6 +21,7 @@ public class TodoAppTest extends ApplicationTest {
private TodoController controller;
private TodoList todoList;
private TodoItem item1, item2;
@Override
public void start(final Stage stage) throws Exception {
......@@ -30,30 +33,110 @@ public class TodoAppTest extends ApplicationTest {
stage.show();
}
@BeforeEach
public void setupItems() {
// same as in test-todolist.json (should perhaps read it instead)
item1 = new TodoItem().checked(true).text("Item 1");
item2 = new TodoItem().checked(false).text("Item 2");
}
@Test
public void testController() {
public void testController_todoList() {
assertNotNull(this.controller);
assertNotNull(this.todoList);
assertEquals(2, this.todoList.getTodoItems().size());
// initial todo items
checkTodoItems(this.todoList, item1, item2);
}
@Test
public void testTodoListView_initialItems() {
final ListView<TodoItem> todoListView = lookup("#todoListView").query();
// list contains same set of elements as the todo list (in some order)
Set<TodoItem> listViewItems = new HashSet<>(todoListView.getItems());
Set<TodoItem> todoListItems = new HashSet<>(this.todoList.getTodoItems());
assertEquals(todoListItems, listViewItems);
// initial todo items, note the unchecked one comes first
checkTodoItems(todoListView.getItems(), item2, item1);
}
@Test
public void testNewTodoItem() {
Set<TodoItem> todoListItems1 = new HashSet<>(this.todoList.getTodoItems());
clickOn("#newTodoItemText").write("New item");
String newItemText = "New item";
clickOn("#newTodoItemText").write(newItemText);
clickOn("#newTodoItemButton");
Set<TodoItem> todoListItems2 = new HashSet<>(this.todoList.getTodoItems());
todoListItems2.removeAll(todoListItems1);
// one new item
assertEquals(1, todoListItems2.size());
TodoItem newItem = new TodoItem().text(newItemText);
// item is added last in underlying todo list
checkTodoListItems(item1, item2, newItem);
// item is last of the unchecked items in list view
checkTodoListViewItems(item2, newItem, item1);
}
@Test
public void testCheckTodoItem() {
TodoItemListCell todoItemListCell = findTodoItemListCell(cell -> ! cell.getItem().isChecked());
clickOn(todoItemListCell.lookup(".check-box"));
TodoItem newItem2 = item2.withChecked(true);
// item is changed
checkTodoListItems(item1, newItem2);
// items in list view change order
checkTodoListViewItems(item1, newItem2);
}
@Test
public void testDragTodoItem() {
TodoItemListCell sourceTodoItemListCell = findTodoItemListCell(0);
TodoItemListCell targetTodoItemListCell = findTodoItemListCell(1);
drag(sourceTodoItemListCell).dropTo(targetTodoItemListCell);
// item order is changed
checkTodoListItems(item2, item1);
// items in list view do not change order
checkTodoListViewItems(item1, item2);
}
// utility methods
private TodoItemListCell findTodoItemListCell(int num) {
return findTodoItemListCell(cell -> true, num);
}
private TodoItemListCell findTodoItemListCell(Predicate<TodoItemListCell> test) {
return findTodoItemListCell(test, 0);
}
private TodoItemListCell findTodoItemListCell(Predicate<TodoItemListCell> test, int num) {
for (Node node : lookup(".list-cell").queryAll()) {
if (node instanceof TodoItemListCell) {
TodoItemListCell todoItemListCell = (TodoItemListCell) node;
if (test.test(todoItemListCell) && num-- == 0) {
return todoItemListCell;
}
}
}
fail();
return null;
}
private void checkTodoItem(TodoItem item, Boolean checked, String text) {
if (checked != null) {
assertEquals(checked, item.isChecked());
}
if (text != null) {
assertEquals(text, item.getText());
}
}
private void checkTodoListItems(TodoItem... items) {
checkTodoItems(this.todoList, items);
}
private void checkTodoListViewItems(TodoItem... items) {
final ListView<TodoItem> todoListView = lookup("#todoListView").query();
checkTodoItems(todoListView.getItems(), items);
}
private void checkTodoItems(Iterable<TodoItem> it, TodoItem... items) {
int i = 0;
for (TodoItem item : items) {
assertTrue(i < items.length);
checkTodoItem(item, items[i].isChecked(), items[i].getText());
i++;
}
assertTrue(i == items.length);
}
}
{
"items": [
{
"text": "Øl",
"checked": false
"text": "Item 1",
"checked": true
},
{
"text": "Pizza",
"text": "Item 2",
"checked": false
}
]
......
......@@ -93,6 +93,7 @@
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
<linkXRef>false</linkXRef>
</configuration>
<executions>
<execution>
<id>checkstyle-check</id>
......@@ -102,7 +103,6 @@
</goals>
</execution>
</executions>
</configuration>
</plugin>
<!-- Run the spotbugs code quality tool -->
<plugin>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment