Applications

Applications

What a step calls: a folder of TypeScript methods that know how to reach a system, documented in place.

An application is a folder under applications/ in the context folder, named after the system it talks to. Its index.ts exports methods, and a method is what a step calls: application: payments with method: refund runs the refund export of applications/payments/index.ts.

File What it is
index.ts The methods, each one documented by the JSDoc block above it.
README.md Anything worth knowing before writing flows against it. Rendered in the application's page.
env/<environment>.env The variables of one environment: URL, credentials, options. See Environments.
env/<environment>.env.example The committed template of that file, names only.
mimic.ts Optional: how to fake this application while another one is under test. See below.
anything else Playwright YAML files, fixtures, SQL, whatever the methods need.

Creating one

The + next to Applications in the sidebar asks for a name and copies a template: three documented methods (one offline, one reading the flow memory, one HTTP call), a README and an env/local.env. Replace them with your own. The name is the folder, and flows refer to it by that name, so the UI warns when you rename an application.

Everything the sidebar shows about an application is read from the folder: the README, the methods with their parameters, outputs and memory, and the environment files. A Document / Source toggle on the application page opens any of those files in an editor, index.ts included.

A method

import { applications, httpClient } from 'ronsel';
import type { Context, Parameters } from 'ronsel';

/**
 * Refunds an order.
 * @param {string} body.orderId - The order to refund.
 * @returns {202} The refund was accepted.
 */
export const refund = applications.handler([
  (ctx: Context, parameters: Parameters) =>
    httpClient.post(ctx, '/refunds', { body: parameters.body })
], 'refund');

applications.handler takes an array and the method's name. The last item of the array does the work; anything before it is a validator that runs first. The function receives three arguments:

Argument What it is
ctx The context. ctx.env holds the variables of the env file of the selected environment; ctx.name and ctx.path name the application; ctx.stepId is the step being run; ctx.reporter is where the helpers report what they did.
parameters The step's parameters, templates already resolved. By convention body, params, query and headers.
flow The whole flow: flow.memory is what earlier steps left behind.

It returns a tuple, [headers, status, body, memory]. The first three are what the step asserts on with test; the fourth is optional, and whatever it holds is merged into the flow memory for later steps. The built-in clients return the first three, so a method that wants to remember something builds the array itself. See Passing data between steps.

Applications are TypeScript, transpiled when they run and never type checked: a type error never stops a flow. The tsconfig.json the tool writes at the root of the context points your editor at the types of the installed package, so completion works while you write.

Validators

validate.body, validate.query, validate.params and validate.headers take a JSON schema and fail the step, with the schema's errors, before the method runs. Their fallbacks fill a missing field before the check, trying each source in order: the flow memory, a replacer, or a constant.

validate.body({
  type: 'object',
  properties: { token: { type: 'string' } },
  fallbacks: {
    token: [
      { type: 'memory', key: 'authToken' },
      { type: 'static', value: 'anonymous' }
    ]
  }
})

The helpers

Everything a method needs to reach a system comes from ronsel.

Helper What it does
httpClient.get / post / put / patch / del(ctx, path, options) An HTTP request to BASE_URL from ctx.env plus path. options carries body, headers and params (the query string). Returns [headers, status, body].
pgClient.query(ctx, sql, values) A PostgreSQL query, connected with DATABASE_CONNECTION_STRING or the PG* variables of ctx.env.
mqttClient.publish(ctx, topic, message, options) Publishes on the broker MQTT_HOST and friends describe. See Latent applications.
playwright.run(ctx, 'file.yaml', parameters, options) Runs a browser automation described in a YAML file next to index.ts. See Browser automation.
inputs.text(ctx, { label, secret, defaultValue }) Stops the run and asks the person for a value: a field under the step in the UI, a prompt on the CLI.
validate.* The validators above.
httpServer, mimicFiles, express For mimics. See below.

The variables each helper reads are listed in Environments.

Mimics

A step can ask for a dependency of the system under test to be faked while it runs, with its mimic key (see Step blocks). The fake is code of the mimicked application: a mimic.ts next to its index.ts, exporting start(config) and stop(config), where config carries what the step wrote (application, url, anything else) plus the flow. start typically opens an HTTP server with the httpServer helper and answers the routes the real dependency would; a response sent with res.json() goes through the replacers, with the request body in scope, so a fake can echo what it was sent. The system under test has to be pointed at that server, which is a variable of its own env file.

Listing what exists

ronsel --capabilities

prints every application of the context with its methods: the same list the sidebar shows, and the same catalogue the AI is given when it writes a flow. How to document a method so that all three read well is in Documenting an application.