diff options
Diffstat (limited to 'src')
11 files changed, 595 insertions, 0 deletions
diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeController.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeController.java new file mode 100644 index 0000000..d81f6d7 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/controller/CreateNewEmployeeController.java @@ -0,0 +1,117 @@ +package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller; + +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.lang.invoke.MethodHandles; +import java.time.LocalDate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.Hyperlink; +import javafx.scene.control.TextField; +import javafx.stage.Stage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; + +@Controller +public class CreateNewEmployeeController { + +    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); +    private final EmployeeService employeeService; + +    @FXML private CheckBox inputIsDriver; +    @FXML private CheckBox inputIsPilot; +    @FXML private Hyperlink btnCancel; +    @FXML private Button btnCreate; +    @FXML private TextField inputName; +    @FXML private ChoiceBox<String> inputQualification; + +    public CreateNewEmployeeController(EmployeeService employeeService) { +        this.employeeService = employeeService; +    } + +    @FXML +    public void initialize() { +        inputQualification.setItems( +                FXCollections.observableArrayList( +                        Stream.of( +                                        EducationLevel.RS, +                                        EducationLevel.NFS, +                                        EducationLevel.NKV, +                                        EducationLevel.NKA, +                                        EducationLevel.NKI, +                                        EducationLevel.NA) +                                .map(Enum::toString) +                                .collect(Collectors.toList()))); + +        inputQualification.setValue(EducationLevel.RS.toString()); +    } + +    @FXML +    public void onCancelClicked() { +        ((Stage) inputQualification.getScene().getWindow()).close(); +    } + +    @FXML +    public void onCreateClicked() { + +        Employee employee = +                Employee.builder() +                        .name(inputName.getText()) +                        .educationLevel(parseEducationLevel()) +                        .birthday(LocalDate.MIN) // TODO: change UI to include birthday field +                        .isDriver(inputIsDriver.isSelected()) +                        .isPilot(inputIsPilot.isSelected()) +                        .build(); + +        try { +            employeeService.add(employee); +        } catch (InvalidEmployeeException e) { +            LOG.error("Invalid Employee: {}", e); + +            showModalDialogWithOkButton( +                    AlertType.ERROR, +                    "Ungültige Eingabe", +                    "Mindestens eines der Eingabefelder haben einen ungültigen Wert!"); +            return; +        } catch (ServiceException e) { +            LOG.error("Employee could not be saved: {}", e); + +            showModalDialogWithOkButton( +                    AlertType.ERROR, +                    "Speicherfehler", +                    "Der Eintrag konnte nicht gespeichert werden. Bitte versuchen Sie es erneut."); +            return; +        } + +        showModalDialogWithOkButton( +                AlertType.INFORMATION, +                "Erfolgreich angelegt", +                "Mitarbeiter wurde erfolgreich angelegt und gespeichert!"); +    } + +    private void showModalDialogWithOkButton( +            AlertType alertType, String headerText, String contentText) { +        Alert alert = new Alert(alertType, contentText, ButtonType.OK); +        alert.setHeaderText(headerText); +        alert.showAndWait(); +    } + +    private EducationLevel parseEducationLevel() { +        if (inputQualification.getSelectionModel().getSelectedItem() == null) { +            return EducationLevel.RS; +        } +        return EducationLevel.valueOf(inputQualification.getSelectionModel().getSelectedItem()); +    } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDao.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDao.java new file mode 100644 index 0000000..fc9a549 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dao/EmployeeDatabaseDao.java @@ -0,0 +1,84 @@ +package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao; + +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ElementNotFoundException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.JDBCConnectionManager; +import java.lang.invoke.MethodHandles; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +@Repository +public class EmployeeDatabaseDao implements EmployeeDAO { + +    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); +    private static final String INSERT_EMPLOYEE_VERSION = +            "INSERT INTO EmployeeVersion(name, birthday, educationLevel, isDriver, isPilot) " +                    + "VALUES(?, ?, ?, ?, ?)"; +    private static final String INSERT_EMPLOYEE = "INSERT INTO Employee(version) VALUES(?)"; + +    private final PreparedStatement insertEmployeeVersion, insertEmployee; + +    public EmployeeDatabaseDao(JDBCConnectionManager connectionManager) +            throws PersistenceException { + +        try { + +            final var connection = connectionManager.getConnection(); +            insertEmployeeVersion = +                    connection.prepareStatement( +                            INSERT_EMPLOYEE_VERSION, Statement.RETURN_GENERATED_KEYS); +            insertEmployee = +                    connection.prepareStatement(INSERT_EMPLOYEE, Statement.RETURN_GENERATED_KEYS); + +        } catch (SQLException e) { +            throw new PersistenceException(e); +        } +    } + +    @Override +    public long add(Employee employee) throws PersistenceException { + +        // Assumption: the given employee is already validated (from service) +        try { +            insertEmployeeVersion.setString(1, employee.name()); +            insertEmployeeVersion.setTimestamp( +                    2, Timestamp.valueOf(employee.birthday().atStartOfDay())); +            insertEmployeeVersion.setString(3, employee.educationLevel().toString()); +            insertEmployeeVersion.setBoolean(4, employee.isDriver()); +            insertEmployeeVersion.setBoolean(5, employee.isPilot()); +            insertEmployeeVersion.executeUpdate(); +            ResultSet rs = insertEmployeeVersion.getGeneratedKeys(); +            if (rs.next()) { +                return rs.getLong(1); +            } + +            throw new PersistenceException("Employee was not created"); + +        } catch (SQLException e) { +            throw new PersistenceException(e); +        } +    } + +    @Override +    public void update(Employee employee) throws ElementNotFoundException, PersistenceException { +        throw new UnsupportedOperationException(); +    } + +    @Override +    public List<Employee> list() throws PersistenceException { +        throw new UnsupportedOperationException(); +    } + +    @Override +    public void remove(long id) throws ElementNotFoundException, PersistenceException { +        throw new UnsupportedOperationException(); +    } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/EmployeeValidator.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/EmployeeValidator.java new file mode 100644 index 0000000..d7fa9aa --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/dto/EmployeeValidator.java @@ -0,0 +1,23 @@ +package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto; + +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; + +public class EmployeeValidator { + +    public static boolean validate(Employee employee) throws InvalidEmployeeException { + +        if (employee.name() == null || employee.name().trim().length() == 0) { +            throw new InvalidEmployeeException("name not set"); +        } + +        if (employee.birthday() == null) { +            throw new InvalidEmployeeException("birthday not set"); +        } + +        if (employee.educationLevel() == null) { +            throw new InvalidEmployeeException("educationLevel not set"); +        } + +        return true; +    } +} diff --git a/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java new file mode 100644 index 0000000..144ccc6 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sepm/assignment/groupphase/einsatzverwaltung/service/EmployeeServiceImpl.java @@ -0,0 +1,44 @@ +package at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service; + +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.EmployeeDAO; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.EmployeeValidator; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.util.List; +import org.springframework.stereotype.Service; + +@Service +public class EmployeeServiceImpl implements EmployeeService { + +    private final EmployeeDAO employeePersistence; + +    public EmployeeServiceImpl(EmployeeDAO employeePersistence) { +        this.employeePersistence = employeePersistence; +    } + +    @Override +    public long add(Employee employee) throws InvalidEmployeeException, ServiceException { + +        EmployeeValidator.validate(employee); +        try { +            return employeePersistence.add(employee); +        } catch (PersistenceException e) { +            throw new ServiceException(e); +        } +    } + +    @Override +    public Employee update(Employee employee) throws InvalidEmployeeException, ServiceException { +        return null; +    } + +    @Override +    public List<Employee> list() throws ServiceException { +        return null; +    } + +    @Override +    public void remove(long id) throws InvalidEmployeeException, ServiceException {} +} diff --git a/src/main/resources/fxml/createNewEmployee.fxml b/src/main/resources/fxml/createNewEmployee.fxml new file mode 100644 index 0000000..5fa1ca9 --- /dev/null +++ b/src/main/resources/fxml/createNewEmployee.fxml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.CheckBox?> +<?import javafx.scene.control.ChoiceBox?> +<?import javafx.scene.control.Hyperlink?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> + + +<AnchorPane prefHeight="114.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.controller.CreateNewEmployeeController"> +   <children> +      <Label layoutX="14.0" layoutY="14.0" text="Neue Person erstellen" /> +      <Label layoutX="14.0" layoutY="38.0" text="Name" /> +      <Label layoutX="206.0" layoutY="38.0" text="Qualifikation" /> +      <CheckBox fx:id="inputIsDriver" layoutX="343.0" layoutY="37.0" mnemonicParsing="false" text="Fahrer" /> +      <CheckBox fx:id="inputIsPilot" layoutX="343.0" layoutY="62.0" mnemonicParsing="false" text="Pilot" /> +      <Hyperlink fx:id="btnCancel" layoutX="441.0" layoutY="31.0" onAction="#onCancelClicked" text="abbrechen" /> +      <Button fx:id="btnCreate" layoutX="441.0" layoutY="55.0" mnemonicParsing="false" onAction="#onCreateClicked" text="Erstellen" /> +      <TextField fx:id="inputName" layoutX="14.0" layoutY="57.0" prefHeight="25.0" prefWidth="179.0" /> +      <ChoiceBox fx:id="inputQualification" layoutX="199.0" layoutY="57.0" prefHeight="25.0" prefWidth="128.0" /> +   </children> +</AnchorPane> diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/CreateNewEmployeeApplication.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/CreateNewEmployeeApplication.java new file mode 100644 index 0000000..e9f4801 --- /dev/null +++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/CreateNewEmployeeApplication.java @@ -0,0 +1,53 @@ +package at.ac.tuwien.sepm.assignment.groupphase.employee; + +import at.ac.tuwien.sepm.assignment.groupphase.util.SpringFXMLLoader; +import java.lang.invoke.MethodHandles; +import javafx.application.Application; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.stage.Stage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.stereotype.Component; + +@Component +@ComponentScan("at.ac.tuwien.sepm.assignment.groupphase") +public final class CreateNewEmployeeApplication extends Application { + +    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + +    public static AnnotationConfigApplicationContext context; + +    @Override +    public void start(Stage primaryStage) throws Exception { +        // setup application +        primaryStage.setTitle("Person anlegen"); +        primaryStage.setWidth(1366); +        primaryStage.setHeight(768); +        primaryStage.centerOnScreen(); +        primaryStage.setOnCloseRequest(event -> LOG.debug("Application shutdown initiated")); + +        context = new AnnotationConfigApplicationContext(CreateNewEmployeeApplication.class); +        final var fxmlLoader = context.getBean(SpringFXMLLoader.class); +        primaryStage.setScene( +                new Scene( +                        (Parent) +                                fxmlLoader.load( +                                        getClass() +                                                .getResourceAsStream( +                                                        "/fxml/createNewEmployee.fxml")))); + +        // show application +        primaryStage.show(); +        primaryStage.toFront(); +        LOG.debug("Application startup complete"); +    } + +    @Override +    public void stop() { +        LOG.debug("Stopping application"); +        context.close(); +    } +} diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/CreateNewEmployeeControllerTest.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/CreateNewEmployeeControllerTest.java new file mode 100644 index 0000000..da8a6ac --- /dev/null +++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/CreateNewEmployeeControllerTest.java @@ -0,0 +1,105 @@ +package at.ac.tuwien.sepm.assignment.groupphase.employee; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import at.ac.tuwien.sepm.assignment.groupphase.util.HighDpiAwareApplicationTest; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javafx.scene.control.DialogPane; +import javafx.scene.input.MouseButton; +import javafx.stage.Modality; +import javafx.stage.Stage; +import javafx.stage.Window; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.testfx.api.FxToolkit; +import org.testfx.robot.Motion; + +public class CreateNewEmployeeControllerTest extends HighDpiAwareApplicationTest { + +    private EmployeeService employeeService; + +    @Before +    public void setup() throws Exception { +        // TODO: check if testfx can be run in headless mode on Jenkins +        FxToolkit.registerPrimaryStage(); +        FxToolkit.setupApplication(CreateNewEmployeeApplication.class); +        employeeService = CreateNewEmployeeApplication.context.getBean(EmployeeService.class); +    } + +    @After +    public void cleanup() throws Exception { +        FxToolkit.cleanupStages(); +    } + +    @Test +    public void testClickAddValidEmployee() throws InvalidEmployeeException, ServiceException { + +        when(employeeService.add(any())).thenReturn(1L); + +        clickOn("#inputName", Motion.DIRECT, MouseButton.PRIMARY); +        write("Name"); +        clickOn("#btnCreate", Motion.DIRECT, MouseButton.PRIMARY); + +        Stage alertDialog = getTopModalStage(); +        Assert.assertNotNull(alertDialog); + +        DialogPane dialogPane = (DialogPane) alertDialog.getScene().getRoot(); +        Assert.assertEquals("Erfolgreich angelegt", dialogPane.getHeaderText()); +    } + +    @Test +    public void testClickAddInvalidEmployee() throws InvalidEmployeeException, ServiceException { + +        when(employeeService.add(any())).thenThrow(InvalidEmployeeException.class); + +        moveTo("#inputName"); +        clickOn("#btnCreate", Motion.DIRECT, MouseButton.PRIMARY); + +        Stage alertDialog = getTopModalStage(); +        Assert.assertNotNull(alertDialog); + +        DialogPane dialogPane = (DialogPane) alertDialog.getScene().getRoot(); +        Assert.assertEquals("Ungültige Eingabe", dialogPane.getHeaderText()); +    } + +    @Test +    public void testClickAddEmployeeWithServiceException() +            throws InvalidEmployeeException, ServiceException { + +        when(employeeService.add(any())).thenThrow(ServiceException.class); + +        clickOn("#inputName", Motion.DIRECT, MouseButton.PRIMARY); +        write("Test"); +        clickOn("#btnCreate", Motion.DIRECT, MouseButton.PRIMARY); + +        Stage alertDialog = getTopModalStage(); +        Assert.assertNotNull(alertDialog); + +        DialogPane dialogPane = (DialogPane) alertDialog.getScene().getRoot(); +        Assert.assertEquals("Speicherfehler", dialogPane.getHeaderText()); +    } + +    private Stage getTopModalStage() { + +        List<Window> allWindows = new ArrayList<>(robotContext().getWindowFinder().listWindows()); +        Collections.reverse(allWindows); +        return (Stage) +                allWindows +                        .stream() +                        .filter(window -> window instanceof Stage) +                        .filter( +                                window -> +                                        ((Stage) window).getModality() +                                                == Modality.APPLICATION_MODAL) +                        .findFirst() +                        .orElse(null); +    } +} diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeeServiceTest.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeeServiceTest.java new file mode 100644 index 0000000..47328b3 --- /dev/null +++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeeServiceTest.java @@ -0,0 +1,68 @@ +package at.ac.tuwien.sepm.assignment.groupphase.employee; + +import static junit.framework.TestCase.fail; +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.EmployeeDAO; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dao.EmployeeDatabaseDao; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.dto.Employee.EducationLevel; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeServiceImpl; +import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidEmployeeException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.PersistenceException; +import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; +import java.time.LocalDate; +import org.junit.Assert; +import org.junit.Test; + +public class EmployeeServiceTest { + +    private final EmployeeDAO employeePersistence = mock(EmployeeDatabaseDao.class); +    private final EmployeeService employeeService = new EmployeeServiceImpl(employeePersistence); + +    public EmployeeServiceTest() throws PersistenceException { +        when(employeePersistence.add(any())).thenReturn(1L); +    } + +    @Test +    public void testAddValidEmployee() { + +        Employee employee = +                Employee.builder() +                        .name("Testperson") +                        .birthday(LocalDate.MIN) +                        .educationLevel(EducationLevel.NA) +                        .isDriver(true) +                        .isPilot(false) +                        .build(); + +        try { +            Assert.assertThat(employeeService.add(employee), is(1L)); +        } catch (InvalidEmployeeException | ServiceException e) { +            fail(); +        } +    } + +    @Test(expected = InvalidEmployeeException.class) +    public void testAddInvalidEmployee() throws InvalidEmployeeException { + +        Employee employee = +                Employee.builder() +                        .name("") +                        .birthday(LocalDate.MIN) +                        .educationLevel(EducationLevel.NA) +                        .isDriver(true) +                        .isPilot(false) +                        .build(); + +        try { +            employeeService.add(employee); +        } catch (ServiceException e) { +            fail(); +        } +    } +} diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeeServiceTestConfiguration.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeeServiceTestConfiguration.java new file mode 100644 index 0000000..3668ef4 --- /dev/null +++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/employee/EmployeeServiceTestConfiguration.java @@ -0,0 +1,19 @@ +package at.ac.tuwien.sepm.assignment.groupphase.employee; + +import static org.mockito.Mockito.mock; + +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeService; +import at.ac.tuwien.sepm.assignment.groupphase.einsatzverwaltung.service.EmployeeServiceImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +@Configuration +public class EmployeeServiceTestConfiguration { + +    @Bean +    @Primary +    public EmployeeService employeeService() { +        return mock(EmployeeServiceImpl.class); +    } +} diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/util/HighDpiAwareApplicationTest.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/util/HighDpiAwareApplicationTest.java new file mode 100644 index 0000000..c9816a1 --- /dev/null +++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/util/HighDpiAwareApplicationTest.java @@ -0,0 +1,24 @@ +package at.ac.tuwien.sepm.assignment.groupphase.util; + +import javafx.geometry.Bounds; +import javafx.scene.Node; +import org.testfx.api.FxRobotContext; +import org.testfx.framework.junit.ApplicationTest; +import org.testfx.service.locator.impl.BoundsLocatorImpl; +import org.testfx.service.locator.impl.PointLocatorImpl; + +public class HighDpiAwareApplicationTest extends ApplicationTest { + +    public HighDpiAwareApplicationTest() { +        FxRobotContext context = robotContext(); +        context.setBoundsLocator( +                new BoundsLocatorImpl() { +                    @Override +                    public Bounds boundsOnScreenFor(Node node) { +                        Bounds bounds = super.boundsOnScreenFor(node); +                        return ScaledBounds.wrap(bounds); +                    } +                }); +        robotContext().setPointLocator(new PointLocatorImpl(context.getBoundsLocator())); +    } +} diff --git a/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/util/ScaledBounds.java b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/util/ScaledBounds.java new file mode 100644 index 0000000..02c15c4 --- /dev/null +++ b/src/test/java/at/ac/tuwien/sepm/assignment/groupphase/util/ScaledBounds.java @@ -0,0 +1,34 @@ +package at.ac.tuwien.sepm.assignment.groupphase.util; + +import java.awt.GraphicsEnvironment; +import javafx.geometry.BoundingBox; +import javafx.geometry.Bounds; + +public class ScaledBounds extends BoundingBox { + +    private static final double scale; + +    static { +        scale = +                1 +                        / GraphicsEnvironment.getLocalGraphicsEnvironment() +                                .getDefaultScreenDevice() +                                .getDefaultConfiguration() +                                .getDefaultTransform() +                                .getScaleX(); +    } + +    public static ScaledBounds wrap(Bounds bounds) { +        return new ScaledBounds(bounds); +    } + +    private ScaledBounds(Bounds wrapped) { +        super( +                wrapped.getMinX() * scale, +                wrapped.getMinY() * scale, +                wrapped.getMinZ() * scale, +                wrapped.getWidth() * scale, +                wrapped.getHeight() * scale, +                wrapped.getDepth()); +    } +}  | 
