Rsclub2_2andClaude Opus 5.5 4b10d96091 Compose screen tests with runComposeUiTest (#107) (#125)
* test: draw and click the in-window menu row (#107)

Pins what MainMenuModelTest cannot see: every item picked through the
drawn row runs its own action, the enabled states and the away and
window-toggle labels follow their state while the menu is down, and a
palette or language change reaches the row on screen.

Named regressions: fe4215bc (menu actions hung on deleted JavaFX
MenuItems) and 83e23f55 (unthemed Swing menu bar), both in main as
2a5c89b9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: draw the station list with its real row key (#107)

The station row key moves from an inline Java lambda into
StationColumns.rowKey, unchanged in its text, so the list can be tested
with the key the application really uses.

The screen test pins three regressions on the drawn table: the same
callsign in two categories collided under one key and sorting dropped
the filters (both 21251377), and the AP column sorted by its text
(ab282162, #87). It also pins that rows replaced after the first draw
reach the screen and that the selection follows a station by key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: draw the monitor window's live tables (#107)

MonitorContent becomes internal so its body can be drawn headless.

The screen test pins the defects the port shipped in this window
(cc8c9020, in main as 2a5c89b9): rows arriving while the window is
open, also after a redraw that was not about the rows, must reach both
tables, and two messages that read alike stay two rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: draw and click the station map window's body (#107)

StationMapWindow.show now hands its body to an internal Content
composable that takes the tile fetcher, the member roster and the map
state as parameters, with the old inline values as defaults, and the
map canvas carries a test tag.

The screen test pins the map selection fixed in 21251377: a marker
click and Reset view go through the central station selector, a click
keeps the category variant already selected and prepares "/cq CALL",
and neither changes the zoom. The header switches write the profile.
Tiles never arrive: an empty temporary cache and a failing source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: draw the Station, Log synch, TRX synch and Airscout tabs (#107)

Each tab is composed headless and checked for its sections and key
controls, and editing a control through the drawn form must write
through to ChatPreferences and redraw. Refused entries stay on screen
as typed and leave the stored value alone. A small helper finds a
control by the label beside it, the way the operator finds it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: draw the Message handling, GUI, Beacon and Notification tabs (#107)

Each tab is composed headless with its sections and key controls, and
edits through the drawn controls reach ChatPreferences and the
application callbacks: the auto answer for both categories, the
debug-to-file switch c8ce0e98 restored, the startup design and the
language, the beacon templates and interval, the cluster server, the
fallback band, the test spot and the monitored callsign dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: draw the Shortcuts and Worked database tabs (#107)

The shortcut and snippet lists show what the profile holds, and an edit
or an added entry made in the drawn list reaches the roster and the
refresh hook the button row depends on (the hook that was called into
thin air before fe4215bc). The worked database lists its rows, re-reads
them on refresh, asks before a reset and leaves the lists alone when
the database reset fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: draw the Profiles and Colours tabs (#107)

Profiles: the default profile and every action are on screen, deleting
it is refused after the confirmation, a cancelled New dialog creates
nothing, and switching hands the selected profile to the application.
Only a temporary registry is touched.

Colours: the six roles show the resolved colour, a typed colour is
committed into the store, a mistyped one is refused and put back, the
shipped reset undoes a change, and the stylesheet export writes once
into a temporary profile directory and never over an existing file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor: give the map's path analysis a seam and tag the monitoring field (#107)

StationMapWindow.Content takes a MapPathAnalysis supplier. The default
looks the running application's reachability service up on every
selection, exactly as the inline chat-controller lookup did, and null
still means: no pan, no analysis. This lets a test run the zoom rule
on selection that cc8c9020 fixed.

The callsign field of the add-to-monitoring dialog in NotificationTab
carries a test tag, so a test types into it by name rather than by
position.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: isolate and harden the screen tests after review (#107)

- No screen test builds ChatPreferences() any more: that constructor
  resolves the real user profile and seeds preferences.xml there. Each
  class uses ChatPreferences(Path) under a @TempDir.
- Compose state changed from the test thread (roster refresh, language
  reset) goes through runOnIdle.
- Dialogs and dropdowns are waited for with waitUntil and found inside
  their overlay (isDialog / isPopup) instead of by tree order; the
  monitored-callsign field is found by its test tag.
- The menu test now asserts Disconnect when online and Connect when
  offline instead of skipping one.
- The map test runs the zoom-on-selection rule through the new seam,
  closes its tile fetcher after each test and keeps its cache in the
  @TempDir.
- StationColumns.rowKey is pinned directly: two categories, two keys.
- The menu colour is sampled further inside the row, and the station
  list click picks its row by position.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: prove the map's selection effect ran when no analysis is available (#107)

Review follow-up. The no-analysis test only asserted that the map stayed
put, which would also hold if the selection effect never ran; it now
counts the analysis lookup. The effect reads the lookup through
rememberUpdatedState, so a caller passing a new lambda is not served a
stale one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 10:21:14 +02:00
2023-11-10 08:33:17 +01:00
2026-10-08 23:22:11 +02:00
2026-10-08 23:22:11 +02:00
2024-01-16 22:51:30 +01:00
2023-11-09 22:53:59 +01:00
2023-11-14 00:50:10 +01:00
2023-11-10 08:33:17 +01:00

KST4Contest

KST4Contest is a Java-based client for the ON4KST chat, developed for coordinated VHF, UHF and microwave contest operation.

The application is developed by Marc Fröhlich (DO5AMF) and since 2026 Philipp Wagner (DN9APW).

Start here

What KST4Contest does

KST4Contest combines the ON4KST chat with information that is useful when coordinating contacts during a contest.

Among other things, it can:

  • display and filter stations from the supported ON4KST chat categories;
  • derive band and frequency information from chat messages and station names;
  • maintain Worked and NOT QRV information for the available bands;
  • calculate station priorities from distance, activity and other available information;
  • manage internal skeds and received Win-Test skeds;
  • use AirScout information when evaluating possible aircraft-scatter contacts;
  • display stations, paths and additional propagation information on maps;
  • exchange information with supported logging programs, Win-Test, PSTRotator and a local DX Cluster interface;
  • provide configurable automatic replies for recurring chat requests.

Calculated scores, aircraft-scatter information and path assessments are operating aids. They depend on the available data and should not be treated as guarantees that a contact is possible.

Installation

Ready-to-use packages are available for Windows, Linux and macOS. These packages include the required Java runtime, so a separate Java installation is normally not necessary.

Use the central download page to select the appropriate build:

  • Stable is intended for normal contest operation.
  • Beta contains changes that are being prepared for a stable release.
  • Nightly contains the latest automated development build and is mainly intended for testing.

Open the download page

Documentation

The documentation is available in German and English:

The Markdown sources used for the wiki and the generated PDF manuals are stored in github_docs.

Changes to operating behaviour should be documented together with their purpose and limitations. This is especially important for functions whose result depends on external data, heuristics or information derived from chat messages.

Building from source

Building KST4Contest requires JDK 21. The Gradle Wrapper included in the repository should be used, so a separate Gradle installation is not required.

Linux and macOS:

./gradlew clean build

Windows:

.\gradlew.bat clean build

Repository structure

  • core/ – domain, controller and network code, free of user-interface technology
  • app-desktop/ – the Compose Multiplatform user interface and the packaging tasks
  • github_docs/ – German and English manual sources
  • website/ – project website sources
  • packaging/ – platform-specific packaging files

CI status

Documentation

Publish wiki

Docs PDF

Builds

Nightly Runtime Artifacts

License

KST4Contest is distributed under the GNU General Public License v3.0.

Supporters/Sponsor

This Project is possible due to donations of the community.

You can sponsor KST4Contest here: Support on Ko-Fi. If you add an Display Name there you will be mentioned here.

The following people are sponsoring KST4Contest:

  • Marco (DJ5KW)
S
Description
No description provided
Readme GPL-3.0
1 GiB
0 Stars 1 Watchers 0 Forks
Languages
Java 54%
Kotlin 36.3%
JavaScript 5%
Nunjucks 1.8%
CSS 0.9%
Other 2%