A Julia package for testing Stipple/Genie applications with integrated frontend support.
GenieTest provides utilities for creating and testing Stipple-based web applications with both backend (Genie/Stipple reactive models) and frontend (browser or Electron) components. It simplifies the process of launching test applications and verifying their behavior.
For this purpose we introduce GenieTest.App that behaves very much like a ReactiveModel with some subtle differences.
- An
Appconsists of the two fields__model__and__window__, which optionally contain a ReactiveModel (backend) and an Electron window (frontend) - Values are retrieved from the model, if available, or from the Electron window as a fallback. In the latter case only public fields are accessible and only fields declared with
@inare sent to the backend. - The model fields are available via dot syntax as usual.
- CAVEAT: The dot syntax always returns values and not Reactive variables. The reason is that the syntax should be identical independent whether we work with fronend or backend. Assignments are nevertheless reactive, e.g.
x = app.myfieldorapp.myfield = "newvalue"will trigger reactive updates. - Silent updates are only possible if a model is available and can be written as
app[:myfield] = "silent update. But in most cases you will better definemodel = app.__model__and continue with standard syntax formodelThis syntax is still in development and can be changed in future versions.
- Flexible App Creation: Launch Stipple apps with configurable frontend and backend options
- Multiple Frontend Options: Support for browser, Electron, or headless (no frontend) modes
- Backend Integration: Automatic connection to Stipple reactive models with timeout handling
- Property Access: Convenient dot notation access to reactive model properties
- Testing Utilities: Helper functions for waiting and notifications in tests
using Pkg
Pkg.develop(path="path/to/GenieTest")using Stipple, Stipple.ReactiveTools, StippleUI
using GenieTest
@app begin
@in x = "World"
@onchange x @info "new x: $x"
@onchange isready @info "Ready!"
end
@page "/" [htmldiv("Hello"), textfield("", :x)]
# Create an app with browser frontend, wait for the model to be ready
app = GenieTest.App("/")
# Access reactive model properties
@show app.x
# Set reactive model properties
app.x = "John"
sleep(3)
# Close the app
close(app)The App constructor provides several configuration options:
App(url::String = "/";
timeout::Int = 10,
port = nothing,
id::String = string(uuid4()),
frontend::Symbol = :browser,
backend::Bool = true,
isready::Function = app -> app.isready === true
)
App(T::Type{ReactiveModel}; kwargs...)
App(context::Module; kwargs)Arguments:
url: URL to open (default:"/"). Automatically prefixes with localhost if needed.T: explicit ReactiveModel, e.g.MyAppcontext: Module name in which an implicit model is defined, e.g.Mainor@__MODULE__
Keyword Arguments:
timeout: Seconds to wait for backend readiness (default: 10)port: Server port (default: usesGenie.config.server_port)id: Debug ID for identifying the Stipple modelfrontend: Frontend type -:browser,:electron, or:nonebackend: Whether to start the backend model (default:!startswith(url, r"https://"i))isready: Function to check app readiness (default:app -> app.isready === true)
# Open in default browser
app = App("/", frontend = :browser)
# Open in Electron window
app = App("/", frontend = :electron)
# No frontend (headless mode)
app = App("/", frontend = :none, backend = true)
# Frontend only (connect to remote backend)
app = App("https://remote-server.com", backend = false)Wait for a condition to become true with timeout:
result = wait_for(timeout = 10, delay = 1) do
app.some_property[] == expected_value
endSend test result notifications to the model:
using Test
result = @test app.value == 42
notify_test(model, result, "Value Check")- Genie: Web framework
- Stipple: Reactive UI framework
- Electron: Desktop application framework
- HTTP: HTTP client/server
- Test: Julia's testing framework
- TestItemRunner: Test execution
- UUIDs: Unique identifier generation
- For local testing, the standard browser is probably the best choice. For remote testing Electron must be used, as the standard browser cannot be addressed via JavaScript from the test suite.
- If you need to evaluate Javascript expressions in the frontend and send them to the backend, Electron is currently more convenient.
- On MacOS Passkeys are, unfortunately, not supported via Electron. (If anyone has a good idea how to get around that limitation, feel welcome to open an issue.)
See LICENSE for details.
Helmut Hänsel helmut.haensel@gmx.de