From 9bac810518af0d1618ab21d01e96bf4a00099ac0 Mon Sep 17 00:00:00 2001 From: Adrian Kunz Date: Fri, 15 Mar 2024 10:20:27 +0100 Subject: [PATCH 1/3] Update Dependencies (#63) * chore: Update to Gradle 8.6 * chore: Update framework test dependencies * ci: Submit Gradle dependencies to GitHub * build(ludo): Remove libs directory dependencies * chore(ludo): Update dependencies * chore(ludo): Update JavaFX * refactor: Put dependency versions in gradle.properties * chore: Put remaining dependencies in gradle.properties --- .github/workflows/gradle-dependencies.yaml | 19 ++ annotation-processor/build.gradle | 10 +- framework/build.gradle | 46 +--- gradle.properties | 54 ++++ gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 43462 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 282 +++++++++++++-------- gradlew.bat | 35 +-- ludo/build.gradle | 71 ++---- 9 files changed, 301 insertions(+), 220 deletions(-) create mode 100644 .github/workflows/gradle-dependencies.yaml diff --git a/.github/workflows/gradle-dependencies.yaml b/.github/workflows/gradle-dependencies.yaml new file mode 100644 index 00000000..20936958 --- /dev/null +++ b/.github/workflows/gradle-dependencies.yaml @@ -0,0 +1,19 @@ +name: Gradle Dependency Submission + +on: + push: + paths: + - '**/*.gradle' + - '.github/workflows/dependencies.yaml' + +permissions: + contents: write + +jobs: + dependency-submission: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + - name: Generate and submit dependency graph + uses: gradle/actions/dependency-submission@v3 diff --git a/annotation-processor/build.gradle b/annotation-processor/build.gradle index 4d61c278..ad32817e 100644 --- a/annotation-processor/build.gradle +++ b/annotation-processor/build.gradle @@ -20,14 +20,10 @@ repositories { // Project dependencies dependencies { - // https://mvnrepository.com/artifact/com.google.auto.service/auto-service-annotations - implementation group: 'com.google.auto.service', name: 'auto-service-annotations', version: '1.1.1' + implementation group: 'com.google.auto.service', name: 'auto-service-annotations', version: autoServiceVersion + annotationProcessor group: 'com.google.auto.service', name: 'auto-service', version: autoServiceVersion - // https://mvnrepository.com/artifact/com.google.auto.service/auto-service - annotationProcessor group: 'com.google.auto.service', name: 'auto-service', version: '1.1.1' - - // Framework - implementation project(":framework") + implementation project(':framework') } // ------------------- Build ------------------- diff --git a/framework/build.gradle b/framework/build.gradle index b421aeb4..c9005a2e 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -2,8 +2,7 @@ plugins { id "java" id 'maven-publish' id 'signing' - // https://plugins.gradle.org/plugin/org.openjfx.javafxplugin - id "org.openjfx.javafxplugin" version "0.1.0" + id "org.openjfx.javafxplugin" version "$javaFxPluginVersion" } group = projectGroup @@ -22,51 +21,32 @@ repositories { // JavaFX dependencies javafx { - version = '21.0.2' + version = javaFxVersion modules = ['javafx.controls', 'javafx.graphics', 'javafx.fxml', 'javafx.media'] } // Project dependencies dependencies { - // https://mvnrepository.com/artifact/org.jetbrains/annotations - implementation group: 'org.jetbrains', name: 'annotations', version: '24.1.0' + implementation group: 'org.jetbrains', name: 'annotations', version: jetbrainsAnnotationsVersion + implementation group: 'io.reactivex.rxjava3', name: 'rxjava', version: rxJavaVersion - // https://mvnrepository.com/artifact/com.google.dagger/dagger - implementation group: 'com.google.dagger', name: 'dagger', version: '2.51' - - // https://mvnrepository.com/artifact/com.google.dagger/dagger-compiler - annotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: '2.51' - - // https://mvnrepository.com/artifact/io.reactivex.rxjava3/rxjava - implementation group: 'io.reactivex.rxjava3', name: 'rxjava', version: '3.1.8' + implementation group: 'com.google.dagger', name: 'dagger', version: daggerVersion + annotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: daggerVersion } // ------------------- Tests ------------------- // Test dependencies dependencies { + testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junitJupiterVersion + testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junitJupiterVersion - // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api - testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.1' - - // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine - testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.1' - - // https://mvnrepository.com/artifact/org.testfx/testfx-junit5 - testImplementation group: 'org.testfx', name: 'testfx-junit5', version: '4.0.17' - - // https://mvnrepository.com/artifact/org.hamcrest/hamcrest - testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2' - - // https://mvnrepository.com/artifact/org.testfx/openjfx-monocle - testImplementation group: 'org.testfx', name: 'openjfx-monocle', version: '17.0.10' - - // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter - testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: '5.11.0' - - // https://mvnrepository.com/artifact/com.google.dagger/dagger-compiler - testAnnotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: '2.51' + testImplementation group: 'org.testfx', name: 'testfx-junit5', version: testFxVersion + testImplementation group: 'org.testfx', name: 'openjfx-monocle', version: monocleVersion + testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: mockitoVersion + testImplementation group: 'org.hamcrest', name: 'hamcrest', version: hamcrestVersion + testAnnotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: daggerVersion } test { diff --git a/gradle.properties b/gradle.properties index 852091b5..5cadc808 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,3 +10,57 @@ javaSourceVersion = 17 javaTargetVersion = 17 generateSourcesJar = false generateJavadocJar = false + +# --------------- Gradle Plugins --------------- + +# https://plugins.gradle.org/plugin/com.github.johnrengelman.shadow +shadowPluginVersion = 7.0.0 + +# https://plugins.gradle.org/plugin/org.openjfx.javafxplugin +javaFxPluginVersion = 0.1.0 + +# https://plugins.gradle.org/plugin/org.fulib.fulibGradle +fulibGradlePluginVersion = 0.5.0 + +# --------------- Dependencies --------------- + +# https://mvnrepository.com/artifact/org.openjfx/javafx-base +javaFxVersion = 21.0.2 + +# https://mvnrepository.com/artifact/org.jetbrains/annotations +jetbrainsAnnotationsVersion = 24.1.0 + +# https://mvnrepository.com/artifact/com.google.dagger/dagger +# https://mvnrepository.com/artifact/com.google.dagger/dagger-compiler +daggerVersion = 2.51 + +# https://mvnrepository.com/artifact/io.reactivex.rxjava3/rxjava +rxJavaVersion = 3.1.8 + +# https://mvnrepository.com/artifact/com.google.auto.service/auto-service +# https://mvnrepository.com/artifact/com.google.auto.service/auto-service-annotations +autoServiceVersion = 1.1.1 + +# https://mvnrepository.com/artifact/org.fulib/fulib +fulibVersion = 1.6.2 + +# https://mvnrepository.com/artifact/org.fulib/fulibScenarios +fulibScenariosVersion = 1.7.1 + +# --------------- Test Dependencies --------------- + +# https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api +# https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine +junitJupiterVersion = 5.10.2 + +# https://mvnrepository.com/artifact/org.testfx/testfx-junit5 +testFxVersion = 4.0.18 + +# https://mvnrepository.com/artifact/org.testfx/openjfx-monocle +monocleVersion = 17.0.10 + +# https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter +mockitoVersion = 5.11.0 + +# https://mvnrepository.com/artifact/org.hamcrest/hamcrest +hamcrestVersion = 2.2 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e411586a..a80b22ce 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 744e882e..1aa94a42 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,99 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +119,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,88 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd32..25da30db 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,13 +41,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/ludo/build.gradle b/ludo/build.gradle index 60971e24..7756fee5 100644 --- a/ludo/build.gradle +++ b/ludo/build.gradle @@ -1,67 +1,40 @@ plugins { id "java" - id "org.openjfx.javafxplugin" version "0.0.13" - id "com.github.johnrengelman.shadow" version "7.0.0" - id 'org.fulib.fulibGradle' version '0.5.0' -} - -configurations { - internal - implementation.extendsFrom(internal) + id "org.openjfx.javafxplugin" version "$javaFxPluginVersion" + id "com.github.johnrengelman.shadow" version "$shadowPluginVersion" + id 'org.fulib.fulibGradle' version "$fulibGradlePluginVersion" } // JavaFX dependencies javafx { - version = '20' + version = javaFxVersion modules = ['javafx.controls', 'javafx.graphics', 'javafx.fxml', 'javafx.media'] } // Project dependencies dependencies { - // https://mvnrepository.com/artifact/org.jetbrains/annotations - implementation 'org.jetbrains:annotations:24.0.1' - - // https://mvnrepository.com/artifact/com.google.dagger/dagger - implementation group: 'com.google.dagger', name: 'dagger', version: '2.42' - - // https://mvnrepository.com/artifact/com.google.dagger/dagger-compiler - annotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: '2.42' - - // https://mvnrepository.com/artifact/io.reactivex.rxjava3/rxjava - implementation group: 'io.reactivex.rxjava3', name: 'rxjava', version: '3.1.4' + implementation group: 'org.jetbrains', name: 'annotations', version: jetbrainsAnnotationsVersion + implementation group: 'io.reactivex.rxjava3', name: 'rxjava', version: rxJavaVersion - // https://mvnrepository.com/artifact/org.fulib/fulibScenarios - fulibScenarios group: 'org.fulib', name: 'fulibScenarios', version: '1.7.0' + implementation group: 'com.google.dagger', name: 'dagger', version: daggerVersion + annotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: daggerVersion - // https://mvnrepository.com/artifact/org.fulib/fulib - fulibScenarios group: 'org.fulib', name: 'fulib', version: '1.6.2' + fulibScenarios group: 'org.fulib', name: 'fulibScenarios', version: fulibScenariosVersion + fulibScenarios group: 'org.fulib', name: 'fulib', version: fulibVersion - implementation project(":framework") + implementation project(':framework') } // ------------------- Tests ------------------- // Test dependencies dependencies { - - // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api - testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.9.2' - - // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine - testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.9.2' - - // https://mvnrepository.com/artifact/org.testfx/testfx-junit5 - testImplementation group: 'org.testfx', name: 'testfx-junit5', version: '4.0.16-alpha' - - // https://mvnrepository.com/artifact/org.testfx/openjfx-monocle - testImplementation group: 'org.testfx', name: 'openjfx-monocle', version: '17.0.10' - - // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter - testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: '5.2.0' - - // https://mvnrepository.com/artifact/com.google.dagger/dagger-compiler - testAnnotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: '2.42' - + testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: junitJupiterVersion + testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: junitJupiterVersion + testImplementation group: 'org.testfx', name: 'testfx-junit5', version: testFxVersion + testImplementation group: 'org.testfx', name: 'openjfx-monocle', version: monocleVersion + testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: mockitoVersion + testAnnotationProcessor group: 'com.google.dagger', name: 'dagger-compiler', version: daggerVersion } java { @@ -74,10 +47,6 @@ test { } jar { - from { - configurations.internal.collect { it.isDirectory() ? it : zipTree(it) } - } - manifest { attributes( "Manifest-Version": 1.0, @@ -106,12 +75,6 @@ repositories { group projectGroup version projectVersion -// Include local jar dependencies -dependencies { - implementation fileTree(dir: "libs/implementation", include: "*.jar") - internal fileTree(dir: "libs/internal", include: "*.jar") -} - static JavaVersion getVersionForMajor(String version) { return JavaVersion.values().find { (it.majorVersion == version) } } From bfef993fb85652711975a109d3dc29dc85846753 Mon Sep 17 00:00:00 2001 From: Paul Mertens <50475262+LeStegii@users.noreply.github.com> Date: Sun, 24 Mar 2024 11:36:29 +0100 Subject: [PATCH 2/3] Add badges for Javadocs and other stuff (#69) * docs(framework): Add badges to readme * docs(framework): Add badges to related javadocs * fix(docs): Fix link * fix(docs): Add link to GH Pages --- README.md | 5 +++-- docs/controller/1-controllers.md | 4 ++-- docs/controller/10-key-events.md | 2 +- docs/controller/2-components.md | 2 +- docs/controller/4-parameters.md | 2 +- docs/controller/5-internationalization.md | 2 +- docs/controller/6-titles.md | 2 +- docs/controller/7-routing.md | 2 +- docs/controller/8-subcomponents.md | 2 +- docs/features/1-subscriber.md | 2 +- docs/features/2-for.md | 2 +- docs/features/4-modals.md | 2 +- docs/features/5-node-duplicator.md | 2 +- docs/features/6-data-structures.md | 12 ++++++------ 14 files changed, 22 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 5fb9e272..d9693608 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# ☕ fulibFx +# ☕ fulibFx +[![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/javadoc.svg?style=for-the-badge&color=green)](https://javadoc.io/doc/org.fulib/fulibFx) ![Java 17/21](https://img.shields.io/github/actions/workflow/status/fujaba/fulibFx/java-ci-cd.yaml?style=for-the-badge&logo=github&color=green) [![GH Pages](https://img.shields.io/badge/GH_Pages-Click_here-green?style=for-the-badge&logo=github)](https://fujaba.github.io/fulibFx) fulibFx is a versatile framework for JavaFX applications that is specifically designed for MVC pattern projects. It provides a simple way to create and manage controllers, views, routes, subcomponents, modals, and more. @@ -125,7 +126,7 @@ When developing an application, it is often necessary to reload the application a way to [refresh a controller](docs/features/3-history.md) without having to reload the whole application. This can be done by calling the `refresh` method - +GIF showing the hot reload feature ### 🧷 Utilities diff --git a/docs/controller/1-controllers.md b/docs/controller/1-controllers.md index 6b78dc5d..fb5c5c74 100644 --- a/docs/controller/1-controllers.md +++ b/docs/controller/1-controllers.md @@ -1,4 +1,4 @@ -# Controller +# Controller [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/controller/Controller.html) Controllers are the backbone of your application. To set up a controller, create a class where the controller logic will be defined and annotate it with `@Controller`. @@ -11,7 +11,7 @@ public class TodoController { } ``` -### Events +### Events [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/event/package-summary.html) Within your controller class, you have the ability to define methods that are automatically triggered when the controller is initialized, rendered or destroyed. These methods should be annotated with either `@onInit`, `@onRender` diff --git a/docs/controller/10-key-events.md b/docs/controller/10-key-events.md index 5d3c5c42..c8e38087 100644 --- a/docs/controller/10-key-events.md +++ b/docs/controller/10-key-events.md @@ -1,4 +1,4 @@ -# Keyboard Listener +# Keyboard Listener [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/event/onKey.html) The framework provides an easy way of registering keybinds for a controller. By using the `@onKey` annotation, you can define methods that will be called when a key is pressed. diff --git a/docs/controller/2-components.md b/docs/controller/2-components.md index e87506e3..bfd9d2c2 100644 --- a/docs/controller/2-components.md +++ b/docs/controller/2-components.md @@ -1,4 +1,4 @@ -# Components +# Components [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/controller/Component.html) Components are a special type of controller that can be used to create reusable components. Components have to extend from a JavaFX Parent (or any class extending from Parent) and have to be annotated with `@Component`. diff --git a/docs/controller/4-parameters.md b/docs/controller/4-parameters.md index a3980f09..07abf369 100644 --- a/docs/controller/4-parameters.md +++ b/docs/controller/4-parameters.md @@ -1,4 +1,4 @@ -# Parameters +# Parameters [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/param/package-summary.html) To pass parameters to a controller, an additional argument can be provided to the show method, consisting of a map of strings and objects. The strings specify the argument's name and the objects are the value of the argument. For example, diff --git a/docs/controller/5-internationalization.md b/docs/controller/5-internationalization.md index b9d2a404..7df8aa85 100644 --- a/docs/controller/5-internationalization.md +++ b/docs/controller/5-internationalization.md @@ -1,4 +1,4 @@ -# Internationalization +# Internationalization [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/controller/Resource.html) In order to use resource bundles in your controller's FXML file, you have to provide an instance of the resource bundle to the framework. This can be done by creating a field containing your instance (e.g. with Dagger) and annotating it with `@Resource`. diff --git a/docs/controller/6-titles.md b/docs/controller/6-titles.md index a049d55b..d6d782fb 100644 --- a/docs/controller/6-titles.md +++ b/docs/controller/6-titles.md @@ -1,4 +1,4 @@ -# Titles +# Titles [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/controller/Title.html) The title of a controller or component can be set by annotating The class with `@Title`. The annotation takes an argument specifying the title of the controller or component. diff --git a/docs/controller/7-routing.md b/docs/controller/7-routing.md index 74213a6e..e90e4cb8 100644 --- a/docs/controller/7-routing.md +++ b/docs/controller/7-routing.md @@ -1,4 +1,4 @@ -# Routing +# Routing [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/Route.html) Routes are the main way to navigate between views. To set up routes to different views, you have to create a class where the routes will be defined. diff --git a/docs/controller/8-subcomponents.md b/docs/controller/8-subcomponents.md index 301fd75e..b938d0a1 100644 --- a/docs/controller/8-subcomponents.md +++ b/docs/controller/8-subcomponents.md @@ -1,4 +1,4 @@ -# Subcomponents +# Subcomponents [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/annotation/controller/SubComponent.html) Components can be used inside other controllers to reduce the complexity of a single controller by moving some features into subcomponents (also called subcomponents). diff --git a/docs/features/1-subscriber.md b/docs/features/1-subscriber.md index 7cb3fb8f..b4b64412 100644 --- a/docs/features/1-subscriber.md +++ b/docs/features/1-subscriber.md @@ -1,4 +1,4 @@ -# Subscriber +# Subscriber [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/controller/Subscriber.html) By creating a new `Subscriber` instance (or by using dependency injection to provide one) and using its utility methods, you can easily manage subscriptions without having to worry about disposing them one by one. Using `subscriber.dispose()` diff --git a/docs/features/2-for.md b/docs/features/2-for.md index 8acc4349..642ec12f 100644 --- a/docs/features/2-for.md +++ b/docs/features/2-for.md @@ -1,4 +1,4 @@ -# For-Loops +# For-Loops [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/constructs/FxFor.html) For-Loops can be used to easily display a node/subcomponent for all items in a list. Whenever an item is added to or removed from the list, the list of nodes updates accordingly. diff --git a/docs/features/4-modals.md b/docs/features/4-modals.md index 7f16dd1c..474769d8 100644 --- a/docs/features/4-modals.md +++ b/docs/features/4-modals.md @@ -1,4 +1,4 @@ -# Modals +# Modals [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/controller/Modals.html) Modals are a special type of window that can be used to display a controller on top of another controller. Modals can be used to display popup windows, dialogs, etc. diff --git a/docs/features/5-node-duplicator.md b/docs/features/5-node-duplicator.md index a63c64b6..5cf8ca3d 100644 --- a/docs/features/5-node-duplicator.md +++ b/docs/features/5-node-duplicator.md @@ -1,4 +1,4 @@ -# Node duplication +# Node duplication [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/duplicate/Duplicators.html) As JavaFX by itself doesn't support the duplication of nodes, the framework implements its own duplication logic in the form of `Duplicator`s. The framework includes duplicators for most of the diff --git a/docs/features/6-data-structures.md b/docs/features/6-data-structures.md index 2f5d20b5..c1a51ab2 100644 --- a/docs/features/6-data-structures.md +++ b/docs/features/6-data-structures.md @@ -1,20 +1,20 @@ # Other Data structures The framework provides a few data structures that can be used to simplify the creation of JavaFX applications. -### Duplicator +### Duplicator [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/duplicate/Duplicators.html) A `Duplicator` is a functional interface that takes an object and returns a duplicate of the object. It can be used to create copies of Objects such as JavaFX nodes. The framework used Duplicators for the For-Loops. For more information, see the section about [Node duplication](5-node-duplicator.md). -### Subscriber +### Subscriber [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/controller/Subscriber.html) The `Subscriber` is a utility class that can be used to manage subscriptions. It can be used to subscribe to observables without having to worry about disposing them one by one. For more information, see the section about [subscriptions](1-subscriber.md). -### RefreshableDisposable +### RefreshableDisposable [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/data/disposable/RefreshableDisposable.html) The `RefreshableDisposable` is an interface defining disposables that can be refreshed. Refreshing a disposable will make it usable again, after it has been disposed. An example for this is the `RefreshableCompositeDisposable`. -### ItemListDisposable +### ItemListDisposable [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/data/disposable/ItemListDisposable.html) The `ItemListDisposable` will run an action for all added items upon disposal. This can be used to clean up items in a list with a certain action in a single disposable. @@ -24,14 +24,14 @@ disposable.add("Hello"); disposable.dispose(); // Will print "Hello", "World" and "!" to the console (LIFO order) ``` -### TraversableQueue +### TraversableQueue [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/doc/org.fulib/fulibFx/latest/org/fulib/fx/data/TraversableQueue.html) A `TraversableQueue` is a queue that saves the latest n entries made to it. Like a normal queue, it can be used to store items in a FIFO order. When the queue is full, the oldest item will be removed. However, it also provides methods to traverse the queue, meaning you can go back and forth between items in the queue. When you go back in the queue and add a new item, all items after the current item will be removed. This can be compared to the history of a browser and is used for the history of routes. -### Either +### Either [![Javadocs](https://javadoc.io/badge2/org.fulib/fulibFx/Javadocs.svg?color=green)](https://javadoc.io/static/org.fulib/fulibFx/0.1.1/org/fulib/fx/data/Either.html) The `Either` class combines two optionals into a single object. It used to represent a value with two possible types. The framework uses it for the history, where the `Either` can be either a controller or a route. It has some methods for checking which type it is and for getting the value correct value. From f29f65b014305430e912c1e345a897a957e09ec8 Mon Sep 17 00:00:00 2001 From: Paul Mertens <50475262+LeStegii@users.noreply.github.com> Date: Sun, 24 Mar 2024 11:42:25 +0100 Subject: [PATCH 3/3] Update Tests (#67) * test(framework): Refactor tests * test(framework): Add tests for duplications * test(framework): Try to fix headless ludo tests * test(ludo): Use more keys instead of tabs * test(framework): Refactor image duplication test --------- Co-authored-by: Adrian Kunz --- build.gradle | 1 + .../java/org/fulib/fx/app/FrameworkTest.java | 70 +++++---- .../java/org/fulib/fx/app/TestRouting.java | 9 +- .../ForController.java | 4 +- .../{modal => controller}/ModalComponent.java | 2 +- .../app/{ => controller}/ParamController.java | 2 +- .../fx/app/controller/TitleController.java | 15 ++ .../{ => controller}/history/AController.java | 2 +- .../{ => controller}/history/BController.java | 2 +- .../{ => controller}/history/CController.java | 2 +- .../basic}/ButtonSubComponent.java | 2 +- .../basic}/SubComponentController.java | 3 +- .../subcomponent/order}/MainController.java | 2 +- .../order}/OtherSubSubController.java | 2 +- .../subcomponent/order}/SubController.java | 2 +- .../subcomponent/order}/SubSubController.java | 2 +- .../types}/BasicComponent.java | 2 +- .../types}/BasicController.java | 2 +- .../types/FXMLController.java} | 8 +- .../types}/MethodController.java | 2 +- .../types}/RootComponent.java | 2 +- .../types/invalid}/NonExtendingComponent.java | 2 +- .../org/fulib/fx/data/DuplicationTest.java | 137 ++++++++++++++++++ .../subcomponent/basic}/WithSubComponent.fxml | 4 +- .../types}/Basic.fxml | 2 +- .../types}/Root.fxml | 2 +- .../fx/app/{ => controller}/view/View.fxml | 2 +- .../test/resources/org/fulib/fx/data/128.jpg | Bin 0 -> 18853 bytes ludo/src/test/java/de/uniks/ludo/AppTest.java | 19 ++- 29 files changed, 240 insertions(+), 66 deletions(-) rename framework/src/test/java/org/fulib/fx/app/{controllertypes => controller}/ForController.java (91%) rename framework/src/test/java/org/fulib/fx/app/{modal => controller}/ModalComponent.java (89%) rename framework/src/test/java/org/fulib/fx/app/{ => controller}/ParamController.java (98%) create mode 100644 framework/src/test/java/org/fulib/fx/app/controller/TitleController.java rename framework/src/test/java/org/fulib/fx/app/{ => controller}/history/AController.java (92%) rename framework/src/test/java/org/fulib/fx/app/{ => controller}/history/BController.java (92%) rename framework/src/test/java/org/fulib/fx/app/{ => controller}/history/CController.java (92%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes/sub => controller/subcomponent/basic}/ButtonSubComponent.java (83%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes => controller/subcomponent/basic}/SubComponentController.java (78%) rename framework/src/test/java/org/fulib/fx/app/{subcontrollertest => controller/subcomponent/order}/MainController.java (94%) rename framework/src/test/java/org/fulib/fx/app/{subcontrollertest => controller/subcomponent/order}/OtherSubSubController.java (93%) rename framework/src/test/java/org/fulib/fx/app/{subcontrollertest => controller/subcomponent/order}/SubController.java (94%) rename framework/src/test/java/org/fulib/fx/app/{subcontrollertest => controller/subcomponent/order}/SubSubController.java (93%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes => controller/types}/BasicComponent.java (88%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes => controller/types}/BasicController.java (88%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes/ViewController.java => controller/types/FXMLController.java} (52%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes => controller/types}/MethodController.java (90%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes => controller/types}/RootComponent.java (90%) rename framework/src/test/java/org/fulib/fx/app/{controllertypes => controller/types/invalid}/NonExtendingComponent.java (78%) create mode 100644 framework/src/test/java/org/fulib/fx/data/DuplicationTest.java rename framework/src/test/resources/org/fulib/fx/app/{controllertypes => controller/subcomponent/basic}/WithSubComponent.fxml (63%) rename framework/src/test/resources/org/fulib/fx/app/{controllertypes => controller/types}/Basic.fxml (73%) rename framework/src/test/resources/org/fulib/fx/app/{controllertypes => controller/types}/Root.fxml (91%) rename framework/src/test/resources/org/fulib/fx/app/{ => controller}/view/View.fxml (73%) create mode 100644 framework/src/test/resources/org/fulib/fx/data/128.jpg diff --git a/build.gradle b/build.gradle index f56e1ce6..fecd8c1d 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ allprojects { 'java.awt.headless': 'true', 'testfx.robot': 'glass', 'testfx.headless': 'true', + 'headless.geometry': '1920x1080-32', 'glass.platform': 'Monocle', 'monocle.platform': 'Headless', 'prism.order': 'sw', diff --git a/framework/src/test/java/org/fulib/fx/app/FrameworkTest.java b/framework/src/test/java/org/fulib/fx/app/FrameworkTest.java index a144d39f..09b9b7a8 100644 --- a/framework/src/test/java/org/fulib/fx/app/FrameworkTest.java +++ b/framework/src/test/java/org/fulib/fx/app/FrameworkTest.java @@ -1,12 +1,15 @@ package org.fulib.fx.app; +import javafx.application.Platform; import org.fulib.fx.FulibFxApp; -import org.fulib.fx.app.controllertypes.BasicComponent; -import org.fulib.fx.app.history.AController; -import org.fulib.fx.app.history.BController; -import org.fulib.fx.app.history.CController; -import org.fulib.fx.app.modal.ModalComponent; -import org.fulib.fx.app.controllertypes.sub.ButtonSubComponent; +import org.fulib.fx.app.controller.types.BasicComponent; +import org.fulib.fx.app.controller.ParamController; +import org.fulib.fx.app.controller.TitleController; +import org.fulib.fx.app.controller.history.AController; +import org.fulib.fx.app.controller.history.BController; +import org.fulib.fx.app.controller.history.CController; +import org.fulib.fx.app.controller.ModalComponent; +import org.fulib.fx.app.controller.subcomponent.basic.ButtonSubComponent; import org.fulib.fx.controller.Modals; import org.fulib.fx.controller.exception.ControllerInvalidRouteException; import org.fulib.fx.controller.exception.IllegalControllerException; @@ -28,6 +31,11 @@ public class FrameworkTest extends ApplicationTest { + public static void runAndWait(Runnable runnable) { + Platform.runLater(runnable); + waitForFxEvents(); + } + public final FulibFxApp app = new FulibFxApp() { final TestComponent component = DaggerTestComponent.builder().mainApp(this).build(); @@ -46,32 +54,38 @@ public void start(Stage stage) throws Exception { stage.requestFocus(); } + @Test + public void title() { + runAndWait(() -> app.show(new TitleController())); + assertEquals("Title", app.stage().getTitle()); + } + /** * Tests if the framework is able to load the routes and different kinds of controllers. */ @Test public void controllerTypes() { - app.show("/controller/basic"); + runAndWait(() -> app.show("/controller/basic")); verifyThat("Basic Controller", Node::isVisible); sleep(200); - app.show("/controller/method"); + runAndWait(() -> app.show("/controller/method")); verifyThat("Method Controller", Node::isVisible); sleep(200); - app.show("/controller/view"); + runAndWait(() -> app.show("/controller/view")); verifyThat("View Controller", Node::isVisible); sleep(200); - app.show("/component/basic"); + runAndWait(() -> app.show("/component/basic")); verifyThat("Basic Component", Node::isVisible); sleep(200); - app.show("/component/root"); + runAndWait(() -> app.show("/component/root")); verifyThat("Root Component", Node::isVisible); sleep(200); - app.show("../root"); + runAndWait(() -> app.show("../root")); verifyThat("Root Component", Node::isVisible); sleep(200); @@ -86,7 +100,7 @@ public void controllerTypes() { */ @Test public void subComponent() { - app.show("/controller/withsubcomponent"); + runAndWait(() -> app.show("/controller/withsubcomponent")); sleep(200); ButtonSubComponent button = lookup("#buttonSubComponent").query(); verifyThat(button, Node::isVisible); @@ -97,7 +111,7 @@ public void subComponent() { public void routeSubComponent() { assertThrows(IllegalArgumentException.class, () -> app.initAndRender("/controller/view")); - assertEquals(BasicComponent.class, app.initAndRender("/component/basic").getClass()); + runAndWait(() -> assertEquals(BasicComponent.class, app.initAndRender("/component/basic").getClass())); } /** @@ -112,7 +126,7 @@ public void simpleForTest() { list.add("!"); }); - app.show("/controller/for", Map.of("list", list)); + runAndWait(() -> app.show("/controller/for", Map.of("list", list))); verifyThat("#container", Node::isVisible); VBox container = lookup("#container").queryAs(VBox.class); @@ -135,20 +149,20 @@ public void testSubOrder() { List renderList = new ArrayList<>(); List destroyList = new ArrayList<>(); - app.show("/ordertest/main", Map.of("initList", initList, "renderList", renderList, "destroyList", destroyList)); + runAndWait(() -> app.show("/ordertest/main", Map.of("initList", initList, "renderList", renderList, "destroyList", destroyList))); assertEquals(List.of("main", "sub", "subsub", "othersubsub"), initList); assertEquals(List.of("subsub", "othersubsub", "sub", "main"), renderList); assertEquals(List.of(), destroyList); - app.show("/controller/basic"); + runAndWait(() -> app.show("/controller/basic")); assertEquals(List.of("othersubsub", "subsub", "sub", "main"), destroyList); } @Test public void modalTest() { - app.show("/controller/basic"); + runAndWait(() -> app.show("/controller/basic")); verifyThat("Basic Controller", Node::isVisible); sleep(200); @@ -178,7 +192,7 @@ public void params() { "character", 'a', "bool", true ); - app.show(controller, params); + runAndWait(() -> app.show(controller, params)); assertEquals(1, controller.getOnInitParam()); assertEquals("string", controller.getSetterParam()); @@ -196,31 +210,31 @@ public void params() { @Test public void history() { - app.show(new AController(), Map.of("string", "a")); + runAndWait(() -> app.show(new AController(), Map.of("string", "a"))); verifyThat("A:a", Node::isVisible); - app.show(new BController(), Map.of("string", "b")); + runAndWait(() -> app.show(new BController(), Map.of("string", "b"))); verifyThat("B:b", Node::isVisible); - app.show(new CController(), Map.of("string", "c")); + runAndWait(() -> app.show(new CController(), Map.of("string", "c"))); verifyThat("C:c", Node::isVisible); - app.back(); + runAndWait(app::back); verifyThat("B:b", Node::isVisible); - app.back(); + runAndWait(app::back); verifyThat("A:a", Node::isVisible); - app.forward(); + runAndWait(app::forward); verifyThat("B:b", Node::isVisible); - app.forward(); + runAndWait(app::forward); verifyThat("C:c", Node::isVisible); - app.forward(); + runAndWait(app::forward); verifyThat("C:c", Node::isVisible); // should not change - app.back(); + runAndWait(app::back); verifyThat("B:b", Node::isVisible); FulibFxApp.FX_SCHEDULER.scheduleDirect(app::refresh); diff --git a/framework/src/test/java/org/fulib/fx/app/TestRouting.java b/framework/src/test/java/org/fulib/fx/app/TestRouting.java index 4c286e19..47063426 100644 --- a/framework/src/test/java/org/fulib/fx/app/TestRouting.java +++ b/framework/src/test/java/org/fulib/fx/app/TestRouting.java @@ -1,8 +1,11 @@ package org.fulib.fx.app; import org.fulib.fx.annotation.Route; -import org.fulib.fx.app.controllertypes.*; -import org.fulib.fx.app.subcontrollertest.MainController; +import org.fulib.fx.app.controller.*; +import org.fulib.fx.app.controller.subcomponent.basic.SubComponentController; +import org.fulib.fx.app.controller.types.*; +import org.fulib.fx.app.controller.types.invalid.NonExtendingComponent; +import org.fulib.fx.app.controller.subcomponent.order.MainController; import javax.inject.Inject; import javax.inject.Provider; @@ -23,7 +26,7 @@ public class TestRouting { @Inject @Route("controller/view") - Provider viewControllerProvider; + Provider viewControllerProvider; @Inject @Route("controller/method") diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/ForController.java b/framework/src/test/java/org/fulib/fx/app/controller/ForController.java similarity index 91% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/ForController.java rename to framework/src/test/java/org/fulib/fx/app/controller/ForController.java index 76da4c6e..ffbb7439 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/ForController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/ForController.java @@ -1,11 +1,11 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller; import org.fulib.fx.annotation.controller.Controller; import org.fulib.fx.annotation.controller.SubComponent; import org.fulib.fx.annotation.event.onDestroy; import org.fulib.fx.annotation.event.onRender; import org.fulib.fx.annotation.param.Param; -import org.fulib.fx.app.controllertypes.sub.ButtonSubComponent; +import org.fulib.fx.app.controller.subcomponent.basic.ButtonSubComponent; import javafx.collections.ObservableList; import javafx.scene.control.Labeled; import javafx.scene.layout.VBox; diff --git a/framework/src/test/java/org/fulib/fx/app/modal/ModalComponent.java b/framework/src/test/java/org/fulib/fx/app/controller/ModalComponent.java similarity index 89% rename from framework/src/test/java/org/fulib/fx/app/modal/ModalComponent.java rename to framework/src/test/java/org/fulib/fx/app/controller/ModalComponent.java index a3b7e1d7..7cd79997 100644 --- a/framework/src/test/java/org/fulib/fx/app/modal/ModalComponent.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/ModalComponent.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.modal; +package org.fulib.fx.app.controller; import org.fulib.fx.annotation.controller.Component; import javafx.scene.control.Label; diff --git a/framework/src/test/java/org/fulib/fx/app/ParamController.java b/framework/src/test/java/org/fulib/fx/app/controller/ParamController.java similarity index 98% rename from framework/src/test/java/org/fulib/fx/app/ParamController.java rename to framework/src/test/java/org/fulib/fx/app/controller/ParamController.java index 4915bb55..6b6143c1 100644 --- a/framework/src/test/java/org/fulib/fx/app/ParamController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/ParamController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app; +package org.fulib.fx.app.controller; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; diff --git a/framework/src/test/java/org/fulib/fx/app/controller/TitleController.java b/framework/src/test/java/org/fulib/fx/app/controller/TitleController.java new file mode 100644 index 00000000..738779cc --- /dev/null +++ b/framework/src/test/java/org/fulib/fx/app/controller/TitleController.java @@ -0,0 +1,15 @@ +package org.fulib.fx.app.controller; + +import javafx.scene.layout.VBox; +import org.fulib.fx.annotation.controller.Controller; +import org.fulib.fx.annotation.controller.Title; + +@Title("Title") +@Controller(view = "#view") +public class TitleController { + + public VBox view() { + return new VBox(); + } + +} diff --git a/framework/src/test/java/org/fulib/fx/app/history/AController.java b/framework/src/test/java/org/fulib/fx/app/controller/history/AController.java similarity index 92% rename from framework/src/test/java/org/fulib/fx/app/history/AController.java rename to framework/src/test/java/org/fulib/fx/app/controller/history/AController.java index e3b3ed1e..905ad710 100644 --- a/framework/src/test/java/org/fulib/fx/app/history/AController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/history/AController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.history; +package org.fulib.fx.app.controller.history; import javafx.scene.control.Label; import javafx.scene.layout.VBox; diff --git a/framework/src/test/java/org/fulib/fx/app/history/BController.java b/framework/src/test/java/org/fulib/fx/app/controller/history/BController.java similarity index 92% rename from framework/src/test/java/org/fulib/fx/app/history/BController.java rename to framework/src/test/java/org/fulib/fx/app/controller/history/BController.java index 93184bd9..5af4ce66 100644 --- a/framework/src/test/java/org/fulib/fx/app/history/BController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/history/BController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.history; +package org.fulib.fx.app.controller.history; import javafx.scene.control.Label; import javafx.scene.layout.VBox; diff --git a/framework/src/test/java/org/fulib/fx/app/history/CController.java b/framework/src/test/java/org/fulib/fx/app/controller/history/CController.java similarity index 92% rename from framework/src/test/java/org/fulib/fx/app/history/CController.java rename to framework/src/test/java/org/fulib/fx/app/controller/history/CController.java index df320215..b820f61b 100644 --- a/framework/src/test/java/org/fulib/fx/app/history/CController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/history/CController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.history; +package org.fulib.fx.app.controller.history; import javafx.scene.control.Label; import javafx.scene.layout.VBox; diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/sub/ButtonSubComponent.java b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/basic/ButtonSubComponent.java similarity index 83% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/sub/ButtonSubComponent.java rename to framework/src/test/java/org/fulib/fx/app/controller/subcomponent/basic/ButtonSubComponent.java index e7cc7cda..1ebc3911 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/sub/ButtonSubComponent.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/basic/ButtonSubComponent.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.controllertypes.sub; +package org.fulib.fx.app.controller.subcomponent.basic; import org.fulib.fx.annotation.controller.Component; import javafx.scene.control.Button; diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/SubComponentController.java b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/basic/SubComponentController.java similarity index 78% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/SubComponentController.java rename to framework/src/test/java/org/fulib/fx/app/controller/subcomponent/basic/SubComponentController.java index 029a1372..45193ec6 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/SubComponentController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/basic/SubComponentController.java @@ -1,8 +1,7 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller.subcomponent.basic; import org.fulib.fx.annotation.controller.Controller; import org.fulib.fx.annotation.controller.SubComponent; -import org.fulib.fx.app.controllertypes.sub.ButtonSubComponent; import javafx.fxml.FXML; import javax.inject.Inject; diff --git a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/MainController.java b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/MainController.java similarity index 94% rename from framework/src/test/java/org/fulib/fx/app/subcontrollertest/MainController.java rename to framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/MainController.java index 67562227..8897dbb3 100644 --- a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/MainController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/MainController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.subcontrollertest; +package org.fulib.fx.app.controller.subcomponent.order; import org.fulib.fx.annotation.controller.Controller; import org.fulib.fx.annotation.controller.SubComponent; diff --git a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/OtherSubSubController.java b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/OtherSubSubController.java similarity index 93% rename from framework/src/test/java/org/fulib/fx/app/subcontrollertest/OtherSubSubController.java rename to framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/OtherSubSubController.java index 3ab70c41..bc2f6827 100644 --- a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/OtherSubSubController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/OtherSubSubController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.subcontrollertest; +package org.fulib.fx.app.controller.subcomponent.order; import org.fulib.fx.annotation.controller.Component; import org.fulib.fx.annotation.event.onDestroy; diff --git a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/SubController.java b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/SubController.java similarity index 94% rename from framework/src/test/java/org/fulib/fx/app/subcontrollertest/SubController.java rename to framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/SubController.java index 951e0de1..2f57b952 100644 --- a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/SubController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/SubController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.subcontrollertest; +package org.fulib.fx.app.controller.subcomponent.order; import org.fulib.fx.annotation.controller.Component; import org.fulib.fx.annotation.controller.SubComponent; diff --git a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/SubSubController.java b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/SubSubController.java similarity index 93% rename from framework/src/test/java/org/fulib/fx/app/subcontrollertest/SubSubController.java rename to framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/SubSubController.java index 9f747c14..260a1d94 100644 --- a/framework/src/test/java/org/fulib/fx/app/subcontrollertest/SubSubController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/subcomponent/order/SubSubController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.subcontrollertest; +package org.fulib.fx.app.controller.subcomponent.order; import org.fulib.fx.annotation.controller.Component; import org.fulib.fx.annotation.event.onDestroy; diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/BasicComponent.java b/framework/src/test/java/org/fulib/fx/app/controller/types/BasicComponent.java similarity index 88% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/BasicComponent.java rename to framework/src/test/java/org/fulib/fx/app/controller/types/BasicComponent.java index a1583196..fee9a13e 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/BasicComponent.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/types/BasicComponent.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller.types; import org.fulib.fx.annotation.controller.Component; import javafx.scene.control.Label; diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/BasicController.java b/framework/src/test/java/org/fulib/fx/app/controller/types/BasicController.java similarity index 88% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/BasicController.java rename to framework/src/test/java/org/fulib/fx/app/controller/types/BasicController.java index 98df643b..a6dcd269 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/BasicController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/types/BasicController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller.types; import org.fulib.fx.annotation.controller.Controller; diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/ViewController.java b/framework/src/test/java/org/fulib/fx/app/controller/types/FXMLController.java similarity index 52% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/ViewController.java rename to framework/src/test/java/org/fulib/fx/app/controller/types/FXMLController.java index 346e9eb2..ba4232c8 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/ViewController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/types/FXMLController.java @@ -1,14 +1,14 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller.types; import org.fulib.fx.annotation.controller.Controller; import javax.inject.Inject; -@Controller(view = "../view/View.fxml") -public class ViewController { +@Controller(view = "../view/View.fxml") // Path traversal +public class FXMLController { @Inject - public ViewController() { + public FXMLController() { // The FXML file contains a label with the text "View Controller" } } diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/MethodController.java b/framework/src/test/java/org/fulib/fx/app/controller/types/MethodController.java similarity index 90% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/MethodController.java rename to framework/src/test/java/org/fulib/fx/app/controller/types/MethodController.java index c27acde3..dffbecbf 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/MethodController.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/types/MethodController.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller.types; import org.fulib.fx.annotation.controller.Controller; import javafx.scene.control.Label; diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/RootComponent.java b/framework/src/test/java/org/fulib/fx/app/controller/types/RootComponent.java similarity index 90% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/RootComponent.java rename to framework/src/test/java/org/fulib/fx/app/controller/types/RootComponent.java index b339b554..3fee1c00 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/RootComponent.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/types/RootComponent.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller.types; import org.fulib.fx.annotation.controller.Component; import javafx.fxml.FXML; diff --git a/framework/src/test/java/org/fulib/fx/app/controllertypes/NonExtendingComponent.java b/framework/src/test/java/org/fulib/fx/app/controller/types/invalid/NonExtendingComponent.java similarity index 78% rename from framework/src/test/java/org/fulib/fx/app/controllertypes/NonExtendingComponent.java rename to framework/src/test/java/org/fulib/fx/app/controller/types/invalid/NonExtendingComponent.java index de6110a6..62990767 100644 --- a/framework/src/test/java/org/fulib/fx/app/controllertypes/NonExtendingComponent.java +++ b/framework/src/test/java/org/fulib/fx/app/controller/types/invalid/NonExtendingComponent.java @@ -1,4 +1,4 @@ -package org.fulib.fx.app.controllertypes; +package org.fulib.fx.app.controller.types.invalid; import org.fulib.fx.annotation.controller.Component; diff --git a/framework/src/test/java/org/fulib/fx/data/DuplicationTest.java b/framework/src/test/java/org/fulib/fx/data/DuplicationTest.java new file mode 100644 index 00000000..aba9711c --- /dev/null +++ b/framework/src/test/java/org/fulib/fx/data/DuplicationTest.java @@ -0,0 +1,137 @@ +package org.fulib.fx.data; + +import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.*; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; +import javafx.stage.Stage; +import org.fulib.fx.duplicate.Duplicators; +import org.junit.jupiter.api.Test; +import org.testfx.framework.junit5.ApplicationTest; + +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.util.List; +import java.util.Objects; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.testfx.util.WaitForAsyncUtils.waitForFxEvents; + +public class DuplicationTest extends ApplicationTest { + + + VBox pane = new VBox(); + + @Override + public void start(Stage stage) { + pane.setAlignment(Pos.CENTER); + stage.setScene(new Scene(pane)); + stage.show(); + } + + @Test + public void button() { + Button button = new Button(); + + // Button(Base) + button.setDefaultButton(true); + button.setCancelButton(true); + button.setOnAction(e -> System.out.println("Button clicked")); + + // Labeled + button.setText("Button"); + button.setAlignment(Pos.BOTTOM_RIGHT); + button.setTextAlignment(TextAlignment.RIGHT); + button.setTextOverrun(OverrunStyle.LEADING_ELLIPSIS); + button.setEllipsisString("Button"); + button.setWrapText(true); + button.setFont(Font.font(20)); + button.setGraphic(new Pane()); + button.setUnderline(true); + button.setLineSpacing(10); + button.setContentDisplay(ContentDisplay.TOP); + button.setGraphicTextGap(10); + button.setTextFill(Color.color(0.5, 0.5, 0.5)); + button.setMnemonicParsing(true); + + // Control + button.setContextMenu(new ContextMenu()); + button.setTooltip(new Tooltip("Button")); + + Button button1 = Duplicators.duplicate(button); + + assertEquals(button.isDefaultButton(), button1.isDefaultButton()); + assertEquals(button.isCancelButton(), button1.isCancelButton()); + assertEquals(button.getOnAction(), button1.getOnAction()); + assertEquals(button.getText(), button1.getText()); + assertEquals(button.getAlignment(), button1.getAlignment()); + assertEquals(button.getTextAlignment(), button1.getTextAlignment()); + assertEquals(button.getTextOverrun(), button1.getTextOverrun()); + assertEquals(button.getEllipsisString(), button1.getEllipsisString()); + assertEquals(button.isWrapText(), button1.isWrapText()); + assertEquals(button.getFont(), button1.getFont()); + assertEquals(button.getGraphic(), button1.getGraphic()); + assertEquals(button.isUnderline(), button1.isUnderline()); + assertEquals(button.getLineSpacing(), button1.getLineSpacing()); + assertEquals(button.getContentDisplay(), button1.getContentDisplay()); + assertEquals(button.getGraphicTextGap(), button1.getGraphicTextGap()); + assertEquals(button.getTextFill(), button1.getTextFill()); + assertEquals(button.isMnemonicParsing(), button1.isMnemonicParsing()); + assertEquals(button.getContextMenu(), button1.getContextMenu()); + assertEquals(button.getTooltip(), button1.getTooltip()); + } + + @Test + public void parents() { + VBox vBox = new VBox( + new Label("1"), + new Text("2") + ); + + VBox duplicate = Duplicators.duplicate(vBox); + + Platform.runLater(() -> { + pane.getChildren().add(vBox); + pane.getChildren().add(duplicate); + }); + waitForFxEvents(); + sleep(200); + + assertEquals(List.of("1", "2"), duplicate.getChildren().stream().map(node -> { + if (node instanceof Label) { + return ((Label) node).getText(); + } else if (node instanceof Text) { + return ((Text) node).getText(); + } + return null; // should not happen + }).toList()); + + } + + @Test + public void imageView() throws URISyntaxException, MalformedURLException { + HBox hBox = new HBox( + new ImageView( + new Image(this.getClass().getResource("128.jpg").toString()) + ) + ); + + HBox duplicate = Duplicators.duplicate(hBox); + + ImageView original = (ImageView) hBox.getChildren().get(0); + ImageView copied = (ImageView) duplicate.getChildren().get(0); + + assertEquals(original.getImage(), copied.getImage()); + } + + +} diff --git a/framework/src/test/resources/org/fulib/fx/app/controllertypes/WithSubComponent.fxml b/framework/src/test/resources/org/fulib/fx/app/controller/subcomponent/basic/WithSubComponent.fxml similarity index 63% rename from framework/src/test/resources/org/fulib/fx/app/controllertypes/WithSubComponent.fxml rename to framework/src/test/resources/org/fulib/fx/app/controller/subcomponent/basic/WithSubComponent.fxml index 04e915a6..fd265d80 100644 --- a/framework/src/test/resources/org/fulib/fx/app/controllertypes/WithSubComponent.fxml +++ b/framework/src/test/resources/org/fulib/fx/app/controller/subcomponent/basic/WithSubComponent.fxml @@ -3,8 +3,8 @@ - - + + diff --git a/framework/src/test/resources/org/fulib/fx/app/controllertypes/Basic.fxml b/framework/src/test/resources/org/fulib/fx/app/controller/types/Basic.fxml similarity index 73% rename from framework/src/test/resources/org/fulib/fx/app/controllertypes/Basic.fxml rename to framework/src/test/resources/org/fulib/fx/app/controller/types/Basic.fxml index 77a049f4..270895f3 100644 --- a/framework/src/test/resources/org/fulib/fx/app/controllertypes/Basic.fxml +++ b/framework/src/test/resources/org/fulib/fx/app/controller/types/Basic.fxml @@ -3,6 +3,6 @@ - + diff --git a/framework/src/test/resources/org/fulib/fx/app/controllertypes/Root.fxml b/framework/src/test/resources/org/fulib/fx/app/controller/types/Root.fxml similarity index 91% rename from framework/src/test/resources/org/fulib/fx/app/controllertypes/Root.fxml rename to framework/src/test/resources/org/fulib/fx/app/controller/types/Root.fxml index ab1e58fa..9c8f008e 100644 --- a/framework/src/test/resources/org/fulib/fx/app/controllertypes/Root.fxml +++ b/framework/src/test/resources/org/fulib/fx/app/controller/types/Root.fxml @@ -3,6 +3,6 @@ - + diff --git a/framework/src/test/resources/org/fulib/fx/app/view/View.fxml b/framework/src/test/resources/org/fulib/fx/app/controller/view/View.fxml similarity index 73% rename from framework/src/test/resources/org/fulib/fx/app/view/View.fxml rename to framework/src/test/resources/org/fulib/fx/app/controller/view/View.fxml index f1a63d8a..1b3a1435 100644 --- a/framework/src/test/resources/org/fulib/fx/app/view/View.fxml +++ b/framework/src/test/resources/org/fulib/fx/app/controller/view/View.fxml @@ -3,6 +3,6 @@ - + diff --git a/framework/src/test/resources/org/fulib/fx/data/128.jpg b/framework/src/test/resources/org/fulib/fx/data/128.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d2b9cf190ba719e786d27fb7143096093d651a62 GIT binary patch literal 18853 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 app.stage().requestFocus()); + waitForFxEvents(); + + press(KeyCode.LEFT); + release(KeyCode.LEFT); + press(KeyCode.TAB); + release(KeyCode.TAB); + press(KeyCode.SPACE); + release(KeyCode.SPACE); waitForFxEvents(); @@ -247,7 +252,7 @@ public void test() { } private void roll() { - clickOn("#eyesLabel");; + clickOn("#eyesLabel"); sleep(1100); }