browser

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2025 License: MIT Imports: 8 Imported by: 0

README

Gost-DOM - A headless browser for Go

The Go-to headless browser for TDD workflows.

Gost-DOM is a headless browser written in Go intended to write tests of web application in Go that relies on JavaScript. Properties of Gost-DOM-based tests:

  • Tests run in parallel due to complete complete isolation[^1]
  • No erratic behaviour due to 100% predictable UI reactions.
  • "Blazingly fast". No out-of-process calls, not even thread boundaries for web API calls. Web application code runs in the test thread, so a panic in your code keeps a full stack trace to the test case. [^2]
  • Dependencies can be replaced while testing.

Yet Gost-DOM still uses HTTP request and responses for verification, testing the entire stack, as well as middlewares.

of usage.

[!NOTE]

This is 0.x version still, and breaking API changes do occur, but will be announced before release in the Gost-DOM discussions (do say Hi! 👋)

Looking for sponsors

This tool has reached a level where it can be used to test some web applications with JavaScript, e.g., simple HTMX applications. But there is still a lot to build to support just the most relevant Web APIs.

I've made good progress because of too much spare time; but that will not last. If I could find enough sponsors, it could mean the difference between continued development, or death 😢

For companies wanting to sponsor, I can send formal invoices too. More information on the project's Sponsor page

Getting started

Project status

This is still in an early phase, but it's approaching a design that seems promising for the purpose.

At the moment there's an emphasis on high-risk features that can expose poor design choices, but the "primary API" has been reasonably stable for a good amount of time.

Upcoming work

The near-future work is prioritised around

  • Provide distinct error messages when using unsupported JS functions
  • Improving fetch implementation
  • Fix incorrectly implemented features
  • Simulate user interaction, such as typing
Notify when using unsupported JS functions

Most of the JS mapping layer is auto-generated, including operations and attribute getter/setters that are not yet supported. This generates explicit error messages in the callback functions, making it clear when using, that the failed test case is caused by lack of support in Gost-DOM - not a bug in your code.

This should be improved further - including when calling functions accepting an options object, and clien code pass a valid, but unsupported option.

Implement more of fetch

The current fetch implementation is extremely basic, having only support for simple GET requests.

This will be improved in the future for more advanced scenarios, including correct headers support, cookies, body - including streaming response bodies, etc.

Fix incorrectly implemented features

Many of the already implemented features or APIs are not completely implemented, a few examples.

  • Assigning to the history doesn't navigate
  • Live collections are not live.
  • Submit buttons cannot override form method and action.

To give users a better chance of predicting what works, and what doesn't, it is an aim to make sure that existing features work as they would in a real browser.

Future goals

There is much to do, which includes (but this is not a full list):

  • Support web-sockets and server events.
  • Implement all standard JavaScript classes that a browser should support; but not part of the ECMAScript standard itself.
    • JavaScript polyfills would be a good starting point; which is how xpath is implemented at the moment.
      • Conversion to native go implementations would be prioritized on usage, e.g. fetch would be high in the list of priorities.
  • Implement default browser behaviour for user interaction, e.g. pressing enter when an input field has focus should submit the form.
Pure Go script engine

V8 is a "feature complete" JavaScript environment, so V8 support will never go away. But it has some overhead, and it depends on Cgo. Also, the current V8 layer leaks memory in the scope of a browsing context.

Goja is a pure Go JavaScript engine, and is alsmost fully supported as an alternative. JavaScript bindings in code target a layer of abstraction, allowing the script engine to be replaced.

CSS Parsing

Parsing CSS woule be nice, allowing test code to verify the resulting styles of an element; but having a working DOM with a JavaScript engine is higher priority.

Mock external sites

The system may depend on external sites in the browser, most notably identity providers (IDP), where your app redirects to the IDP, which redirects on successful login; but could be other services such as map providers, etc.

For testing purposes, replacing this with a dummy replacement would have some benefits:

  • The verification of your system doesn't depend on the availability of an external service; when working offline
  • Avoid tests breaking due to a new UI in your external dependency.
  • For an identity provider
    • Avoid pollution of dummy accounts to run your test suite.
    • Avoid locking out test accounts due to "suspiscious activity".
    • The IDP may use a Captcha or 2FA that can be impossible; or difficult to control from tests, and would cause a significant slowdown to the test suite.
  • For applications like map providers
    • Avoid being billed for API use during testing.

Out of scope.

Full Spec Compliance

A goal is not always meant to be reached, it often serves simply as something to aim at.

  • Bruce Lee

While it is a goal to reach whatwg spec compliance, the primary goal is to have a useful tool for testing modern web applications.

Some specs don't really have any usage in modern web applications. For example, you generally wouldn't write an application that depends on quirks mode.

Another example is document.write. I've yet to work on any application that depends on this. However, implementing support for this feature require a complete rewrite of the HTML parser. You would need a really good case (or sponsorship level) to have that prioritised.

Accessibility tree

It is not currently planned that this library should maintain the accessibility tree; nor provide higher level testing capabilities like what Testing Library provides for JavaScript.

These problems should eventually be solved, but could easily be implemented in a different library with dependency to the DOM alone.

Visual Rendering

It is not a goal to be able to provide a visual rendering of the DOM.

But just like the accessibility tree, this could be implemented in a new library depending only on the interface from here.

Terminology

Some words inherntly have multiple meanings.

  • Interface. The IDL Specification defines interfaces; which are exposed in certain scopes, implemented by "classes" in JavaScript.
    • The interfaces can be composed of partial or mixin interfaces.
    • IDL Interfaces and mixin interfaces are represented in Go, and typically exposed as Go interface types.

Attribution / 3rd party included code.

Some web APIs are implemented by embedding polyfills from other open-source JavaScript libraries.


[^1]: Complete isolation depends on your code, e.g., if you don't replace database dependencies, they are not isolated. [^2]: This depends on how you configure Gost-DOM.

Documentation

Overview

Package browser is the main entry point for Gost, helping create a window initialized with a script enging, connected to a server.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Browser

type Browser struct {
	Client     http.Client
	ScriptHost ScriptHost
	Logger     log.Logger
	// contains filtered or unexported fields
}

Pretty stupid right now, but should _probably_ allow handling multiple windows/tabs. This used to be the case for _some_ identity providers, but I'm not sure if that even work anymore because of browser security.

func New

func New(options ...BrowserOption) *Browser

New initialises a new Browser with the default script engine.

func NewBrowser deprecated

func NewBrowser() *Browser

Deprecated: NewBrowser should not be called. Call New instead.

This method will selfdestruct in 10 commits

func NewBrowserFromHandler deprecated

func NewBrowserFromHandler(handler http.Handler) *Browser

Deprecated: NewBrowserFromHandler should not be called, call, NewFromHandler instead.

This method will selfdestruct in 10 commits

func NewFromHandler deprecated

func NewFromHandler(handler http.Handler) *Browser

NewFromHandler initialises a new Browser with with an http.Handler

Deprecated: Prefer browser.New(browser.WithHandler(...)) instead.

func (*Browser) Close

func (b *Browser) Close()

func (*Browser) Closed added in v0.8.0

func (b *Browser) Closed() bool

func (*Browser) NewWindow added in v0.5.1

func (b *Browser) NewWindow() Window

NewWindow creates a new window. Panics if the browser has been closed

func (*Browser) Open

func (b *Browser) Open(location string) (window Window, err error)

Open will open a new html.Window, loading the specified location. If the server does not respons with a 200 status code, an error is returned.

See html.NewWindowReader about the return value, and when the window returns.

type BrowserOption added in v0.5.1

type BrowserOption func(*browserConfig)

func WithContext added in v0.8.0

func WithContext(ctx context.Context) BrowserOption

func WithHandler added in v0.5.1

func WithHandler(h http.Handler) BrowserOption

WithHandler configures the browser's http.Client to use an http.Roundtripper that bypasses the TCP stack and calls directly into the specified handler as a normal function call.

Note: There is a current limitation that NO requests from the browser will be sent when using this. So sites will not work if they

  • Depend on content from CDN
  • Depend on an external service, e.g., an identity provider.

That is a limitation that was the result of prioritising more important, and higher risk features.

func WithLogger added in v0.5.1

func WithLogger(l *slog.Logger) BrowserOption

func WithScriptHost added in v0.8.0

func WithScriptHost(host html.ScriptHost) BrowserOption

Directories

Path Synopsis
browser module
dom
Package dom provides the fundamental DOM implementation for Gost-DOM.
Package dom provides the fundamental DOM implementation for Gost-DOM.
event
Package event contains core browser event behavior
Package event contains core browser event behavior
Package html works on top of the DOM to implement specific HTML elements.
Package html works on top of the DOM to implement specific HTML elements.
input
controller
Package controller can simulate user interaction
Package controller can simulate user interaction
key
Package key represents keys on the keyboard that the user might type.
Package key represents keys on the keyboard that the user might type.
internal
clock
Package clock provides a simulated time for Gost-DOM.
Package clock provides a simulated time for Gost-DOM.
constants
Package constants is a collection of values that are used many times in the implementation, but has no relevance to users of the library, e.g., a link to where you can file an issue when you encounter a not-implemented feature; or a feature that is not fully implemented, e.g.
Package constants is a collection of values that are used many times in the implementation, but has no relevance to users of the library, e.g., a link to where you can file an issue when you encounter a not-implemented feature; or a feature that is not fully implemented, e.g.
dom
gosthttp
Package gosthttp provides functionality to bypass the TCP stack.
Package gosthttp provides functionality to bypass the TCP stack.
interfaces
Package interfaces contains go interfaces generated from IDL specs
Package interfaces contains go interfaces generated from IDL specs
interfaces/html-interfaces
Package htmlinterfaces contains internal code representing the IDL interfaces in the HTML DOM API [HTML DOM API]: https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API
Package htmlinterfaces contains internal code representing the IDL interfaces in the HTML DOM API [HTML DOM API]: https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API
interfaces/url-interfaces
Package urlinterfaces contains internal code representing the IDL interfaces in the URL API [URL API]: https://developer.mozilla.org/en-US/docs/Web/API/URL_API
Package urlinterfaces contains internal code representing the IDL interfaces in the URL API [URL API]: https://developer.mozilla.org/en-US/docs/Web/API/URL_API
log
Package log contains functions used internally for logging to a default logger implementing slog.Logger.
Package log contains functions used internally for logging to a default logger implementing slog.Logger.
monads/result
package result provides monadic result binding
package result provides monadic result binding
promise
Package promise provides a Go way to represent the concept of a Promise.
Package promise provides a Go way to represent the concept of a Promise.
test/scripttests
Package scripttests contains a specification of the behaviour of client-side scripting.
Package scripttests contains a specification of the behaviour of client-side scripting.
testing/gomega-matchers
Package gomegamatchers just exposes gomega matchers for easier importing.
Package gomegamatchers just exposes gomega matchers for easier importing.
testing/htmltest
Package htmltest contains test helpers when working with the html package
Package htmltest contains test helpers when working with the html package
uievents
Package uievents creates and dispatches [UI Events].
Package uievents creates and dispatches [UI Events].
Package logger provides the basic functionality of supplying a custom logger.
Package logger provides the basic functionality of supplying a custom logger.
scripting
gojahost
The gojahost package provides functionality to execute client-scripts in gost-dom.
The gojahost package provides functionality to execute client-scripts in gost-dom.
internal/js
Package js provides an abstraction on top of V8.
Package js provides an abstraction on top of V8.
v8host
The v8host packages provides functionality to execute client-side scripts in gost-dom.
The v8host packages provides functionality to execute client-side scripts in gost-dom.
testing
gomega-matchers
Package matchers contains custom matches for use with the [Gomega] assertion library.
Package matchers contains custom matches for use with the [Gomega] assertion library.
Package url contains types defined in the url web IDL spec.
Package url contains types defined in the url web IDL spec.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL