Skip to content

UI Test

Lauri Rooden edited this page Feb 20, 2026 · 1 revision

UI Testing

ui-test.js extends the test framework with browser assertions for testing LiteJS UI applications. It adds chainable methods to assert that poll the DOM until conditions are met or timeout is reached.

Setup

Load test.js and ui-test.js after LiteJS in an HTML page:

<script type="ui">
%view home #
  h1 Hello
%start
</script>
<script src="litejs-full.js"></script>
<script src="test.js"></script>
<script src="ui-test.js"></script>
<script>
describe.onend = function() {
	document.getElementById("out").textContent = describe.output
}
</script>
<script src="my-tests.js"></script>

Running

Open the HTML page in a browser or run with lj ui-test:

lj ui-test                          # default: test/index.html on :8091
lj ui-test my-page.html             # custom URL path
lj ui-test --port=3000 --budget=10000  # custom port and timeout

This starts a local server, finds an available browser (Chrome/Chromium), runs it headless, and exits 0 on pass or 1 on failure. The port auto-increments if already in use.

Navigation

  • assert.open(url[, replace]) - Navigate to route via LiteJS.go().
  • assert.waitView(route[, options]) - Poll until LiteJS.ui.route matches.
  • assert.waitSelector(sel[, options]) - Poll until selector is in DOM.

DOM Assertions

All methods poll every 50ms until the condition is met or describe.conf.timeout is reached.

  • assert.hasText(sel, expected[, options]) - Poll until element text matches.
  • assert.hasElements(sel, expected[, options]) - Poll until element count matches.
  • assert.fill(sel, value[, options]) - Set input value.
  • assert.click(sel[, options]) - Poll until element is found, then dispatch click.

Async Control

  • assert.wait() - Queue all subsequent method calls. Returns a resume function that restores methods and replays the queue. Used internally by waitFor.
  • assert.waitFor(fn[, options]) - Poll fn every 50ms until truthy, then resume. All chainable methods use this internally.

Layout

  • assert.resizeTo(width, height) - Resize viewport and emit resize event.
  • assert.isVisible(el) - Assert element has non-zero dimensions.

CSS Coverage

Track which CSS rules are exercised during test navigation.

  • assert.collectCssUsage([options]) - Parse stylesheets and start counting selector matches on every view show. Options: ignoreFiles (array), ignoreSelectors (array).
  • describe.unusedCss() - Return array of unused selectors. Available for build tools to consume.
  • assert.assertCssUsage() - Assert no unused selectors remain.
describe("app", function() {
	it("should set up tracking", function(assert) {
		assert.collectCssUsage({
			ignoreSelectors: ["*:before", "*:after"]
		})
		assert.end()
	})

	// ... navigation tests that visit all views ...

	it("should use all css rules", function(assert) {
		assert.assertCssUsage()
	})
})

View Coverage

Track which views are visited during tests.

  • assert.collectViewsUsage() - Start tracking view show events.
  • describe.unusedViews() - Return array of unused view routes.
  • assert.assertViewsUsage() - Assert all defined views were shown.

Example

describe("ui-test.js", function() {
	it("should render home view", function(assert) {
		assert
		.open("")
		.waitView("home")
		.hasText("h2", "Welcome")
		.end()
	})

	it("should navigate to about", function(assert) {
		assert
		.click('a[href="#about"]')
		.waitView("about")
		.hasText("h2", "About")
		.hasElements("ul > li", 3)
		.end()
	})

	it("should interact with counter", function(assert) {
		assert
		.click('a[href="#counter"]')
		.waitView("counter")
		.hasText(".count", "Count: 0")
		.click("#btn-inc")
		.hasText(".count", "Count: 1")
		.end()
	})
})

Clone this wiki locally