Extractors #

In order to describe a condition about the web page you’re testing, you first need to extract state. This is done with the extract function, which runs inside the browser on every state that Bombadil decides to capture.

extract(state => ...)

You give it a function that takes the current browser state as an argument, and returns JSON-serializable data. The state object contains a bunch of things, but the most important are document and window — the same ones you have access to in JavaScript running in a browser.

To extract the title, you’d define this at the top level of your specification:

const title = extract(state => state.document.title || "");

The title value is not a string though — it’s a Cell<string>, a stateful value that changes over time. For every new state captured by Bombadil, the extractor function gets run, and the cell is updated with its return value.

Using the title cell, you can define the property:

export const hasTitle = always(() => 
    title.current !== ""
);

Two things to note about this example:

  1. The expression passed to always is a function that takes no arguments — a thunk. This is because it needs to be evaluated in every state. It needs to always be true, not just once, and that’s why you need to supply the thunk rather than a boolean.
  2. To get the string value out of the cell, you use .current.

This is a custom property using the temporal operator called always. There are other temporal operators, described in Formulas below.