Skip to main content

Evaluate Expressions

The evaluate expression language allows for data set interaction using custom JavaScript expressions within a crul query. The evaluate command can operate as --type reducing or mapping. For performance reasons, it is best to utilize the default reducing type. When reducing, the expression will operate on the entire result set at once, while when mapping, will operate on the result set one row at a time. The expression will operate in a sandboxed headless browser tab, which has overhead of a new tab per row when operating as a mapping stage.

The expression language is used with the evaluate command, as well as in other browser related commands which accept an --expression flag or argument (see navigate, open, etc.).

Expression format

The evaluate expression format is straightforward. It follows the general pattern for a JavaScript arrow function expression: () => {}.

evaluate "() => ({date: Date.now()})"

In order to operate on data from the previous stage, you will need to include data as an argument to the expression: (data) => { return data.length }

devices
|| evaluate "(data) => data.filter(item => item.name.indexOf('iPhone') !== -1)"

In order to include available runtime libraries (outlined below), you will need to add a flag for the library, and an object as the last argument of the expression containing the library name: (data, { _ }) => { ... }

devices
|| evaluate "(data) => _.sampleSize(data, 10)" --lodash

Return format

crul will transform the output of the evaluate expression into rows. If you return a string/boolean, you will get back a single row containing the response in a column named content. To return rows, your expression should return an array of objects [{ key: "value1" }, { key: "value2" }]. The previous return wil create two rows, with a single key column.

Syntax highlighting

In order to enable JavaScript syntax highlighting in the crul web query interface, you will need to use the ```javascript () => {}``` syntax around your expression.

devices
|| evaluate ```javascript
(data) => data
```

Advanced features

The evaluate runtime has access to the following libraries: lodash, mathjs, and faker. You can include each library in the runtime by providing a --lodash, --mathjs, or --faker flag to the evaluate command.

lodash

You can use the lodash library for common data manipulation tasks.

devices
/* sort by viewport.deviceScaleFactor in descending order and by name in ascending order */
|| evaluate "(data) => _.orderBy(data, ['viewport.deviceScaleFactor', 'name'], ['desc', 'asc'])"
--lodash

mathjs

You can use the mathjs library for more advanced mathematical expressions than possible through the basic math command.

devices
|| evaluate "(data, { mathjs }) => {
/* get all the device scale factor values */
const scaleFactors = data.map(item=>item.viewport.deviceScaleFactor);
/* get the std deviation of all scale factors */
return {
standardDeviation: mathjs.std(scaleFactors)
}
}
"
--mathjs

faker

You can use the faker library for data set generation.

evaluate ```javascript (data, {faker}) => { 
return { "uuid": faker.datatype.uuid() }
}``` --faker