diff --git a/.github/workflows-are-custom b/.github/workflows-are-custom new file mode 100644 index 0000000..e69de29 diff --git a/.github/workflows/main-openjdk_current-linux.yml b/.github/workflows/main.linux.temurin.current.yml similarity index 88% rename from .github/workflows/main-openjdk_current-linux.yml rename to .github/workflows/main.linux.temurin.current.yml index 9091334..d1328d9 100644 --- a/.github/workflows/main-openjdk_current-linux.yml +++ b/.github/workflows/main.linux.temurin.current.yml @@ -1,4 +1,4 @@ -name: main-openjdk_current-linux +name: main.linux.temurin.current on: push: @@ -14,7 +14,7 @@ jobs: - name: JDK uses: actions/setup-java@v1 with: - java-version: 16 + java-version: 20 - name: Build run: ./.github/workflows/run-with-xvfb.sh mvn --errors clean verify site - name: Upload video @@ -22,7 +22,7 @@ jobs: if: ${{ always() }} with: name: test-video - path: test-suite.mkv + path: test-suite.webm - name: Upload test logs uses: actions/upload-artifact@v2 if: ${{ always() }} diff --git a/.github/workflows/main-openjdk_lts-linux.yml b/.github/workflows/main.linux.temurin.lts.yml similarity index 90% rename from .github/workflows/main-openjdk_lts-linux.yml rename to .github/workflows/main.linux.temurin.lts.yml index cafdd4e..1382054 100644 --- a/.github/workflows/main-openjdk_lts-linux.yml +++ b/.github/workflows/main.linux.temurin.lts.yml @@ -1,4 +1,4 @@ -name: main-openjdk_lts-linux +name: main.linux.temurin.lts on: push: @@ -14,7 +14,7 @@ jobs: - name: JDK uses: actions/setup-java@v1 with: - java-version: 11 + java-version: 17 - name: Build run: ./.github/workflows/run-with-xvfb.sh mvn --errors clean verify site - name: Upload video @@ -22,7 +22,7 @@ jobs: if: ${{ always() }} with: name: test-video - path: test-suite.mkv + path: test-suite.webm - name: Upload test logs uses: actions/upload-artifact@v2 if: ${{ always() }} diff --git a/.github/workflows/main-openjdk_current-windows.yml b/.github/workflows/main.windows.temurin.current.yml similarity index 84% rename from .github/workflows/main-openjdk_current-windows.yml rename to .github/workflows/main.windows.temurin.current.yml index e63a2bc..fd11abb 100644 --- a/.github/workflows/main-openjdk_current-windows.yml +++ b/.github/workflows/main.windows.temurin.current.yml @@ -1,4 +1,4 @@ -name: main-openjdk_current-windows +name: main.windows.temurin.current on: push: @@ -14,6 +14,6 @@ jobs: - name: JDK uses: actions/setup-java@v1 with: - java-version: 16 + java-version: 20 - name: Build run: mvn -DskipTests=true --errors clean verify site diff --git a/.github/workflows/main.windows.temurin.lts.yml b/.github/workflows/main.windows.temurin.lts.yml new file mode 100644 index 0000000..bd7776b --- /dev/null +++ b/.github/workflows/main.windows.temurin.lts.yml @@ -0,0 +1,19 @@ +name: main.windows.temurin.lts + +on: + push: + branches: [ develop, feature/*, release/* ] + pull_request: + branches: [ develop ] + +jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: JDK + uses: actions/setup-java@v1 + with: + java-version: 17 + - name: Build + run: mvn -DskipTests=true --errors clean verify site diff --git a/.github/workflows/run-with-xvfb.sh b/.github/workflows/run-with-xvfb.sh index bce5226..7e0344e 100755 --- a/.github/workflows/run-with-xvfb.sh +++ b/.github/workflows/run-with-xvfb.sh @@ -10,10 +10,11 @@ exec > >(tee build.txt) 2>&1 # fluxbox to provide a bare-minimum window manager with click-to-focus # ffmpeg to record the session # feh to set a background -# xterm to display the build log in the video # -sudo apt-get -y install xvfb fluxbox feh ffmpeg xterm +sudo apt-get -y update +sudo apt-get -y upgrade +sudo apt-get -y install xvfb fluxbox feh ffmpeg #--------------------------------------------------------------------- # Start Xvfb on a new display. @@ -30,13 +31,6 @@ sleep 1 fluxbox & sleep 1 -#--------------------------------------------------------------------- -# Start an xterm that displays the build log. -# - -xterm -geometry 200x40 -e tail -F build.txt & -sleep 1 - #--------------------------------------------------------------------- # Set a desktop image. # @@ -48,7 +42,7 @@ sleep 1 # Start recording the session. # -ffmpeg -f x11grab -y -r 15 -video_size 1280x1024 -i :99 -vcodec libx264 test-suite.mkv & +ffmpeg -f x11grab -y -r 60 -video_size 1280x1024 -i :99 test-suite.webm & FFMPEG_PID="$!" #--------------------------------------------------------------------- @@ -63,5 +57,5 @@ FFMPEG_PID="$!" # stops. # -sleep 5 +sleep 20 kill -INT "${FFMPEG_PID}" diff --git a/README-CHANGES.xml b/README-CHANGES.xml index 93cc58d..54f9853 100644 --- a/README-CHANGES.xml +++ b/README-CHANGES.xml @@ -39,7 +39,7 @@ - + @@ -111,13 +111,40 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README-LICENSE.txt b/README-LICENSE.txt index d9b093f..271af0c 100644 --- a/README-LICENSE.txt +++ b/README-LICENSE.txt @@ -1,4 +1,4 @@ -Copyright © 2020 Mark Raynsford http://io7m.com +Copyright © 2020 Mark Raynsford https://www.io7m.com Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/README.in b/README.in index 79981df..a99d0d1 100644 --- a/README.in +++ b/README.in @@ -1,4 +1,8 @@ -An alternative to JavaFX's FileChooser that aims to be feature-compatible, + + +# jwheatsheaf + +An alternative to JavaFX's FileChooser that aims to be feature-compatible, if not fully API-compatible. ### Features @@ -8,7 +12,7 @@ if not fully API-compatible. * Directory creation. * Configurable, extensible file/directory filtering. * Simple case-insensitive directory searching. - * Written in pure Java 11. + * Written in pure Java 17. * [OSGi](https://www.osgi.org/) ready * [JPMS](https://en.wikipedia.org/wiki/Java_Platform_Module_System) ready * ISC license @@ -26,6 +30,20 @@ slightly differently on each platform. The purpose of the `jwheatsheaf` package configurable, styleable, consistent, non-native file chooser implementation analogous to the `JFileChooser` class. +### Building + +``` +$ mvn clean verify +``` + +Note: The above will run the test suite, and this _will_ take over your +keyboard and mouse for the duration of the test suite run. If you don't +want to run the tests, use the `skipTests` propery: + +``` +$ mvn -DskipTests=true clean verify +``` + ### Usage The simplest possible code that can open a file chooser and select at most one file: @@ -38,7 +56,7 @@ final var configuration = .build(); final var choosers = JWFileChoosers.create(); -final var chooser = choosers.create(mainWindow, configuration); +final var chooser = choosers.create(configuration); final List selected = chooser.showAndWait(); ``` diff --git a/README.md b/README.md index afc9c50..624aae9 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,22 @@ jwheatsheaf === [![Maven Central](https://img.shields.io/maven-central/v/com.io7m.jwheatsheaf/com.io7m.jwheatsheaf.svg?style=flat-square)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.io7m.jwheatsheaf%22) -[![Maven Central (snapshot)](https://img.shields.io/nexus/s/https/oss.sonatype.org/com.io7m.jwheatsheaf/com.io7m.jwheatsheaf.svg?style=flat-square)](https://oss.sonatype.org/content/repositories/snapshots/com/io7m/jwheatsheaf/) +[![Maven Central (snapshot)](https://img.shields.io/nexus/s/https/s01.oss.sonatype.org/com.io7m.jwheatsheaf/com.io7m.jwheatsheaf.svg?style=flat-square)](https://s01.oss.sonatype.org/content/repositories/snapshots/com/io7m/jwheatsheaf/) [![Codecov](https://img.shields.io/codecov/c/github/io7m/jwheatsheaf.svg?style=flat-square)](https://codecov.io/gh/io7m/jwheatsheaf) ![jwheatsheaf](./src/site/resources/jwheatsheaf.jpg?raw=true) -| JVM | Platform | Status | -|-----------------|----------|--------| -| OpenJDK LTS | Linux | [![Build (OpenJDK LTS, Linux)](https://img.shields.io/github/workflow/status/io7m/jwheatsheaf/main-openjdk_lts-linux)](https://github.com/io7m/jwheatsheaf/actions?query=workflow%3Amain-openjdk_lts-linux) | -| OpenJDK Current | Linux | [![Build (OpenJDK Current, Linux)](https://img.shields.io/github/workflow/status/io7m/jwheatsheaf/main-openjdk_current-linux)](https://github.com/io7m/jwheatsheaf/actions?query=workflow%3Amain-openjdk_current-linux) -| OpenJDK Current | Windows | [![Build (OpenJDK Current, Windows)](https://img.shields.io/github/workflow/status/io7m/jwheatsheaf/main-openjdk_current-windows)](https://github.com/io7m/jwheatsheaf/actions?query=workflow%3Amain-openjdk_current-windows) +| JVM | Platform | Status | +|-----|----------|--------| +| OpenJDK (Temurin) Current | Linux | [![Build (OpenJDK (Temurin) Current, Linux)](https://img.shields.io/github/actions/workflow/status/io7m/jwheatsheaf/main.linux.temurin.current.yml)](https://github.com/io7m/jwheatsheaf/actions?query=workflow%3Amain.linux.temurin.current)| +| OpenJDK (Temurin) LTS | Linux | [![Build (OpenJDK (Temurin) LTS, Linux)](https://img.shields.io/github/actions/workflow/status/io7m/jwheatsheaf/main.linux.temurin.lts.yml)](https://github.com/io7m/jwheatsheaf/actions?query=workflow%3Amain.linux.temurin.lts)| +| OpenJDK (Temurin) Current | Windows | [![Build (OpenJDK (Temurin) Current, Windows)](https://img.shields.io/github/actions/workflow/status/io7m/jwheatsheaf/main.windows.temurin.current.yml)](https://github.com/io7m/jwheatsheaf/actions?query=workflow%3Amain.windows.temurin.current)| +| OpenJDK (Temurin) LTS | Windows | [![Build (OpenJDK (Temurin) LTS, Windows)](https://img.shields.io/github/actions/workflow/status/io7m/jwheatsheaf/main.windows.temurin.lts.yml)](https://github.com/io7m/jwheatsheaf/actions?query=workflow%3Amain.windows.temurin.lts)| -An alternative to JavaFX's FileChooser that aims to be feature-compatible, + +# jwheatsheaf + +An alternative to JavaFX's FileChooser that aims to be feature-compatible, if not fully API-compatible. ### Features @@ -23,7 +27,7 @@ if not fully API-compatible. * Directory creation. * Configurable, extensible file/directory filtering. * Simple case-insensitive directory searching. - * Written in pure Java 11. + * Written in pure Java 17. * [OSGi](https://www.osgi.org/) ready * [JPMS](https://en.wikipedia.org/wiki/Java_Platform_Module_System) ready * ISC license @@ -41,6 +45,20 @@ slightly differently on each platform. The purpose of the `jwheatsheaf` package configurable, styleable, consistent, non-native file chooser implementation analogous to the `JFileChooser` class. +### Building + +``` +$ mvn clean verify +``` + +Note: The above will run the test suite, and this _will_ take over your +keyboard and mouse for the duration of the test suite run. If you don't +want to run the tests, use the `skipTests` propery: + +``` +$ mvn -DskipTests=true clean verify +``` + ### Usage The simplest possible code that can open a file chooser and select at most one file: @@ -53,7 +71,7 @@ final var configuration = .build(); final var choosers = JWFileChoosers.create(); -final var chooser = choosers.create(mainWindow, configuration); +final var chooser = choosers.create(configuration); final List selected = chooser.showAndWait(); ``` diff --git a/com.io7m.jwheatsheaf.api/pom.xml b/com.io7m.jwheatsheaf.api/pom.xml index d9898c4..17accf2 100644 --- a/com.io7m.jwheatsheaf.api/pom.xml +++ b/com.io7m.jwheatsheaf.api/pom.xml @@ -9,14 +9,14 @@ com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 com.io7m.jwheatsheaf.api com.io7m.jwheatsheaf.api JavaFX File Chooser (API) - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf @@ -67,6 +67,35 @@ + + + com.io7m.stmp + string-template-maven-plugin + + + generate-version + generate-sources + + render + + + + + + + + + diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserAction.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserAction.java index 6384dac..61aee64 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserAction.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserAction.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationDefaults.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationDefaults.java index 0dc9c76..0dad606 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationDefaults.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationDefaults.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationType.java index d9aea92..db434b4 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserConfigurationType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,6 +18,7 @@ import com.io7m.immutables.styles.ImmutablesStyleType; import com.io7m.jaffirm.core.Preconditions; +import javafx.stage.Modality; import org.immutables.value.Value; import java.net.URL; @@ -139,7 +140,7 @@ default boolean allowDirectoryCreation() } /** - * Determine whether or not to show a link to the parent directory inside + * Determine whether to show a link to the parent directory inside * the file listing. This entry is always called "..". * * @return {@code true} if the directory listing will contain ".." @@ -244,4 +245,16 @@ default JWFileChooserStringOverridesType stringOverrides() { return JWFileChooserStringOverridesEmpty.get(); } + + /** + * @return The modality that will be used for file choosers + * + * @since 4.0.0 + */ + + @Value.Default + default Modality modality() + { + return Modality.APPLICATION_MODAL; + } } diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserEventType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserEventType.java index 9c8aa75..24ac1b5 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserEventType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserEventType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserFilterType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserFilterType.java index 6f2a833..c92b6a9 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserFilterType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserFilterType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesAbstract.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesAbstract.java index 158d4bd..f7c3ee3 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesAbstract.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesAbstract.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesEmpty.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesEmpty.java index b0386b2..9a0f260 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesEmpty.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesEmpty.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesType.java index b27aacc..8956b10 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserStringOverridesType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserType.java index 2e3c194..1721e22 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChooserType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,6 +16,8 @@ package com.io7m.jwheatsheaf.api; +import javafx.stage.Stage; + import java.nio.file.Path; import java.util.List; import java.util.function.Consumer; @@ -64,4 +66,10 @@ public interface JWFileChooserType */ void cancel(); + + /** + * @return The stage to which this file chooser is attached + */ + + Stage stage(); } diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChoosersType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChoosersType.java index 6f34f5f..303553e 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChoosersType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileChoosersType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,8 +16,6 @@ package com.io7m.jwheatsheaf.api; -import javafx.stage.Window; - import java.io.Closeable; /** @@ -32,14 +30,12 @@ public interface JWFileChoosersType extends Closeable /** * Create a new file chooser. * - * @param window The owning window * @param configuration The file chooser configuration * * @return A new file chooser */ JWFileChooserType create( - Window window, JWFileChooserConfiguration configuration ); diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileImageSetType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileImageSetType.java index f21eb31..2deed3d 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileImageSetType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileImageSetType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileKind.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileKind.java index 4704693..001e1a4 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileKind.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileKind.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileSizeFormatterType.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileSizeFormatterType.java index 832c8ae..9abf65d 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileSizeFormatterType.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/JWFileSizeFormatterType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/package-info.java b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/package-info.java index d1455ab..e91ba22 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/package-info.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/com/io7m/jwheatsheaf/api/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,7 +19,7 @@ */ @Export -@Version("2.0.0") +@Version("4.0.0") package com.io7m.jwheatsheaf.api; import org.osgi.annotation.bundle.Export; diff --git a/com.io7m.jwheatsheaf.api/src/main/java/module-info.java b/com.io7m.jwheatsheaf.api/src/main/java/module-info.java index 3063eb3..a32138d 100644 --- a/com.io7m.jwheatsheaf.api/src/main/java/module-info.java +++ b/com.io7m.jwheatsheaf.api/src/main/java/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.api/src/main/string-template/JWVersion.st b/com.io7m.jwheatsheaf.api/src/main/string-template/JWVersion.st new file mode 100644 index 0000000..345e9ff --- /dev/null +++ b/com.io7m.jwheatsheaf.api/src/main/string-template/JWVersion.st @@ -0,0 +1,34 @@ +JWVersion( + appVersion, + appBuild) ::= << + +/* + * Copyright © 2023 Mark Raynsford \ https://www.io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jwheatsheaf.api; + +public final class JWVersion +{ + public static final String MAIN_VERSION = ""; + public static final String MAIN_BUILD = ""; + + private JWVersion() + { + + } +} + +>> diff --git a/com.io7m.jwheatsheaf.documentation/pom.xml b/com.io7m.jwheatsheaf.documentation/pom.xml index fab6d81..3f31312 100644 --- a/com.io7m.jwheatsheaf.documentation/pom.xml +++ b/com.io7m.jwheatsheaf.documentation/pom.xml @@ -9,14 +9,14 @@ com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 com.io7m.jwheatsheaf.documentation com.io7m.jwheatsheaf.documentation JavaFX File Chooser (Documentation) - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf true diff --git a/com.io7m.jwheatsheaf.examples/pom.xml b/com.io7m.jwheatsheaf.examples/pom.xml index 00b8247..8e74a16 100644 --- a/com.io7m.jwheatsheaf.examples/pom.xml +++ b/com.io7m.jwheatsheaf.examples/pom.xml @@ -9,14 +9,14 @@ com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 com.io7m.jwheatsheaf.examples com.io7m.jwheatsheaf.examples JavaFX File Chooser (Examples) - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf true diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleApplication.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleApplication.java index 69e9c4f..05ef907 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleApplication.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleApplication.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilesystems.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilesystems.java index 800185a..bd2991b 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilesystems.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilesystems.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterRejectAll.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterRejectAll.java index c1f79af..c340927 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterRejectAll.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterRejectAll.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterXML.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterXML.java index 364c5de..4cac60c 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterXML.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleFilterXML.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleImageSets.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleImageSets.java index 287f964..cfb4cde 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleImageSets.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleImageSets.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleInverseIconSet.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleInverseIconSet.java index 4ef73d0..227cd94 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleInverseIconSet.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleInverseIconSet.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleMain.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleMain.java index 2151b6b..961a186 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleMain.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleMain.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleViewController.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleViewController.java index 8050680..df52fa1 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleViewController.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleViewController.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -39,6 +39,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -49,6 +50,7 @@ import java.util.Objects; import java.util.ResourceBundle; import java.util.concurrent.Executors; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -88,6 +90,8 @@ public final class ExampleViewController implements Initializable @FXML private CheckBox unusualStrings; @FXML + private CheckBox onlyFiles; + @FXML private ChoiceBox action; @FXML private TextField title; @@ -219,6 +223,13 @@ private void onOpenSelected() stringOverrides = JWFileChooserStringOverridesEmpty.get(); } + final Function fileSelectionMode; + if (this.onlyFiles.isSelected()) { + fileSelectionMode = path -> Boolean.valueOf(Files.isRegularFile(path)); + } else { + fileSelectionMode = path -> Boolean.TRUE; + } + configurationBuilder .setAllowDirectoryCreation(this.allowDirectoryCreation.isSelected()) .setShowParentDirectory(this.parentDirectory.isSelected()) @@ -230,6 +241,7 @@ private void onOpenSelected() .setStringOverrides(stringOverrides) .addFileFilters(new ExampleFilterRejectAll()) .addFileFilters(new ExampleFilterXML()) + .setFileSelectionMode(fileSelectionMode) .addAllRecentFiles(recents); if (this.homeDirectory.isSelected()) { @@ -261,9 +273,7 @@ private void onOpenSelected() testing, locale )) { - final var chooser = - choosers.create(this.main.getScene().getWindow(), configuration); - + final var chooser = choosers.create(configuration); chooser.setEventListener(event -> { if (event instanceof JWFileChooserEventType.JWFileChooserEventErrorType) { final var alert = new Alert(Alert.AlertType.ERROR); diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleWeirdStrings.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleWeirdStrings.java index 7d29015..43b1686 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleWeirdStrings.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/ExampleWeirdStrings.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/package-info.java b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/package-info.java index 41b1f98..63fb9a7 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/package-info.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/com/io7m/jwheatsheaf/examples/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/java/module-info.java b/com.io7m.jwheatsheaf.examples/src/main/java/module-info.java index 9e3f6ec..05632c3 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/java/module-info.java +++ b/com.io7m.jwheatsheaf.examples/src/main/java/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.examples/src/main/resources/com/io7m/jwheatsheaf/examples/example.fxml b/com.io7m.jwheatsheaf.examples/src/main/resources/com/io7m/jwheatsheaf/examples/example.fxml index a3e3fdf..920dd6f 100644 --- a/com.io7m.jwheatsheaf.examples/src/main/resources/com/io7m/jwheatsheaf/examples/example.fxml +++ b/com.io7m.jwheatsheaf.examples/src/main/resources/com/io7m/jwheatsheaf/examples/example.fxml @@ -4,6 +4,7 @@ + @@ -14,7 +15,6 @@ - @@ -51,6 +51,7 @@ + @@ -71,8 +72,7 @@ diff --git a/com.io7m.jwheatsheaf.filter.glob/pom.xml b/com.io7m.jwheatsheaf.filter.glob/pom.xml index c1873b0..7a1a58f 100644 --- a/com.io7m.jwheatsheaf.filter.glob/pom.xml +++ b/com.io7m.jwheatsheaf.filter.glob/pom.xml @@ -9,14 +9,14 @@ com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 com.io7m.jwheatsheaf.filter.glob com.io7m.jwheatsheaf.filter.glob JavaFX File Chooser (Glob filter) - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf 3.0.0-SNAPSHOT diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobBuilderType.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobBuilderType.java index 1c812fe..30edb65 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobBuilderType.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobBuilderType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactory.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactory.java index 6e8e2f3..276cbf1 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactory.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactory.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactoryType.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactoryType.java index b91cba5..d87739b 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactoryType.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobFactoryType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobRuleKind.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobRuleKind.java index a3ba565..36be55b 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobRuleKind.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/JWFilterGlobRuleKind.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlob.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlob.java index 0b103c9..291fbe0 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlob.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlob.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobBuilder.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobBuilder.java index 79d7a9e..60ce25b 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobBuilder.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobRuleType.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobRuleType.java index b7efc27..9bb78dd 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobRuleType.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/JWFilterGlobRuleType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/package-info.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/package-info.java index 7a7c48d..5a506a7 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/package-info.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/internal/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/package-info.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/package-info.java index 0cf01e9..51a2b11 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/package-info.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/com/io7m/jwheatsheaf/filter/glob/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.filter.glob/src/main/java/module-info.java b/com.io7m.jwheatsheaf.filter.glob/src/main/java/module-info.java index 1b215ee..6b25e8f 100644 --- a/com.io7m.jwheatsheaf.filter.glob/src/main/java/module-info.java +++ b/com.io7m.jwheatsheaf.filter.glob/src/main/java/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.oxygen/pom.xml b/com.io7m.jwheatsheaf.oxygen/pom.xml index 66abd3a..6fa9118 100644 --- a/com.io7m.jwheatsheaf.oxygen/pom.xml +++ b/com.io7m.jwheatsheaf.oxygen/pom.xml @@ -9,14 +9,14 @@ com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 com.io7m.jwheatsheaf.oxygen com.io7m.jwheatsheaf.oxygen JavaFX File Chooser (Oxygen Icon Theme) - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf diff --git a/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/JWOxygenIconSet.java b/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/JWOxygenIconSet.java index c06f7ef..9a0b25e 100644 --- a/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/JWOxygenIconSet.java +++ b/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/JWOxygenIconSet.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/package-info.java b/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/package-info.java index 56d641a..d6f6b35 100644 --- a/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/package-info.java +++ b/com.io7m.jwheatsheaf.oxygen/src/main/java/com/io7m/jwheatsheaf/oxygen/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.oxygen/src/main/java/module-info.java b/com.io7m.jwheatsheaf.oxygen/src/main/java/module-info.java index 77002af..566134f 100644 --- a/com.io7m.jwheatsheaf.oxygen/src/main/java/module-info.java +++ b/com.io7m.jwheatsheaf.oxygen/src/main/java/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/pom.xml b/com.io7m.jwheatsheaf.tests/pom.xml index 0fa5603..ef69ffb 100644 --- a/com.io7m.jwheatsheaf.tests/pom.xml +++ b/com.io7m.jwheatsheaf.tests/pom.xml @@ -9,14 +9,14 @@ com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 com.io7m.jwheatsheaf.tests com.io7m.jwheatsheaf.tests JavaFX File Chooser (Test suite) - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf true @@ -38,14 +38,6 @@ org.openjfx javafx-swing - - org.testfx - testfx-core - - - org.testfx - testfx-junit5 - org.mockito mockito-core @@ -58,6 +50,10 @@ com.github.marschall memoryfilesystem + + com.io7m.percentpass + com.io7m.percentpass.extension + org.junit.jupiter junit-jupiter-api @@ -66,6 +62,10 @@ org.junit.jupiter junit-jupiter-engine + + com.io7m.xoanon + com.io7m.xoanon.extension + diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserActionSaveTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserActionSaveTest.java index 4a9d46a..37d18d4 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserActionSaveTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserActionSaveTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,50 +19,63 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.stage.Stage; +import javafx.stage.Window; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; +import java.util.Objects; -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static javafx.scene.input.KeyCode.ENTER; + +@ExtendWith(XoExtension.class) public final class JWFileChooserActionSaveTest { private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } + + @BeforeEach + public void setup() throws Exception { this.events = Collections.synchronizedList(new ArrayList<>()); - this.filesystems = JWTestFilesystems.create(); - final var systems = this.filesystems.filesystems(); - this.dosFilesystem = systems.get("ExampleDOS"); + this.filesystems = + JWTestFilesystems.create(); + final var systems = + this.filesystems.filesystems(); + this.dosFilesystem = + systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.CREATE) @@ -70,17 +83,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); } /** @@ -89,39 +98,35 @@ public void stop() * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_NameField_ExplicitlyTypedName_CandidateSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - - robot.clickOn("#fileChooserNameField"); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.write("GCC.EXE"); - delegate.pauseBriefly(); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - - robot.type(KeyCode.ENTER); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\GCC.EXE"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); + JWTestUtilities.findOKButton(robot, window); + final var nameField = + JWTestUtilities.findNameField(robot, window); + + robot.waitUntil(TIMEOUT, () -> !nameField.isDisabled()); + robot.pointAt(nameField); + robot.click(nameField); + robot.typeText(nameField, "GCC.EXE"); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.typeRaw(nameField, ENTER); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.pointAt(okButton); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\GCC.EXE"); Assertions.assertEquals(0, this.events.size()); } @@ -133,40 +138,48 @@ public void test_NameField_ExplicitlyTypedName_CandidateSelected( * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_SelectDirectly_TargetIsNotFile_TargetSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - + JWTestUtilities.findOKButton(robot, window); final var selectButton = - robot.lookup("#fileChooserSelectDirectButton") - .queryButton(); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(selectButton); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.write("Y:\\NEWFILE.TXT"); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.type(KeyCode.ENTER); - - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Y:\\NEWFILE.TXT"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); + JWTestUtilities.findSelectButton(robot, window); + + robot.waitUntil(TIMEOUT, () -> !selectButton.isDisabled()); + robot.pointAt(selectButton); + robot.click(selectButton); + robot.waitUntil(TIMEOUT, () -> windowIsOpenWithTitle("Enter Path")); + + final var dialogField = + robot.findWithIdInAnyStage( + TextField.class, "fileChooserDialogSelectDirectTextField"); + + /* + * There is a problem with using '\' in some keyboard layouts, so we set + * the text field directly here and then act as if the user typed it. + */ + + robot.pointAt(dialogField); + robot.execute(() -> dialogField.setText("Y:\\NEWFILE.TXT")); + robot.typeRaw(KeyCode.SPACE); + robot.typeRaw(KeyCode.BACK_SPACE); + robot.typeRaw(ENTER); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.pointAt(okButton); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Y:\\NEWFILE.TXT"); Assertions.assertEquals(0, this.events.size()); } @@ -178,40 +191,48 @@ public void test_SelectDirectly_TargetIsNotFile_TargetSelected( * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_SelectDirectly_TargetIsFile_TargetSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - + JWTestUtilities.findOKButton(robot, window); final var selectButton = - robot.lookup("#fileChooserSelectDirectButton") - .queryButton(); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(selectButton); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.write("Z:\\USERS\\GROUCH\\PHOTO.JPG"); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.type(KeyCode.ENTER); - - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\PHOTO.JPG"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); + JWTestUtilities.findSelectButton(robot, window); + + robot.waitUntil(TIMEOUT, () -> !selectButton.isDisabled()); + robot.pointAt(selectButton); + robot.click(selectButton); + robot.waitUntil(TIMEOUT, () -> windowIsOpenWithTitle("Enter Path")); + + final var dialogField = + robot.findWithIdInAnyStage( + TextField.class, "fileChooserDialogSelectDirectTextField"); + + /* + * There is a problem with using '\' in some keyboard layouts, so we set + * the text field directly here and then act as if the user typed it. + */ + + robot.pointAt(dialogField); + robot.execute(() -> dialogField.setText("Z:\\USERS\\GROUCH\\PHOTO.JPG")); + robot.typeRaw(KeyCode.SPACE); + robot.typeRaw(KeyCode.BACK_SPACE); + robot.typeRaw(ENTER); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.pointAt(okButton); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\PHOTO.JPG"); Assertions.assertEquals(0, this.events.size()); } @@ -222,45 +243,58 @@ public void test_SelectDirectly_TargetIsFile_TargetSelected( * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_SelectDirectly_TargetIsDirectory_TargetSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - + JWTestUtilities.findOKButton(robot, window); final var selectButton = - robot.lookup("#fileChooserSelectDirectButton") - .queryButton(); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(selectButton); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.write("Z:\\USERS\\"); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.type(KeyCode.ENTER); - - delegate.waitUntil(() -> !okButton.isDisabled()); - - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Z:\\USERS"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); + JWTestUtilities.findSelectButton(robot, window); + + robot.waitUntil(TIMEOUT, () -> !selectButton.isDisabled()); + robot.pointAt(selectButton); + robot.click(selectButton); + robot.waitUntil(TIMEOUT, () -> windowIsOpenWithTitle("Enter Path")); + + final var dialogField = + robot.findWithIdInAnyStage( + TextField.class, "fileChooserDialogSelectDirectTextField"); + + /* + * There is a problem with using '\' in some keyboard layouts, so we set + * the text field directly here and then act as if the user typed it. + */ + + robot.pointAt(dialogField); + robot.execute(() -> dialogField.setText("Z:\\USERS\\")); + robot.typeRaw(KeyCode.SPACE); + robot.typeRaw(KeyCode.BACK_SPACE); + robot.typeRaw(ENTER); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.pointAt(okButton); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS"); Assertions.assertEquals(0, this.events.size()); } + + private static boolean windowIsOpenWithTitle( + final String title) + { + return Window.getWindows() + .stream() + .filter(w -> w instanceof Stage) + .map(Stage.class::cast) + .anyMatch(w -> Objects.equals(w.getTitle(), title)); + } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserBug34.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserBug34.java new file mode 100644 index 0000000..0dc314c --- /dev/null +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserBug34.java @@ -0,0 +1,124 @@ +/* + * Copyright © 2020 Mark Raynsford https://www.io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jwheatsheaf.tests; + +import com.io7m.jwheatsheaf.api.JWFileChooserAction; +import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; +import com.io7m.jwheatsheaf.api.JWFileChooserEventType; +import com.io7m.jwheatsheaf.api.JWFileChoosersType; +import com.io7m.jwheatsheaf.ui.JWFileChoosers; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCKey; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findNameField; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; +import static javafx.scene.input.KeyCode.ENTER; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(XoExtension.class) +public final class JWFileChooserBug34 +{ + private JWTestFilesystems filesystems; + private FileSystem dosFilesystem; + private List events; + private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; + + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } + + @BeforeEach + public void setup() + throws IOException + { + this.events = Collections.synchronizedList(new ArrayList<>()); + + this.filesystems = JWTestFilesystems.create(); + final var systems = this.filesystems.filesystems(); + this.dosFilesystem = systems.get("ExampleDOS"); + + this.configuration = + JWFileChooserConfiguration.builder() + .setAction(JWFileChooserAction.CREATE) + .setFileSystem(this.dosFilesystem) + .setFileSelectionMode(path -> { + return Boolean.valueOf(Files.isRegularFile(path)); + }) + .build(); + + this.choosers = JWFileChoosers.create(); + } + + @AfterEach + public void tearDown() + throws IOException + { + this.choosers.close(); + } + + /** + * In CREATE mode, specifying a nonexistent file if using a filter that + * checks if files are regular files, does not silently fail when the user + * clicks OK. + */ + + @MinimumPassing(executionCount = 5, passMinimum = 4) + public void test_NameField_NonexistentFileDoesNotSilentlyFail( + final XCCommanderType commander, + final XCRobotType robot) + throws Exception + { + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); + + final var okButton = + findOKButton(robot, window); + final var nameField = + findNameField(robot, window); + + robot.click(nameField); + robot.typeText(nameField, "THIS_DOES_NOT_EXIST.TXT"); + robot.type(nameField, List.of(new XCKey(ENTER, false, false, false))); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\THIS_DOES_NOT_EXIST.TXT"); + assertEquals(0, this.events.size()); + } +} diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserConfigurationTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserConfigurationTest.java index 10b340c..8b4899a 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserConfigurationTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserConfigurationTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDefaultModeTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDefaultModeTest.java index 3ff7235..e24053f 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDefaultModeTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDefaultModeTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,40 +19,44 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; -import javafx.stage.Stage; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; -@SuppressWarnings({"unused", "SameParameterValue"}) -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(XoExtension.class) public final class JWFileChooserDefaultModeTest { - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; + + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } - @Start - public void start(final Stage stage) + @BeforeEach + public void setup() throws Exception { this.events = Collections.synchronizedList(new ArrayList<>()); @@ -61,7 +65,7 @@ public void start(final Stage stage) final var systems = filesystems.filesystems(); final FileSystem dosFilesystem = systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.OPEN_EXISTING_SINGLE) @@ -69,55 +73,48 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); - } - - @AfterEach - public void afterEach() - { - Assertions.assertEquals(0, this.events.size()); } /** * Clicking the "Open" button (if enabled) permits picking the selected file. */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_DefaultMode_ClickOpenButton_SelectedItemReturned( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - final var delegate = new JWRobotDelegate(robot); - final var okButton = delegate.getOkButton(); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(delegate.getTableCellFileName("DATA.XML")); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(delegate.getTableCellFileName("DOC")); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + final var okButton = findOKButton(robot, window); + robot.waitUntil(TIMEOUT, okButton::isDisabled); - this.assertSelected("Z:\\USERS\\GROUCH\\DOC"); - } + final var cell0 = + robot.findWithText(window, "DATA.XML"); + final var cell1 = + robot.findWithText(window, "DOC"); - private void assertSelected(final String... selectedItems) - { - Assertions.assertEquals( - List.of(selectedItems), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); + robot.click(cell0); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + + robot.click(cell1); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\DOC"); + assertEquals(0, this.events.size()); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDirectoryModeTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDirectoryModeTest.java index 0e862e2..fff5c8d 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDirectoryModeTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserDirectoryModeTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,44 +19,51 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; -import javafx.stage.Stage; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.control.TableCell; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; + +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertNothingSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findDirectoryTable; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; /** * Verify that DOC, which represents a directory, may be selected. */ -@SuppressWarnings({"unused", "SameParameterValue"}) -@ExtendWith(ApplicationExtension.class) +@ExtendWith(XoExtension.class) public final class JWFileChooserDirectoryModeTest { - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; + + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } - @Start - public void start(final Stage stage) + @BeforeEach + public void setup() throws Exception { this.events = Collections.synchronizedList(new ArrayList<>()); @@ -65,7 +72,7 @@ public void start(final Stage stage) final var systems = filesystems.filesystems(); final FileSystem dosFilesystem = systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.OPEN_EXISTING_SINGLE) @@ -74,22 +81,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); - } - - @Stop - public void stop() - throws IOException - { - this.choosers.close(); - this.chooser.cancel(); } @AfterEach public void afterEach() + throws IOException { + this.choosers.close(); Assertions.assertEquals(0, this.events.size()); } @@ -98,90 +96,111 @@ public void afterEach() * candidate for opening. */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_DirectoryMode_SingleClickDirectory_CandidateSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); + + final var okButton = + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, okButton::isDisabled); - final var delegate = new JWRobotDelegate(robot); - final var okButton = delegate.getOkButton(); + final var docCell = + robot.findWithText(TableCell.class, directoryTable, "DOC"); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(delegate.getDirectoryTable()); - delegate.pauseBriefly(); - robot.clickOn(delegate.getTableCellFileName("DOC")); - delegate.pauseBriefly(); + robot.click(directoryTable); + robot.click(docCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - this.assertSelected("Z:\\USERS\\GROUCH\\DOC"); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\DOC"); } /** - * Double clicking a file in the directory listing does nothing. + * Double-clicking a file in the directory listing does nothing. */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_DirectoryMode_SingleClickFile_NothingSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); + + final var okButton = + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); - final var delegate = new JWRobotDelegate(robot); - final var okButton = delegate.getOkButton(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.pointAt(directoryTable); + robot.click(directoryTable); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(delegate.getDirectoryTable()); - delegate.pauseBriefly(); - robot.clickOn(delegate.getTableCellFileName("DATA.XML")); - delegate.pauseBriefly(); + final var docCell = + robot.findWithText(TableCell.class, directoryTable, "DATA.XML"); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(okButton); + robot.pointAt(docCell); + robot.doubleClick(docCell); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + robot.click(okButton); - this.assertSelected(); + assertNothingSelected(chooser); } /** - * Double clicking a directory navigates to that directory. + * Double-clicking a directory navigates to that directory. */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_DirectoryMode_DoubleClickDirectory_DirectoryNavigated( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); - final var delegate = new JWRobotDelegate(robot); - final var okButton = delegate.getOkButton(); + final var okButton = + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.doubleClickOn(delegate.getTableCellFileName("DOC")); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - delegate.pauseBriefly(); - robot.clickOn(delegate.getTableCellFileName(".")); - delegate.pauseBriefly(); + final var docCell = + robot.findWithText(TableCell.class, directoryTable, "DOC"); - robot.clickOn(okButton); + robot.pointAt(docCell); + robot.doubleClick(docCell); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); - this.assertSelected("Z:\\USERS\\GROUCH\\DOC"); - } + final var dotCell = + robot.findWithText(TableCell.class, directoryTable, "."); - private void assertSelected(final String... selectedItems) - { - Assertions.assertEquals( - List.of(selectedItems), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); + robot.pointAt(dotCell); + robot.click(dotCell); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\DOC"); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserFilterDefaultTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserFilterDefaultTest.java index 93d576a..1754d70 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserFilterDefaultTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserFilterDefaultTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,21 +19,16 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; -import javafx.stage.Stage; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; -import org.testfx.matcher.control.TableViewMatchers; import java.io.IOException; import java.nio.file.FileSystem; @@ -41,17 +36,30 @@ import java.util.Collections; import java.util.List; -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findCancelButton; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findDirectoryTable; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@ExtendWith(XoExtension.class) public final class JWFileChooserFilterDefaultTest { private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } + + @BeforeEach + public void setup() throws Exception { this.events = Collections.synchronizedList(new ArrayList<>()); @@ -63,7 +71,7 @@ public void start(final Stage stage) final var filter = new JWFileFilterHideAll(); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.CREATE) @@ -73,17 +81,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); } /** @@ -92,33 +96,30 @@ public void stop() * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testFilterDefaultHidesEverything( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); - final var delegate = new JWRobotDelegate(robot); - - final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); final var cancelButton = - robot.lookup("#fileChooserCancelButton") - .queryButton(); - - delegate.pauseBriefly(); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - + findCancelButton(robot, window); final var tableView = - robot.lookup("#fileChooserDirectoryTable") - .queryTableView(); + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !tableView.isDisabled()); + robot.execute(() -> assertEquals(0, tableView.getItems().size())); - FxAssert.verifyThat(tableView, TableViewMatchers.hasNumRows(0)); - robot.clickOn(cancelButton); + robot.execute(() -> assertTrue(window.isFocused())); + robot.execute(() -> assertTrue(window.isShowing())); + robot.click(cancelButton); - Assertions.assertEquals(List.of(), this.chooser.result()); - Assertions.assertEquals(0, this.events.size()); + assertEquals(List.of(), chooser.result()); + assertEquals(0, this.events.size()); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameCreateTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameCreateTest.java index 544edcc..3bb83ac 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameCreateTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameCreateTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,42 +19,47 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; -import javafx.stage.Stage; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(XoExtension.class) public final class JWFileChooserInitialNameCreateTest { private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) - throws Exception + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } + + @BeforeEach + public void setup() + throws IOException { this.events = Collections.synchronizedList(new ArrayList<>()); @@ -62,7 +67,7 @@ public void start(final Stage stage) final var systems = this.filesystems.filesystems(); this.dosFilesystem = systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.CREATE) @@ -71,17 +76,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); } /** @@ -90,34 +91,26 @@ public void stop() * @param robot The FX test robot */ - @Test - public void test_SelectItem_WithInitialFileName_CandidateSelected( - final FxRobot robot, - final TestInfo info) - throws TimeoutException + @MinimumPassing(executionCount = 5, passMinimum = 4) + public void testInitialNameCreate( + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - final var textField = - robot.lookup("#fileChooserNameField") - .queryTextInputControl(); - - delegate.waitUntil(() -> !textField.textProperty().get().isEmpty()); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\SOMETHING.TXT"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + findOKButton(robot, window); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.pointAt(okButton); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\SOMETHING.TXT"); + assertEquals(0, this.events.size()); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameOpenTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameOpenTest.java index 255299c..e1ff1cc 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameOpenTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserInitialNameOpenTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,42 +19,47 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; -import javafx.stage.Stage; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(XoExtension.class) public final class JWFileChooserInitialNameOpenTest { private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) - throws Exception + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } + + @BeforeEach + public void setup() + throws IOException { this.events = Collections.synchronizedList(new ArrayList<>()); @@ -62,7 +67,7 @@ public void start(final Stage stage) final var systems = this.filesystems.filesystems(); this.dosFilesystem = systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.OPEN_EXISTING_SINGLE) @@ -71,17 +76,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); } /** @@ -90,33 +91,25 @@ public void stop() * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testInitialNameOpen( - final FxRobot robot, - final TestInfo info) - throws TimeoutException + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - final var textField = - robot.lookup("#fileChooserNameField") - .queryTextInputControl(); - - delegate.waitUntil(() -> !textField.textProperty().get().isEmpty()); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - delegate.pauseBriefly(); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\README.TXT"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + findOKButton(robot, window); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\README.TXT"); + assertEquals(0, this.events.size()); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserParentDirectoryTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserParentDirectoryTest.java index e6dcd76..ace71c8 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserParentDirectoryTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserParentDirectoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,48 +19,52 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; -import javafx.stage.Stage; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.control.TableCell; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; +import java.util.Objects; -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findDirectoryTable; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findNameField; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; + +@ExtendWith(XoExtension.class) public final class JWFileChooserParentDirectoryTest { - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) + @BeforeEach + public void setup() throws Exception { this.events = Collections.synchronizedList(new ArrayList<>()); - final JWTestFilesystems filesystems = JWTestFilesystems.create(); - final var systems = filesystems.filesystems(); - final FileSystem dosFilesystem = systems.get("ExampleDOS"); + final JWTestFilesystems filesystems = + JWTestFilesystems.create(); + final var systems = + filesystems.filesystems(); + final FileSystem dosFilesystem = + systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setShowParentDirectory(true) @@ -69,23 +73,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); - } - - @AfterEach - public void afterEach() - { - Assertions.assertEquals(0, this.events.size()); } /** @@ -93,37 +87,48 @@ public void afterEach() * directory. */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_ParentDirectory_DoubleClickParent_NavigatesToParent( - final FxRobot robot, - final TestInfo info) - { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); - final var okButton = delegate.getOkButton(); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.doubleClickOn(delegate.getTableCellFileName("..")); - delegate.pauseBriefly(); - - robot.clickOn(delegate.getTableCellFileName(".")); - delegate.pauseBriefly(); - - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - this.assertSelected("Z:\\USERS"); - } - - private void assertSelected(final String... selectedItems) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - Assertions.assertEquals( - List.of(selectedItems), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); + + final var okButton = + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + final var nameField = + findNameField(robot, window); + + robot.waitUntil(TIMEOUT, window::isShowing); + robot.waitUntil(TIMEOUT, window::isFocused); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + + final var dotDot = + robot.findWithText(directoryTable, ".."); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.pointAt(dotDot); + robot.doubleClick(dotDot); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + + final var dot = + robot.findWithText(directoryTable, "."); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.pointAt(dot); + robot.click(dot); + robot.waitUntil(TIMEOUT, () -> Objects.equals(nameField.getText(), ".")); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS"); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSaveConfirmTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSaveConfirmTest.java index 7daebd0..33083b3 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSaveConfirmTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSaveConfirmTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,40 +19,50 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.control.Button; import javafx.stage.Stage; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; - -import java.io.IOException; + import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; +import java.util.Objects; + +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findNameField; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; +import static javafx.stage.Window.getWindows; +import static org.junit.jupiter.api.Assertions.assertEquals; -@ExtendWith(ApplicationExtension.class) +@ExtendWith(XoExtension.class) public final class JWFileChooserSaveConfirmTest { private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; + + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } - @Start - public void start(final Stage stage) + @BeforeEach + public void setup() throws Exception { this.events = Collections.synchronizedList(new ArrayList<>()); @@ -61,7 +71,7 @@ public void start(final Stage stage) final var systems = this.filesystems.filesystems(); this.dosFilesystem = systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.CREATE) @@ -70,17 +80,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() - throws IOException + @AfterEach + public void tearDown() + throws Exception { this.choosers.close(); - this.chooser.cancel(); } /** @@ -90,44 +96,49 @@ public void stop() * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_Confirmation_SelectedName_CandidateSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var nameField = + findNameField(robot, window); + + robot.click(nameField); + robot.waitUntil(TIMEOUT, okButton::isDisabled); - robot.clickOn("#fileChooserNameField"); + robot.typeText(nameField, "DATA.XML"); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.write("DATA.XML"); - delegate.pauseBriefly(); + robot.click(okButton); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - delegate.pauseBriefly(); + /* + * Wait until the popup has opened. + */ + + robot.waitUntil(TIMEOUT, () -> { + return getWindows() + .stream() + .filter(w -> w instanceof Stage) + .map(Stage.class::cast) + .anyMatch(w -> Objects.equals(w.getTitle(), "Confirmation")); + }); final var replaceButton = - robot.lookup("Replace") - .queryButton(); + robot.findWithTextInAnyStage(Button.class, "Replace"); - robot.clickOn(replaceButton); - delegate.pauseBriefly(); + robot.click(replaceButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\DATA.XML"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\DATA.XML"); + assertEquals(0, this.events.size()); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSlowIOTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSlowIOTest.java index f9c31c0..ddcc741 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSlowIOTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserSlowIOTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,27 +19,22 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; import com.io7m.jwheatsheaf.ui.internal.JWFileChoosersTesting; -import javafx.stage.Stage; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.control.ListView; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -47,10 +42,15 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.Executors; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findDirectoryTable; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(XoExtension.class) public final class JWFileChooserSlowIOTest { private static final Logger LOG = @@ -58,21 +58,22 @@ public final class JWFileChooserSlowIOTest private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) + @BeforeEach + public void setup() throws Exception { - this.events = Collections.synchronizedList(new ArrayList<>()); + this.events = + Collections.synchronizedList(new ArrayList<>()); this.filesystems = JWTestFilesystems.create(); final var systems = this.filesystems.filesystems(); this.dosFilesystem = systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.OPEN_EXISTING_MULTIPLE) @@ -87,18 +88,13 @@ public void start(final Stage stage) .build(), Locale.getDefault() ); - - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); } /** @@ -108,49 +104,42 @@ public void stop() * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_SelectItem_SingleClickFirstRow_CandidateSelected( - final FxRobot robot, - final TestInfo info) - throws TimeoutException + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - + findOKButton(robot, window); final var root = - robot.lookup(".fileChooserSourceList") - .query(); - + robot.findWithId(ListView.class, window, "fileChooserSourceList"); final var directoryTable = - robot.lookup(".fileChooserDirectoryTable") - .query(); - - delegate.waitUntil(() -> Boolean.valueOf(!root.isDisabled())); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - - robot.doubleClickOn("Z:\\"); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - - delegate.waitUntil(() -> Boolean.valueOf(!root.isDisabled())); - robot.clickOn(directoryTable); - delegate.pauseBriefly(); - robot.clickOn("USERS"); - - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Z:\\USERS"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + findDirectoryTable(robot, window); + + robot.waitUntil(5_000L, () -> !root.isDisabled()); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + + robot.doubleClick(robot.findWithText(root, "Z:\\")); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + + robot.waitUntil(5_000L, () -> !root.isDisabled()); + robot.click(directoryTable); + + robot.waitUntil(5_000L, () -> !root.isDisabled()); + robot.click(robot.findWithText(directoryTable, "USERS")); + + robot.waitUntil(5_000L, () -> !root.isDisabled()); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS"); + assertEquals(0, this.events.size()); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserTest.java index a5bc4e3..16a27b4 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,36 +19,50 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.Node; import javafx.scene.control.TableCell; import javafx.scene.input.KeyCode; -import javafx.stage.Stage; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import javafx.stage.PopupWindow; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; -@ExtendWith(ApplicationExtension.class) +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findCancelButton; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findDirectoryCreateButton; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findDirectoryTable; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findHomeButton; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findNameField; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findOKButton; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findPathMenu; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findSearchField; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findSourceList; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findUpButton; +import static java.nio.file.Files.createDirectories; +import static java.nio.file.Files.writeString; +import static javafx.scene.input.KeyCode.ENTER; +import static javafx.stage.Window.getWindows; +import static org.junit.jupiter.api.Assertions.assertEquals; + + +@ExtendWith(XoExtension.class) public final class JWFileChooserTest { private static final Logger LOG = @@ -56,21 +70,25 @@ public final class JWFileChooserTest private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) - throws Exception + @BeforeEach + public void setup() + throws IOException { - this.events = Collections.synchronizedList(new ArrayList<>()); + this.events = + Collections.synchronizedList(new ArrayList<>()); - this.filesystems = JWTestFilesystems.create(); - final var systems = this.filesystems.filesystems(); - this.dosFilesystem = systems.get("ExampleDOS"); + this.filesystems = + JWTestFilesystems.create(); + final var systems = + this.filesystems.filesystems(); + this.dosFilesystem = + systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.OPEN_EXISTING_MULTIPLE) @@ -79,58 +97,62 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); } /** * Clicking the cancel button yields nothing. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testCancel( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); + + robot.click(findCancelButton(robot, window)); + robot.waitForStageToClose(window, TIMEOUT); - robot.clickOn("#fileChooserCancelButton"); - Assertions.assertEquals(List.of(), this.chooser.result()); - Assertions.assertEquals(0, this.events.size()); + assertEquals(List.of(), chooser.result()); + assertEquals(0, this.events.size()); } /** * Clicking the first row of the directory table yields a directory, and * clicking the OK button selects it. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testDirectorySelect( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .queryAllAs(TableCell.class) + robot.findAll(TableCell.class, directoryTable) .stream() .filter(cell -> Objects.equals(cell.getText(), ".")) .findFirst() @@ -138,59 +160,62 @@ public void testDirectorySelect( "Unable to locate a '.' directory entry") ); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(targetCell); - robot.clickOn(targetCell); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + robot.click(targetCell); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH"); + assertEquals(0, this.events.size()); } /** * Navigation via the path menu works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testPathMenuSelect( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); final var choice = - robot.lookup("#fileChooserPathMenu") - .query(); - - robot.clickOn(choice); + findPathMenu(robot, window); + + robot.click(choice); + + final var popup = + robot.evaluate(() -> { + return getWindows() + .stream() + .filter(w -> w instanceof PopupWindow) + .map(PopupWindow.class::cast) + .findFirst() + .orElseThrow() + .getScene() + .getRoot(); + }); final var pathMenuItem = - robot.lookup(".context-menu") - .lookup("Z:\\") - .query(); + robot.findWithText(popup, "Z:\\"); LOG.debug("pathMenuItem: {}", pathMenuItem); - robot.clickOn(pathMenuItem); - delegate.pauseBriefly(); + robot.click(pathMenuItem); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .queryAllAs(TableCell.class) + robot.findAll(TableCell.class, directoryTable) .stream() .filter(cell -> Objects.equals(cell.getText(), ".")) .findFirst() @@ -198,137 +223,122 @@ public void testPathMenuSelect( "Unable to locate a '.' directory entry") ); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(targetCell); - robot.clickOn(targetCell); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + robot.click(targetCell); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\"); + assertEquals(0, this.events.size()); } /** * Navigation via the filesystem root menu succeeds. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testSourceMenuSelect( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var sourceList = + findSourceList(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); final var rootItem = - robot.lookup(".fileChooserSourceList") - .lookup("Z:\\") - .query(); + robot.findWithText(sourceList, "Z:\\"); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); LOG.debug("rootItem: {}", rootItem); - robot.doubleClickOn(rootItem); - delegate.pauseBriefly(); + robot.pointAt(rootItem); + robot.doubleClick(rootItem); final TableCell row = - robot.lookup(".table-row-cell") - .lookup("USERS") - .query(); + robot.findWithText(TableCell.class, directoryTable, "USERS"); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(row); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + robot.pointAt(row); + robot.click(row); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS"); + assertEquals(0, this.events.size()); } /** - * Double clicking a directory navigates to that directory. - * - * @param robot The FX test robot - * - * @throws Exception On errors + * Double-clicking a directory navigates to that directory. */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testDirectoryDoubleClick( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var sourceList = + findSourceList(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); - Files.createDirectories( + createDirectories( this.dosFilesystem.getPath("Y:\\", "EGG")); - Files.writeString( + writeString( this.dosFilesystem.getPath("Y:\\", "EGG", "EGG.TXT"), "EGG!"); - final var sourceList = - robot.lookup(".fileChooserSourceList") - .query(); - - final var directoryTable = - robot.lookup(".fileChooserDirectoryTable") - .query(); - - final var sourceItem = - robot.lookup(".fileChooserSourceList") - .lookup("Y:\\") - .query(); + robot.waitUntil(TIMEOUT, () -> !sourceList.isDisabled()); + final var sourceItem = robot.findWithText(sourceList, "Y:\\"); + robot.pointAt(sourceItem); + robot.doubleClick(sourceItem); - robot.doubleClickOn(sourceItem); - delegate.waitUntil(() -> !sourceList.isDisabled()); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + final var egg = robot.findWithText(directoryTable, "EGG"); + robot.pointAt(egg); + robot.doubleClick(egg); + robot.waitUntil(TIMEOUT, () -> !sourceList.isDisabled()); - robot.doubleClickOn("EGG"); - delegate.waitUntil(() -> !sourceList.isDisabled()); + robot.waitUntil(TIMEOUT, okButton::isDisabled); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn(directoryTable); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.pointAt(directoryTable); + robot.click(directoryTable); - robot.clickOn("EGG.TXT"); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + final var eggText = robot.findWithText(directoryTable, "EGG.TXT"); + robot.click(eggText); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Y:\\EGG\\EGG.TXT"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Y:\\EGG\\EGG.TXT"); + assertEquals(0, this.events.size()); } /** @@ -337,122 +347,124 @@ public void testDirectoryDoubleClick( * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testDirectoryCreate( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var sourceList = + findSourceList(robot, window); + final var createButton = + findDirectoryCreateButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); - final var rootItem = - robot.lookup(".fileChooserSourceList") - .lookup("X:\\") - .query(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); - robot.doubleClickOn(rootItem); + final var rootItem = robot.findWithText(sourceList, "X:\\"); + robot.pointAt(rootItem); + robot.doubleClick(rootItem); - robot.clickOn("#fileChooserCreateDirectoryButton"); - robot.write("CREATED"); - robot.type(KeyCode.ENTER); + robot.waitUntil(TIMEOUT, () -> !createButton.isDisabled()); + robot.pointAt(createButton); + robot.click(createButton); + robot.typeText("CREATED"); + robot.typeRaw(ENTER); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.clickOn("CREATED"); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn("#fileChooserOKButton"); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); - Assertions.assertEquals( - List.of("X:\\CREATED"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + final var created = robot.findWithText(directoryTable, "CREATED"); + robot.pointAt(created); + robot.click(created); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.pointAt(okButton); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "X:\\CREATED"); + assertEquals(0, this.events.size()); } /** * Searching works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testDirectorySearch( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); final var searchField = - robot.lookup("#fileChooserSearchField") - .query(); - robot.clickOn(searchField); + findSearchField(robot, window); + + robot.waitUntil(TIMEOUT, okButton::isDisabled); - robot.write("PHOTO.JPG"); + robot.click(searchField); + robot.typeText(searchField, "PHOTO.JPG"); final var tableItem = - robot.lookup("PHOTO.JPG") - .match(node -> node instanceof TableCell) - .query(); + robot.findWithText(TableCell.class, directoryTable, "PHOTO.JPG"); LOG.debug("testDirectorySearch: {}", tableItem); - robot.clickOn(tableItem); - delegate.pauseBriefly(); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\PHOTO.JPG"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + robot.click(tableItem); + + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); + + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\PHOTO.JPG"); + assertEquals(0, this.events.size()); } /** * The up button works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testDirectoryUp( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - - robot.clickOn("#fileChooserUpButton"); - delegate.pauseBriefly(); + findOKButton(robot, window); + final var upButton = + findUpButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); - robot.clickOn("#fileChooserUpButton"); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, okButton::isDisabled); + robot.click(upButton); + robot.waitUntil(TIMEOUT, () -> !upButton.isDisabled()); + robot.click(upButton); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .queryAllAs(TableCell.class) + robot.findAll(TableCell.class, directoryTable) .stream() .filter(cell -> Objects.equals(cell.getText(), "USERS")) .findFirst() @@ -460,51 +472,44 @@ public void testDirectoryUp( "Unable to locate a 'USERS' directory entry") ); - robot.clickOn(targetCell); - delegate.pauseBriefly(); - robot.clickOn(targetCell); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS"); + assertEquals(0, this.events.size()); } /** * The home button works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testDirectoryHome( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); final var homeButton = - robot.lookup("#fileChooserHomeButton") - .queryButton(); + findHomeButton(robot, window); - robot.clickOn(homeButton); + robot.waitUntil(TIMEOUT, () -> !homeButton.isDisabled()); + robot.click(homeButton); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .queryAllAs(TableCell.class) + robot.findAll(TableCell.class, directoryTable) .stream() .filter(cell -> Objects.equals(cell.getText(), "FILE.TXT")) .findFirst() @@ -512,284 +517,265 @@ public void testDirectoryHome( "Unable to locate a 'FILE.TXT' directory entry") ); - robot.clickOn(targetCell); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\HOME\\FILE.TXT"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\HOME\\FILE.TXT"); + assertEquals(0, this.events.size()); } /** * Pressing escape closes the dialog without selecting a file. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testEscapeCloses( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); - final var rootItem = - robot.lookup(".fileChooserSourceList") - .query(); + final var sourceList = + findSourceList(robot, window); - robot.clickOn(rootItem); - robot.type(KeyCode.ESCAPE); + robot.click(sourceList); + robot.typeRaw(KeyCode.ESCAPE); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of(), - this.chooser.result() - ); - Assertions.assertEquals(0, this.events.size()); + assertEquals(List.of(), chooser.result()); + assertEquals(0, this.events.size()); } /** * Sorting by type works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testSortType( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); final var column = - robot.lookup("#fileChooserTableColumnType") - .query(); + robot.findWithId(directoryTable, "fileChooserTableColumnType"); - delegate.pauseBriefly(); - robot.clickOn(column); - robot.clickOn(column); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.pointAt(column); + robot.click(column); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.pointAt(column); + robot.click(column); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .nth(0) - .queryAs(TableCell.class); + robot.findAll(TableCell.class, directoryTable) + .stream() + .findFirst() + .orElseThrow(); - delegate.pauseBriefly(); - robot.clickOn(targetCell); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.pointAt(targetCell); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\README.TXT"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\README.TXT"); + assertEquals(0, this.events.size()); } /** * Sorting by name works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testSortName( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); final var column = - robot.lookup("#fileChooserTableColumnName") - .query(); + robot.findWithId(directoryTable, "fileChooserTableColumnName"); - delegate.pauseBriefly(); - robot.clickOn(column); - robot.clickOn(column); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(column); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(column); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .nth(0) - .queryAs(TableCell.class); + robot.findAll(TableCell.class, directoryTable) + .stream() + .findFirst() + .orElseThrow(); - delegate.pauseBriefly(); - robot.clickOn(targetCell); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\README.TXT"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\README.TXT"); + assertEquals(0, this.events.size()); } /** * Sorting by time works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testSortTime( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); final var column = - robot.lookup("#fileChooserTableColumnModified") - .query(); + robot.findWithId(directoryTable, "fileChooserTableColumnModified"); - delegate.pauseBriefly(); - robot.clickOn(column); - robot.clickOn(column); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(column); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(column); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .nth(0) - .queryAs(TableCell.class); + robot.findAll(TableCell.class, directoryTable) + .stream() + .findFirst() + .orElseThrow(); - delegate.pauseBriefly(); - robot.clickOn(targetCell); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\PHOTO.JPG"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\PHOTO.JPG"); + assertEquals(0, this.events.size()); } /** * Sorting by size works. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void testSortSize( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); + findOKButton(robot, window); + final var directoryTable = + findDirectoryTable(robot, window); + + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); final var column = - robot.lookup("#fileChooserTableColumnSize") - .query(); + robot.findWithId(directoryTable, "fileChooserTableColumnSize"); - delegate.pauseBriefly(); - robot.clickOn(column); - robot.clickOn(column); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(column); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(column); final var targetCell = - robot.lookup(n -> n instanceof TableCell) - .nth(0) - .queryAs(TableCell.class); + robot.findAll(TableCell.class, directoryTable) + .stream() + .findFirst() + .orElseThrow(); - delegate.pauseBriefly(); - robot.clickOn(targetCell); - delegate.pauseBriefly(); + robot.waitUntil(TIMEOUT, () -> !directoryTable.isDisabled()); + robot.click(targetCell); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\DATA.XML"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\DATA.XML"); + assertEquals(0, this.events.size()); } /** * Typing a name into the name field and pressing return selects an item and * requests focus for the OK button. Pressing return again presses the button. - * - * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_TypeNameIntoFieldAndReturn_CandidateSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) + throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("#fileChooserOKButton") - .queryButton(); - + findOKButton(robot, window); final var fileField = - robot.lookup("#fileChooserNameField") - .query(); + findNameField(robot, window); - robot.clickOn(fileField); - robot.write("DATA.XML"); - robot.type(KeyCode.ENTER); - delegate.pauseBriefly(); + robot.click(fileField); + robot.typeText(fileField, "DATA.XML"); + robot.typeRaw(ENTER); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.type(KeyCode.ENTER); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.typeRaw(ENTER); + robot.waitForStageToClose(window, TIMEOUT); - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\DATA.XML"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\DATA.XML"); + assertEquals(0, this.events.size()); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserWeirdStringsTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserWeirdStringsTest.java index 057d80d..400bb68 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserWeirdStringsTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileChooserWeirdStringsTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,41 +19,54 @@ import com.io7m.jwheatsheaf.api.JWFileChooserAction; import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; import com.io7m.jwheatsheaf.api.JWFileChooserEventType; -import com.io7m.jwheatsheaf.api.JWFileChooserType; import com.io7m.jwheatsheaf.api.JWFileChoosersType; import com.io7m.jwheatsheaf.ui.JWFileChoosers; +import com.io7m.percentpass.extension.MinimumPassing; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.control.Button; import javafx.stage.Stage; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; +import javafx.stage.Window; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; -import org.testfx.api.FxAssert; -import org.testfx.api.FxRobot; -import org.testfx.framework.junit5.ApplicationExtension; -import org.testfx.framework.junit5.Start; -import org.testfx.framework.junit5.Stop; -import org.testfx.matcher.base.NodeMatchers; import java.io.IOException; import java.nio.file.FileSystem; -import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; - -@ExtendWith(ApplicationExtension.class) +import java.util.Objects; + +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.TIMEOUT; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.assertIsSelected; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.createChooser; +import static com.io7m.jwheatsheaf.tests.JWTestUtilities.findNameField; +import static javafx.scene.input.KeyCode.BACK_SPACE; +import static javafx.scene.input.KeyCode.SPACE; +import static javafx.stage.Window.getWindows; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(XoExtension.class) public final class JWFileChooserWeirdStringsTest { private JWTestFilesystems filesystems; private FileSystem dosFilesystem; - private JWFileChooserType chooser; private List events; private JWFileChoosersType choosers; + private JWFileChooserConfiguration configuration; - @Start - public void start(final Stage stage) - throws Exception + @BeforeAll + public static void beforeAll() + { + JWTestUtilities.publishApplicationInfo(); + } + + @BeforeEach + public void setup() + throws IOException { this.events = Collections.synchronizedList(new ArrayList<>()); @@ -61,7 +74,7 @@ public void start(final Stage stage) final var systems = this.filesystems.filesystems(); this.dosFilesystem = systems.get("ExampleDOS"); - final var configuration = + this.configuration = JWFileChooserConfiguration.builder() .setAllowDirectoryCreation(true) .setAction(JWFileChooserAction.CREATE) @@ -71,17 +84,13 @@ public void start(final Stage stage) .build(); this.choosers = JWFileChoosers.create(); - this.chooser = this.choosers.create(stage, configuration); - this.chooser.setEventListener(event -> this.events.add(event)); - this.chooser.show(); } - @Stop - public void stop() + @AfterEach + public void tearDown() throws IOException { this.choosers.close(); - this.chooser.cancel(); } /** @@ -91,49 +100,65 @@ public void stop() * @param robot The FX test robot */ - @Test + @MinimumPassing(executionCount = 5, passMinimum = 4) public void test_Confirmation_WeirdStrings_CandidateSelected( - final FxRobot robot, - final TestInfo info) + final XCCommanderType commander, + final XCRobotType robot) throws Exception { - JWFileWindowTitles.setTitle(this.chooser, info); - - final var delegate = new JWRobotDelegate(robot); + final var chooser = + createChooser(this.choosers, this.configuration, commander); + final var window = + chooser.stage(); final var okButton = - robot.lookup("Manticulate") - .queryButton(); - - robot.clickOn("#fileChooserNameField"); + robot.findWithText(Button.class, window, "Manticulate"); + final var nameField = + findNameField(robot, window); + + robot.waitUntil(TIMEOUT, () -> !nameField.isDisabled()); + robot.click(nameField); + + robot.typeText(nameField, "DATA.XML"); + robot.typeRaw(SPACE); + robot.typeRaw(BACK_SPACE); + robot.waitUntil(TIMEOUT, () -> !okButton.isDisabled()); + robot.click(okButton); + + robot.waitUntil(TIMEOUT, () -> windowIsOpenWithTitle("Confirmation")); + + final var dialog = + robot.evaluate(() -> { + return getWindows() + .stream() + .filter(w -> w instanceof Stage) + .map(Stage.class::cast) + .filter(s -> Objects.equals(s.getTitle(), "Confirmation")) + .findFirst() + .orElseThrow(); + }); + + robot.findWithText(dialog, "Defloccate velleity 'DATA.XML'?"); + robot.findWithText(dialog, "Defloccate velleity?"); - FxAssert.verifyThat(okButton, NodeMatchers.isDisabled()); - robot.write("DATA.XML"); - delegate.pauseBriefly(); + final var replaceButton = + robot.findWithText(Button.class, dialog, "Defloccate"); - FxAssert.verifyThat(okButton, NodeMatchers.isEnabled()); - robot.clickOn(okButton); - delegate.pauseBriefly(); + robot.pointAt(replaceButton); + robot.click(replaceButton); + robot.waitUntil(TIMEOUT, () -> !dialog.isShowing()); - robot.lookup("Defloccate velleity 'DATA.XML'?") - .queryLabeled(); - robot.lookup("Defloccate velleity?") - .queryLabeled(); + assertIsSelected(chooser, "Z:\\USERS\\GROUCH\\DATA.XML"); + assertEquals(0, this.events.size()); + } - final var replaceButton = - robot.lookup("Defloccate") - .queryButton(); - - robot.clickOn(replaceButton); - delegate.pauseBriefly(); - - Assertions.assertEquals( - List.of("Z:\\USERS\\GROUCH\\DATA.XML"), - this.chooser.result() - .stream() - .map(Path::toString) - .collect(Collectors.toList()) - ); - Assertions.assertEquals(0, this.events.size()); + private static boolean windowIsOpenWithTitle( + final String title) + { + return Window.getWindows() + .stream() + .filter(w -> w instanceof Stage) + .map(Stage.class::cast) + .anyMatch(w -> Objects.equals(w.getTitle(), title)); } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileFilterHideAll.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileFilterHideAll.java index 44fd68d..23114e9 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileFilterHideAll.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileFilterHideAll.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileItemsTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileItemsTest.java index f72e5d1..a62b57d 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileItemsTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileItemsTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileListTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileListTest.java deleted file mode 100644 index 2f5e6fd..0000000 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileListTest.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright © 2020 Mark Raynsford http://io7m.com - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package com.io7m.jwheatsheaf.tests; - -import com.io7m.jwheatsheaf.api.JWFileChooserFilterType; -import com.io7m.jwheatsheaf.api.JWFileChoosersType; -import com.io7m.jwheatsheaf.api.JWFileKind; -import com.io7m.jwheatsheaf.ui.JWFileChoosers; -import com.io7m.jwheatsheaf.ui.internal.JWFileChooserFilterOnlyDirectories; -import com.io7m.jwheatsheaf.ui.internal.JWFileItem; -import com.io7m.jwheatsheaf.ui.internal.JWFileList; -import com.io7m.jwheatsheaf.ui.internal.JWStrings; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.FileTime; -import java.util.List; -import java.util.Objects; - -public final class JWFileListTest -{ - private JWFileItem item0; - private JWFileItem item1; - private JWFileItem item2; - private List baseItems; - private JWStrings strings; - private JWFileChoosersType choosers; - - @BeforeEach - public void testSetup() - { - this.strings = - JWStrings.of(JWStrings.getResourceBundle()); - this.choosers = - JWFileChoosers.create(); - - this.item0 = - JWFileItem.builder() - .setPath(Paths.get("/x")) - .setModifiedTime(FileTime.fromMillis(0L)) - .setKind(JWFileKind.REGULAR_FILE) - .setSize(0L) - .build(); - this.item1 = - JWFileItem.builder() - .setPath(Paths.get("/y")) - .setModifiedTime(FileTime.fromMillis(0L)) - .setKind(JWFileKind.REGULAR_FILE) - .setSize(0L) - .build(); - this.item2 = - JWFileItem.builder() - .setPath(Paths.get("/z")) - .setModifiedTime(FileTime.fromMillis(0L)) - .setKind(JWFileKind.REGULAR_FILE) - .setSize(0L) - .build(); - - this.baseItems = - List.of(this.item0, this.item1, this.item2); - } - - @AfterEach - public void testShutdown() - throws IOException - { - this.choosers.close(); - } - - @Test - public void testListBase() - { - final var items = new JWFileList(this.choosers.filterForAllFiles()); - - items.setItems(this.baseItems); - Assertions.assertEquals(this.baseItems, items.items()); - } - - @Test - public void testListSearch() - { - final var items = new JWFileList(this.choosers.filterForAllFiles()); - - items.setItems(this.baseItems); - items.setSearch("x"); - Assertions.assertEquals(List.of(this.item0), items.items()); - items.setSearch(""); - Assertions.assertEquals(this.baseItems, items.items()); - } - - @Test - public void testListFilter() - { - final var items = new JWFileList(this.choosers.filterForAllFiles()); - - items.setItems(this.baseItems); - items.setFilter(new JWFileChooserFilterType() - { - @Override - public String description() - { - return "y"; - } - - @Override - public boolean isAllowed(final Path path) - { - return Objects.equals(path.toString(), "/y"); - } - }); - - Assertions.assertEquals(List.of(this.item1), items.items()); - items.setFilter(this.choosers.filterForAllFiles()); - Assertions.assertEquals(this.baseItems, items.items()); - } - - @Test - public void testListFilterDirectories() - { - final var items = new JWFileList(this.choosers.filterForAllFiles()); - - items.setItems(this.baseItems); - items.setFilter(JWFileChooserFilterOnlyDirectories.create(this.strings)); - Assertions.assertEquals(List.of(), items.items()); - items.setFilter(this.choosers.filterForAllFiles()); - Assertions.assertEquals(this.baseItems, items.items()); - } -} diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSizeFormatterTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSizeFormatterTest.java index 7d415bd..e7df943 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSizeFormatterTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSizeFormatterTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,10 +16,26 @@ package com.io7m.jwheatsheaf.tests; +import com.io7m.jwheatsheaf.api.JWFileChooserFilterType; +import com.io7m.jwheatsheaf.api.JWFileChoosersType; +import com.io7m.jwheatsheaf.api.JWFileKind; +import com.io7m.jwheatsheaf.ui.JWFileChoosers; +import com.io7m.jwheatsheaf.ui.internal.JWFileChooserFilterOnlyDirectories; +import com.io7m.jwheatsheaf.ui.internal.JWFileItem; +import com.io7m.jwheatsheaf.ui.internal.JWFileList; +import com.io7m.jwheatsheaf.ui.internal.JWStrings; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; +import java.util.List; +import java.util.Objects; import java.util.stream.Stream; import static com.io7m.jwheatsheaf.api.JWFileChooserConfigurationDefaults.fileSizeFormatter; @@ -60,7 +76,7 @@ public Stream test_FormatSize_VariousUnits_CorrectString() { return Stream.of( testOf(1L, "1B"), - testOf(1000L, "1.00kB"), + testOf(1_000L, "1.00kB"), testOf(10_000L, "10.00kB"), testOf(100_000L, "100.00kB"), testOf(1_000_000L, "1.00MB"), @@ -75,4 +91,114 @@ public Stream test_FormatSize_VariousUnits_CorrectString() testOf(1000_000_000_000_000L, "1000.00TB") ); } + + public static final class JWFileListTest + { + private JWFileItem item0; + private JWFileItem item1; + private JWFileItem item2; + private List baseItems; + private JWStrings strings; + private JWFileChoosersType choosers; + + @BeforeEach + public void testSetup() + { + this.strings = + JWStrings.of(JWStrings.getResourceBundle()); + this.choosers = + JWFileChoosers.create(); + + this.item0 = + JWFileItem.builder() + .setPath(Paths.get("/x")) + .setModifiedTime(FileTime.fromMillis(0L)) + .setKind(JWFileKind.REGULAR_FILE) + .setSize(0L) + .build(); + this.item1 = + JWFileItem.builder() + .setPath(Paths.get("/y")) + .setModifiedTime(FileTime.fromMillis(0L)) + .setKind(JWFileKind.REGULAR_FILE) + .setSize(0L) + .build(); + this.item2 = + JWFileItem.builder() + .setPath(Paths.get("/z")) + .setModifiedTime(FileTime.fromMillis(0L)) + .setKind(JWFileKind.REGULAR_FILE) + .setSize(0L) + .build(); + + this.baseItems = + List.of(this.item0, this.item1, this.item2); + } + + @AfterEach + public void testShutdown() + throws IOException + { + this.choosers.close(); + } + + @Test + public void testListBase() + { + final var items = new JWFileList(this.choosers.filterForAllFiles()); + + items.setItems(this.baseItems); + assertEquals(this.baseItems, items.items()); + } + + @Test + public void testListSearch() + { + final var items = new JWFileList(this.choosers.filterForAllFiles()); + + items.setItems(this.baseItems); + items.setSearch("x"); + assertEquals(List.of(this.item0), items.items()); + items.setSearch(""); + assertEquals(this.baseItems, items.items()); + } + + @Test + public void testListFilter() + { + final var items = new JWFileList(this.choosers.filterForAllFiles()); + + items.setItems(this.baseItems); + items.setFilter(new JWFileChooserFilterType() + { + @Override + public String description() + { + return "y"; + } + + @Override + public boolean isAllowed(final Path path) + { + return Objects.equals(path.toString(), "/y"); + } + }); + + assertEquals(List.of(this.item1), items.items()); + items.setFilter(this.choosers.filterForAllFiles()); + assertEquals(this.baseItems, items.items()); + } + + @Test + public void testListFilterDirectories() + { + final var items = new JWFileList(this.choosers.filterForAllFiles()); + + items.setItems(this.baseItems); + items.setFilter(JWFileChooserFilterOnlyDirectories.create(this.strings)); + assertEquals(List.of(), items.items()); + items.setFilter(this.choosers.filterForAllFiles()); + assertEquals(this.baseItems, items.items()); + } + } } diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSourceEntryRecentItemsTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSourceEntryRecentItemsTest.java index 55fbb77..3c446f7 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSourceEntryRecentItemsTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileSourceEntryRecentItemsTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileWindowTitles.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileWindowTitles.java deleted file mode 100644 index cd25926..0000000 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFileWindowTitles.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright © 2021 Mark Raynsford http://io7m.com - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package com.io7m.jwheatsheaf.tests; - -import com.io7m.jwheatsheaf.api.JWFileChooserType; -import javafx.application.Platform; -import javafx.stage.Stage; -import org.junit.jupiter.api.TestInfo; - -import java.lang.reflect.Method; - -public final class JWFileWindowTitles -{ - private JWFileWindowTitles() - { - - } - - public static void setTitle( - final JWFileChooserType chooser, - final TestInfo title) - { - try { - final var field = - chooser.getClass() - .getDeclaredField("window"); - - field.setAccessible(true); - final Stage window = (Stage) field.get(chooser); - - Platform.runLater(() -> { - final var builder = new StringBuilder(); - builder.append( - title.getTestClass().map(Class::getSimpleName).orElse("")); - builder.append(":"); - builder.append( - title.getTestMethod().map(Method::getName).orElse("")); - builder.append(" ("); - builder.append(title.getDisplayName()); - builder.append(")"); - window.setTitle(builder.toString()); - }); - } catch (final IllegalAccessException | NoSuchFieldException e) { - throw new IllegalStateException(e); - } - } -} diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFilterGlobTest.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFilterGlobTest.java index 343608e..82277e5 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFilterGlobTest.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWFilterGlobTest.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWRobotDelegate.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWRobotDelegate.java deleted file mode 100644 index 2075eab..0000000 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWRobotDelegate.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright © 2020 Mark Raynsford http://io7m.com - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package com.io7m.jwheatsheaf.tests; - -import javafx.scene.Node; -import javafx.scene.control.Button; -import javafx.scene.control.TableCell; -import javafx.scene.control.TextInputControl; -import org.testfx.api.FxRobot; -import org.testfx.service.query.NodeQuery; -import org.testfx.util.WaitForAsyncUtils; - -import java.util.Objects; -import java.util.concurrent.TimeoutException; -import java.util.function.BooleanSupplier; - -import static java.util.concurrent.TimeUnit.SECONDS; - -/** - * Abstracts common unit test functionality with respect to retrieving widgets. - */ - -@SuppressWarnings("unused") -final class JWRobotDelegate -{ - private final FxRobot robot; - - JWRobotDelegate( - final FxRobot inRobot) - { - this.robot = Objects.requireNonNull(inRobot, "inRobot"); - } - - Button getOkButton() - { - return this.lookup("#fileChooserOKButton").queryButton(); - } - - TextInputControl getNameField() - { - return this.lookup("#fileChooserNameField").queryTextInputControl(); - } - - Node getSourceList() - { - return this.query(".fileChooserSourceList"); - } - - Node getDirectoryTable() - { - return this.query(".fileChooserDirectoryTable"); - } - - /** - * @param columnName One of: {@code Size}, {@code Name}, {@code Modified} - */ - - Node getTableColumn(final String columnName) - { - return this.query("#fileChooserTableColumn" + columnName); - } - - Node query(final String nodeName) - { - return this.lookup(nodeName).query(); - } - - NodeQuery lookup(final String widgetId) - { - return this.robot.lookup(widgetId); - } - - TableCell getTableCellFileName(final String text) - { - return this.robot.lookup(n -> n instanceof TableCell) - .queryAllAs(TableCell.class) - .stream() - .filter(cell -> Objects.equals(cell.getText(), text)) - .findFirst() - .orElseThrow(() -> new IllegalStateException( - String.format("Unable to locate a '%s' directory entry", text)) - ); - } - - void pauseBriefly() - { - this.robot.sleep(1L, SECONDS); - } - - /** - * Wait until the given condition is true, or until ten seconds have elapsed. - * - * @param condition The condition - * - * @throws TimeoutException If the time elapses before the condition becomes true - */ - - public void waitUntil( - final BooleanSupplier condition) - throws TimeoutException - { - WaitForAsyncUtils.waitFor(10L, SECONDS, () -> { - return Boolean.valueOf(condition.getAsBoolean()); - }); - } -} diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestDirectories.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestDirectories.java index fa9a6eb..b4d6e59 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestDirectories.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestDirectories.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestFilesystems.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestFilesystems.java index 1154ec4..d6ec743 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestFilesystems.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestFilesystems.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestUtilities.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestUtilities.java new file mode 100644 index 0000000..82129b9 --- /dev/null +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWTestUtilities.java @@ -0,0 +1,254 @@ +/* + * Copyright © 2023 Mark Raynsford https://www.io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +package com.io7m.jwheatsheaf.tests; + +import com.io7m.jwheatsheaf.api.JWFileChooserConfiguration; +import com.io7m.jwheatsheaf.api.JWFileChooserType; +import com.io7m.jwheatsheaf.api.JWFileChoosersType; +import com.io7m.jwheatsheaf.api.JWVersion; +import com.io7m.xoanon.commander.api.XCApplicationInfo; +import com.io7m.xoanon.commander.api.XCCommanderType; +import com.io7m.xoanon.commander.api.XCFXThread; +import com.io7m.xoanon.commander.api.XCRobotType; +import com.io7m.xoanon.extension.XoExtension; +import javafx.scene.control.Button; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.ListView; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableView; +import javafx.scene.control.TextField; +import javafx.stage.Stage; +import org.junit.jupiter.api.Assertions; + +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + +/** + * Assertions and functions for writing file chooser tests. + */ + +public final class JWTestUtilities +{ + private JWTestUtilities() + { + + } + + static final long TIMEOUT = 1_000L; + + static JWFileChooserType createChooser( + final JWFileChoosersType choosers, + final JWFileChooserConfiguration configuration, + final XCCommanderType commander) + throws Exception + { + final var robot = + commander.robot() + .get(TIMEOUT, MILLISECONDS); + + final var chooser = + XCFXThread.runAndWait( + TIMEOUT, MILLISECONDS, () -> choosers.create(configuration) + ); + XCFXThread.runVWait(TIMEOUT, MILLISECONDS, chooser::show); + + robot.execute(() -> chooser.stage().requestFocus()); + robot.waitUntil(TIMEOUT, () -> chooser.stage().isShowing()); + robot.waitUntil(TIMEOUT, () -> chooser.stage().isFocused()); + return chooser; + } + + static void assertIsSelected( + final JWFileChooserType chooser, + final String... selectedItems) + { + Assertions.assertEquals( + List.of(selectedItems), + chooser.result() + .stream() + .map(Path::toString) + .collect(Collectors.toList()) + ); + } + + static void assertNothingSelected( + final JWFileChooserType chooser) + { + Assertions.assertEquals( + List.of(), + chooser.result() + .stream() + .map(Path::toString) + .collect(Collectors.toList()) + ); + } + + static Button findSelectButton( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + Button.class, + window, + "fileChooserSelectDirectButton" + ); + } + + static Button findOKButton( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + Button.class, + window, + "fileChooserOKButton" + ); + } + + static Button findUpButton( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + Button.class, + window, + "fileChooserUpButton" + ); + } + + static Button findHomeButton( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + Button.class, + window, + "fileChooserHomeButton" + ); + } + + static Button findCancelButton( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + Button.class, + window, + "fileChooserCancelButton" + ); + } + + static Button findDirectoryCreateButton( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + Button.class, + window, + "fileChooserCreateDirectoryButton" + ); + } + + static ChoiceBox findPathMenu( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + ChoiceBox.class, + window, + "fileChooserPathMenu" + ); + } + + static ListView findSourceList( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + ListView.class, + window, + "fileChooserSourceList" + ); + } + + static TextField findSearchField( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + TextField.class, + window, + "fileChooserSearchField" + ); + } + + static TextField findNameField( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + TextField.class, + window, + "fileChooserNameField" + ); + } + + static TableView findDirectoryTable( + final XCRobotType robot, + final Stage window) + throws Exception + { + return robot.findWithId( + TableView.class, + window, + "fileChooserDirectoryTable" + ); + } + + static TableCell findDirectoryTableFileCell( + final XCRobotType robot, + final Stage window, + final String doc) + throws Exception + { + final var table = findDirectoryTable(robot, window); + return robot.findWithText(TableCell.class, table, doc); + } + + static void publishApplicationInfo() + { + XoExtension.setApplicationInfo(new XCApplicationInfo( + "com.io7m.jwheatsheaf", + JWVersion.MAIN_VERSION, + JWVersion.MAIN_BUILD + )); + } +} diff --git a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWWeirdStrings.java b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWWeirdStrings.java index 6630b15..bdbe412 100644 --- a/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWWeirdStrings.java +++ b/com.io7m.jwheatsheaf.tests/src/test/java/com/io7m/jwheatsheaf/tests/JWWeirdStrings.java @@ -1,5 +1,5 @@ /* - * Copyright © 2021 Mark Raynsford http://io7m.com + * Copyright © 2021 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.tests/src/test/resources/logback-test.xml b/com.io7m.jwheatsheaf.tests/src/test/resources/logback-test.xml new file mode 100644 index 0000000..9c1b757 --- /dev/null +++ b/com.io7m.jwheatsheaf.tests/src/test/resources/logback-test.xml @@ -0,0 +1,23 @@ + + + + + + jwheatsheaf: %logger{128}: %level: %msg%n + + System.err + + + + + + + + + + + diff --git a/com.io7m.jwheatsheaf.tests/src/test/resources/logback.xsd b/com.io7m.jwheatsheaf.tests/src/test/resources/logback.xsd new file mode 100644 index 0000000..d25ffa1 --- /dev/null +++ b/com.io7m.jwheatsheaf.tests/src/test/resources/logback.xsd @@ -0,0 +1,523 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.io7m.jwheatsheaf.ui/pom.xml b/com.io7m.jwheatsheaf.ui/pom.xml index 1059f15..be35767 100644 --- a/com.io7m.jwheatsheaf.ui/pom.xml +++ b/com.io7m.jwheatsheaf.ui/pom.xml @@ -9,14 +9,14 @@ com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 com.io7m.jwheatsheaf.ui com.io7m.jwheatsheaf.ui JavaFX File Chooser (UI) - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChooser.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChooser.java index 5dd2dc5..9a84ed4 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChooser.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChooser.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -72,4 +72,10 @@ public void cancel() { this.viewController.cancel(); } + + @Override + public Stage stage() + { + return this.window; + } } diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChoosers.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChoosers.java index 9bb59e7..17f064a 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChoosers.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/JWFileChoosers.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -32,10 +32,7 @@ import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.Pane; -import javafx.stage.Modality; import javafx.stage.Stage; -import javafx.stage.StageStyle; -import javafx.stage.Window; import java.io.IOException; import java.io.UncheckedIOException; @@ -44,6 +41,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import static javafx.stage.StageStyle.DECORATED; + /** * The default implementation of the {@link JWFileChoosersType} interface. */ @@ -168,10 +167,8 @@ public static JWFileChoosersType createWith( @Override public JWFileChooserType create( - final Window window, final JWFileChooserConfiguration configuration) { - Objects.requireNonNull(window, "window"); Objects.requireNonNull(configuration, "configuration"); try { @@ -198,10 +195,10 @@ public JWFileChooserType create( configuration ); - final var dialog = new Stage(((Stage) window).getStyle()); - dialog.initModality(Modality.APPLICATION_MODAL); - dialog.initStyle(StageStyle.DECORATED); + final var dialog = new Stage(DECORATED); dialog.setScene(new Scene(pane)); + dialog.initModality(configuration.modality()); + /* * Configure the title for the dialog. diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterAllFiles.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterAllFiles.java index 1c44c03..5b0c2f0 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterAllFiles.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterAllFiles.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterOnlyDirectories.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterOnlyDirectories.java index c05a20b..9e14c39 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterOnlyDirectories.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserFilterOnlyDirectories.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserViewController.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserViewController.java index eaed0ca..7791929 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserViewController.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChooserViewController.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -49,6 +49,7 @@ import javafx.scene.control.TextInputDialog; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; +import javafx.stage.Stage; import javafx.util.Callback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,7 +117,7 @@ public final class JWFileChooserViewController private JWStrings strings; private JWToolTips toolTips; private List lockableViews; - private List result; + private volatile List result; private TableView.TableViewSelectionModel directoryTableSelectionModel; private volatile Path currentDirectory; @@ -558,6 +559,7 @@ private void onSelectDirectButton() dialog.setTitle(this.strings.enterPathTitle()); dialog.setHeaderText(null); dialog.setContentText(this.strings.enterPath()); + dialog.getEditor().setId("fileChooserDialogSelectDirectTextField"); this.configuration.cssStylesheet().ifPresent(css -> { dialog.getDialogPane() @@ -650,6 +652,8 @@ private void onCreateDirectoryButton() @FXML private void onOKSelected() { + LOG.debug("ok: selected"); + this.result = List.of(); var resultTarget = List.of(); @@ -669,25 +673,24 @@ private void onOKSelected() break; } - resultTarget = - resultTarget.stream() - .filter(this::filterSelectionMode) - .collect(Collectors.toList()); - - if (!resultTarget.isEmpty()) { - final boolean confirmed; - if (this.isFileSelectionConfirmationRequired()) { - confirmed = this.confirmFileSelection(resultTarget); - } else { - confirmed = true; - } + final boolean confirmed; + if (this.isFileSelectionConfirmationRequired()) { + confirmed = this.confirmFileSelection(resultTarget); + } else { + confirmed = true; + } - if (confirmed) { - this.result = resultTarget; - final var window = this.mainContent.getScene().getWindow(); - window.hide(); - } + if (!confirmed) { + LOG.trace("ok: confirmation failed"); + return; } + + this.result = resultTarget; + final var window = + (Stage) this.mainContent.getScene().getWindow(); + + LOG.trace("ok: hiding window"); + window.close(); } /** diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChoosersTestingType.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChoosersTestingType.java index b0e3c67..5d4cdb3 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChoosersTestingType.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileChoosersTestingType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileImageDefaultSet.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileImageDefaultSet.java index 6026537..c950c1c 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileImageDefaultSet.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileImageDefaultSet.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableNameCell.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableNameCell.java index a7b842f..c250f88 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableNameCell.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableNameCell.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableSizeCell.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableSizeCell.java index 60e4f43..7830a19 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableSizeCell.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableSizeCell.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTimeCell.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTimeCell.java index 3d68a43..295f221 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTimeCell.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTimeCell.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTypeCell.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTypeCell.java index d704dc6..226cee3 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTypeCell.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemTableTypeCell.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemType.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemType.java index e608ccd..30ddc05 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemType.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItemType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItems.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItems.java index 9514368..5320374 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItems.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileItems.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileList.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileList.java index 3d513b9..5b6fd1d 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileList.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileList.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileListingRetrieverType.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileListingRetrieverType.java index f04154b..091159a 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileListingRetrieverType.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileListingRetrieverType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryFilesystemRoot.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryFilesystemRoot.java index bdb8f87..5c9d8fa 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryFilesystemRoot.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryFilesystemRoot.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryRecentItems.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryRecentItems.java index 934f486..77f2166 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryRecentItems.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryRecentItems.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryType.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryType.java index d4144fe..6c3191c 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryType.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileSourceEntryType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileTimeFormatterType.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileTimeFormatterType.java index 7970041..6d408f2 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileTimeFormatterType.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWFileTimeFormatterType.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWImages.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWImages.java index 500159f..11ebb1e 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWImages.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWImages.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWStrings.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWStrings.java index b640ade..d845555 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWStrings.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWStrings.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWToolTips.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWToolTips.java index 5e6c6ca..ca150fd 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWToolTips.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/JWToolTips.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/package-info.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/package-info.java index 00de113..6f1a34c 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/package-info.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/internal/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/package-info.java b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/package-info.java index ad8efaf..ae11ddd 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/package-info.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/com/io7m/jwheatsheaf/ui/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,7 +19,7 @@ */ @Export -@Version("2.1.0") +@Version("4.0.0") package com.io7m.jwheatsheaf.ui; import org.osgi.annotation.bundle.Export; diff --git a/com.io7m.jwheatsheaf.ui/src/main/java/module-info.java b/com.io7m.jwheatsheaf.ui/src/main/java/module-info.java index 9836d20..7560763 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/java/module-info.java +++ b/com.io7m.jwheatsheaf.ui/src/main/java/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Mark Raynsford http://io7m.com + * Copyright © 2020 Mark Raynsford https://www.io7m.com * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/com.io7m.jwheatsheaf.ui/src/main/resources/com/io7m/jwheatsheaf/ui/internal/Strings.properties b/com.io7m.jwheatsheaf.ui/src/main/resources/com/io7m/jwheatsheaf/ui/internal/Strings.properties index d120779..3cd2f1c 100644 --- a/com.io7m.jwheatsheaf.ui/src/main/resources/com/io7m/jwheatsheaf/ui/internal/Strings.properties +++ b/com.io7m.jwheatsheaf.ui/src/main/resources/com/io7m/jwheatsheaf/ui/internal/Strings.properties @@ -1,5 +1,5 @@ # -# Copyright © 2020 Mark Raynsford http://io7m.com +# Copyright © 2020 Mark Raynsford https://www.io7m.com # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above diff --git a/pom.xml b/pom.xml index 45e1940..3f7a384 100644 --- a/pom.xml +++ b/pom.xml @@ -10,17 +10,17 @@ com.io7m.primogenitor com.io7m.primogenitor.full - 6.4.2 + 7.7.0 com.io7m.jwheatsheaf com.io7m.jwheatsheaf - 3.0.0 + 4.0.0-beta0001 pom com.io7m.jwheatsheaf JavaFX File Chooser - http://github.com/io7m/jwheatsheaf + https://www.io7m.com/software/jwheatsheaf 2020 @@ -35,17 +35,17 @@ - b0ab224c1aa641afbe9d0d34b1f60f1d - 2.8.3 - 2.0.0 - 16 - 4.0.16-alpha + 2.9.3 + 1.0.0-beta0001 + 3.0.0 + 20.0.1 + 5.9.3 - ISC License - http://io7m.com/license/isc.txt + ISC + https://www.io7m.com/license/isc.txt @@ -60,7 +60,7 @@ io7m io7m code@io7m.com - http://io7m.com + https://www.io7m.com @@ -72,7 +72,7 @@ - http://github.com/io7m/jwheatsheaf/issues + https://github.com/io7m/jwheatsheaf/issues GitHub Issues @@ -84,11 +84,11 @@ sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ sonatype-nexus-snapshots - https://oss.sonatype.org/content/repositories/snapshots/ + https://s01.oss.sonatype.org/content/repositories/snapshots/ @@ -112,12 +112,12 @@ com.io7m.jaffirm com.io7m.jaffirm.core - 3.0.1 + 4.0.0 com.io7m.junreachable com.io7m.junreachable.core - 3.0.0 + 4.0.0 org.openjfx @@ -142,12 +142,12 @@ org.osgi org.osgi.annotation.bundle - 1.1.0 + 2.0.0 org.osgi org.osgi.annotation.versioning - 1.1.1 + 1.1.2 org.quicktheories @@ -157,62 +157,72 @@ nl.jqno.equalsverifier equalsverifier - 3.1.12 + 3.14.1 org.jgrapht jgrapht-core - 1.4.0 + 1.5.2 org.slf4j slf4j-api - 2.0.0-alpha1 + 2.0.7 ch.qos.logback logback-classic - 1.3.0-alpha4 + 1.4.7 org.junit.jupiter junit-jupiter-api - 5.6.0 + ${junit.version} org.junit.jupiter junit-jupiter-engine - 5.6.0 + ${junit.version} org.mockito mockito-core - 3.3.0 + 5.3.1 com.github.marschall memoryfilesystem - 2.1.0 + 2.6.1 - org.testfx - testfx-junit5 - ${testfx.version} + com.io7m.primogenitor + com.io7m.primogenitor.support + 7.7.0 - org.testfx - testfx-core - ${testfx.version} + com.io7m.percentpass + com.io7m.percentpass.extension + 0.0.3 - com.io7m.primogenitor - com.io7m.primogenitor.support - 6.4.2 + com.io7m.xoanon + com.io7m.xoanon.extension + ${com.io7m.xoanon.version} + + + + com.io7m.stmp + string-template-maven-plugin + 1.2.0 + + + + @@ -229,12 +239,6 @@ - - - org.apache.maven.plugins - maven-checkstyle-plugin - - com.io7m.minisite diff --git a/src/site/resources/features.xml b/src/site/resources/features.xml index d8c1c96..797038f 100644 --- a/src/site/resources/features.xml +++ b/src/site/resources/features.xml @@ -7,7 +7,7 @@
  • Directory creation.
  • Configurable, extensible file/directory filtering.
  • Simple case-insensitive directory searching.
  • -
  • Written in pure Java 11.
  • +
  • Written in pure Java 17.
  • OSGi-ready
  • JPMS-ready
  • ISC license
  • diff --git a/src/site/resources/icon.png b/src/site/resources/icon.png index 1d6e2a6..7d029a8 100644 Binary files a/src/site/resources/icon.png and b/src/site/resources/icon.png differ diff --git a/src/site/resources/jwheatsheaf.jpg b/src/site/resources/jwheatsheaf.jpg index 1a8f4fa..36d39b8 100644 Binary files a/src/site/resources/jwheatsheaf.jpg and b/src/site/resources/jwheatsheaf.jpg differ diff --git a/src/site/resources/overview.xml b/src/site/resources/overview.xml index 49c0ee7..0fc70fd 100644 --- a/src/site/resources/overview.xml +++ b/src/site/resources/overview.xml @@ -1,15 +1,15 @@