Making and extending tests

Every project can be driven through the OpenEditor canvas: click things, check states, capture the outcome of each step, and replay the whole flow against a live frame. Tests live in a single oe-tests.json at your project root.

How a test runs

  1. Open the project's Tests view in the editor.
  2. Pick an environment and run the test live (browser / simulator) or replay from prior canvas captures.
  3. Each step reports pass / fail, its duration, and (when asked) a screenshot.
  4. Results and screenshots stream into the canvas next to the live app frame.

oe-tests.json

{
  "project": "fullstack-init",
  "simulator": "iPhone 16 Pro",
  "defaultEnvironmentId": "local",
  "environments": [
    { "id": "local", "label": "Local", "baseUrl": "http://localhost:9111", "kind": "local" },
    { "id": "preview", "label": "Preview", "baseUrl": "https://preview.example.com", "kind": "preview" },
    { "id": "production", "label": "Production", "baseUrl": "https://example.com", "kind": "production" }
  ],
  "flows": [
    { "id": "checkout", "name": "Checkout", "description": "Core purchase flow" }
  ],
  "tests": [
    {
      "name": "Add to cart and checkout",
      "flow": "Checkout",
      "flowId": "checkout",
      "type": "web",
      "environmentId": "local",
      "description": "Verifies the primary purchase path.",
      "steps": [
        { "action": "navigate", "url": "http://localhost:9111/", "wait": 1200 },
        { "action": "clickSelector", "selector": "[data-testid='add-to-cart']", "wait": 600 },
        { "action": "assertText", "selector": "[data-testid='cart-count']", "text": "1" },
        { "action": "screenshot", "name": "Cart with one item" },
        { "action": "clickSelector", "selector": "button[aria-label='Checkout']" },
        { "action": "assertPath", "expectedPath": "/checkout" }
      ]
    }
  ]
}

Step actions

Web tests drive a live browser; iOS tests drive a simulator. The runtime is inferred from the test type (or project type), but you can force it with "type": "web" | "ios" | "shopify".

ActionRuntimeWhat it doesFields
navigatewebLoad a URL for the selected environment.url | path, wait
clickSelectorwebClick the first element matching a selector.selector, wait
typeTextwebType text into the first matching field.selector, text, wait
assertTextwebPass if the text is present (optionally scoped to a selector).text, selector?
assertPathwebPass if the app is on the expected path.expectedPath | url
screenshotweb · iosCapture the current screen as a step outcome.name
waitweb · iosPause for a duration.wait
deepLinkweb · iosOpen a deep link / route in the app.url | path
tapXYiosTap a normalized x/y coordinate in the simulator.x, y
tapLabeliosTap a control by its accessibility label.label
scenarioiosLaunch a deterministic app fixture scenario.scenario, environment

Selectors

Selectors resolve in priority order. Prefer data-testid when you control the markup — it is stable across redesigns and localization.

[data-testid="add-to-cart"]
[data-component="ProductCard"]
#main-submit
button[aria-label="Checkout"]
input[name="email"]

Environments

A test can run against any declared environment. Steps that use path resolve against the selected environment's baseUrl, so the same test runs locally, on a preview, or in production.

Extending tests