Skip to content

GenieFramework/GenieTest.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GenieTest

A Julia package for testing Stipple/Genie applications with integrated frontend support.

Overview

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 App consists 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 @in are 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.myfield or app.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 define model = app.__model__ and continue with standard syntax for model This syntax is still in development and can be changed in future versions.

Features

  • 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

Installation

using Pkg
Pkg.develop(path="path/to/GenieTest")

Usage

Basic Example

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)

Creating Apps

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. MyApp
  • context: Module name in which an implicit model is defined, e.g. Main or @__MODULE__

Keyword Arguments:

  • timeout: Seconds to wait for backend readiness (default: 10)
  • port: Server port (default: uses Genie.config.server_port)
  • id: Debug ID for identifying the Stipple model
  • frontend: Frontend type - :browser, :electron, or :none
  • backend: Whether to start the backend model (default: !startswith(url, r"https://"i))
  • isready: Function to check app readiness (default: app -> app.isready === true)

Frontend Options

# 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)

Utility Functions

wait_for

Wait for a condition to become true with timeout:

result = wait_for(timeout = 10, delay = 1) do
    app.some_property[] == expected_value
end

notify_test

Send test result notifications to the model:

using Test
result = @test app.value == 42
notify_test(model, result, "Value Check")

Dependencies

  • 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

Remarks

  • 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.)

License

See LICENSE for details.

Author

Helmut Hänsel helmut.haensel@gmx.de

About

Testing of GenieFramework apps both local and remote

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages