diff --git a/javafx-template/src/main/java/app/AppController.java b/javafx-template/src/main/java/app/AppController.java index d622f38..9efef1c 100644 --- a/javafx-template/src/main/java/app/AppController.java +++ b/javafx-template/src/main/java/app/AppController.java @@ -19,6 +19,15 @@ public class AppController { calc = new Calc(0.0, 0.0, 0.0); } + public Calc getCalc() { + return calc; + } + + public void setCalc(Calc calc) { + this.calc = calc; + updateOperandsView(); + } + @FXML private ListView operandsView; diff --git a/javafx-template/src/test/java/app/AppTest.java b/javafx-template/src/test/java/app/AppTest.java index 018f314..aa6dc6e 100644 --- a/javafx-template/src/test/java/app/AppTest.java +++ b/javafx-template/src/test/java/app/AppTest.java @@ -3,22 +3,130 @@ package app; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Label; +import javafx.scene.control.ListView; import javafx.stage.Stage; import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.opentest4j.AssertionFailedError; import org.testfx.framework.junit5.ApplicationTest; +import org.testfx.matcher.control.LabeledMatchers; /** * TestFX App test */ public class AppTest extends ApplicationTest { + private AppController controller; + private Parent root; + @Override public void start(Stage stage) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("App.fxml")); - Parent parent = fxmlLoader.load(); - stage.setScene(new Scene(parent)); + root = fxmlLoader.load(); + controller = fxmlLoader.getController(); + stage.setScene(new Scene(root)); stage.show(); } + + public Parent getRootNode() { + return root; + } + + private String enterLabel = """ + E + n + t + e + r + """.stripTrailing(); + + private void click(String... labels) { + for (var label : labels) { + clickOn(LabeledMatchers.hasText(label)); + } + } + + private String getOperandString() { + return ((Label) getRootNode().lookup("#operandView")).getText(); + } + + private ListView getOperandsView() { + return (ListView) getRootNode().lookup("#operandsView"); + } + + private void checkView(double... operands) { + for (int i = 0; i < operands.length; i++) { + Assertions.assertEquals(operands[i], controller.getCalc().peekOperand(i), "Wrong value at #" + i + " of operand stack"); + } + List viewItems = getOperandsView().getItems(); + for (int i = 0; i < operands.length; i++) { + Assertions.assertEquals(operands[i], viewItems.get(viewItems.size() - i - 1), "Wrong value at #" + i + " of operands view"); + } + } + + private void checkView(String operandString, double... operands) { + Assertions.assertEquals(operandString, getOperandString()); + checkView(operands); + } + + // see https://www.baeldung.com/parameterized-tests-junit-5 + // about @ParameterizedTest + + @ParameterizedTest + @MethodSource + public void testClicksOperand(String labels, String operandString) { + for (var label : labels.split(" ")) { + click(label); + } + checkView(operandString); + } + + private static Stream testClicksOperand() { + return Stream.of( + Arguments.of("2 7", "27"), + Arguments.of("2 7 .", "27."), + Arguments.of("2 7 . 5", "27.5"), + Arguments.of("2 7 . 5 .", "27.") + ); + } + + @ParameterizedTest + @MethodSource + public void testClicksOperands(String labels, String operandsString) { + for (var label : labels.split(" ")) { + click(label.equals("\n") ? enterLabel : label); + } + checkView(Stream.of(operandsString.split(" ")).mapToDouble(Double::valueOf).toArray()); + } + + private static Stream testClicksOperands() { + return Stream.of( + Arguments.of("2 7 . 5 \n", "27.5"), + Arguments.of("2 7 \n", "27.0"), + Arguments.of("2 \n 7 \n 5 \n", "5.0", "7.0", "2.0"), + Arguments.of("2 7 . \n", "27.0"), + Arguments.of("2 7 . 5 \n", "27.5"), + Arguments.of("2 \n 7 +", "9.0"), + Arguments.of("2 \n 7 -", "-5.0"), + Arguments.of("2 \n 7 *", "14.0"), + Arguments.of("6 \n 3 /", "2.0"), + Arguments.of("2 5 \n √", "5.0") + ); + } + + @Test + public void testPi() { + click("π"); + checkView("", Math.PI); + } }