> ## Documentation Index
> Fetch the complete documentation index at: https://documents.tmsone.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Test Builder

The **Test Builder** allows you to generate executable Playwright automation scripts from your manual test cases using AI. Instead of writing automation code by hand, you describe your test steps and the AI generates a ready-to-run script.

***

## How it works

You provide test steps, a target URL, and optional reusable flows. The AI generates a **Playwright automation script** that can be executed directly from TMS ONE. Results are tracked in [Execution History](/qa/execution-history).

```text theme={null}
Flow Library (optional)
  ↓  define reusable step sequences
Test Builder — fill in steps and URL
  ↓  insert flows + add specific steps
AI generates Playwright script
  ↓
Save to Script History
  ↓
Execute scripts
  ↓
View results in Execution History
```

<Tip>
  If your tests share common sequences (login, navigation, setup), create them in the [Flow Library](/qa/flow-library) first. This avoids duplicating steps across every script.
</Tip>

***

## Quickest way: Automate directly from a test case

The fastest way to generate an automation script is directly from your test cases list — no need to navigate to the Test Builder manually.

1. Go to **Test Cases** in your project
2. Find the test case you want to automate
3. Click the **magic wand icon** (Automate) in the Actions column
4. You'll be taken straight to the Test Builder with the test case pre-linked and details pre-populated
5. Add the **Page URL**, review the steps, and click **Generate Test Script**

<Tip>
  This is the recommended way to automate existing manual test cases — it saves time and automatically maintains the link between your manual test case and the generated automation script.
</Tip>

***

## Creating an automation script from scratch

### 1. Navigate to Test Builder

From the left sidebar, click **Test Builder** under your project. Note that **Flow Library** appears directly above Test Builder in the sidebar — if you have repeatable sequences across tests, set those up in the Flow Library first.

### 2. Fill in the generation form

<ParamField path="Test Title" type="text" required>
  A name for the automation script.\
  Example: *"Login flow - valid credentials"*
</ParamField>

<ParamField path="Page URL" type="text" required>
  The full URL of the page being tested.\
  Example: `https://yourapp.com/login`
</ParamField>

<ParamField path="Test Steps" type="table" required>
  Define the actions the automation should perform. Each step has three parts:

  | Field    | Description                                                                                                         | Example                                    |
  | -------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
  | Action   | What to do                                                                                                          | `click`, `type`, `toHaveText`, `toHaveURL` |
  | Selector | The CSS selector or XPath of the element to target                                                                  | `#email`, `button[type='submit']`          |
  | Value    | A fixed value, a Scenario Table column key (variable mode), or a `{{paramName}}` token referencing a flow parameter | `admin@example.com`, `expectedTitle`       |

  Click **+ Add Step** to add more steps.

  #### The `{ }` variable toggle

  Many step types display a **`{ }`** toggle button at the left of the Value field. Clicking it switches the step between **literal** mode (value is hardcoded) and **variable** mode (value is read from the Scenario Table at runtime).

  * **Type / Select actions** — variable mode links the value to a Scenario Table column key, so each scenario row provides a different input.
  * **Assertion actions** (`toContainText`, `toHaveText`, `toHaveValue`, `toHaveCount`, `toHaveURL`) — variable mode drives the expected value from a Scenario Table column, so different scenarios can assert different expected outputs.

  When the toggle is **blue**, the step is in variable mode. When **grey**, it is in literal mode.

  #### Inserting a reusable flow

  Click **+ Insert Flow** above the steps table to insert a flow from the [Flow Library](/qa/flow-library). Select a flow, supply any required parameter values, and click **Insert**. The flow's steps are inserted as a block in your steps list.

  If no flows appear in the picker, you will see a prompt linking you to the Flow Library to create one.
</ParamField>

<ParamField path="Scenario Data" type="table">
  Optional. Add multiple test data combinations to run the same script with different inputs. Each row is a separate scenario.

  Example:

  | Scenario Title    | email                                         | password  |
  | ----------------- | --------------------------------------------- | --------- |
  | Valid admin login | [admin@company.com](mailto:admin@company.com) | Admin123! |
  | Valid user login  | [user@company.com](mailto:user@company.com)   | User123!  |

  You can also **import scenarios from a CSV file**.
</ParamField>

***

## Scenario-driven assertions

By default, assertions use a **fixed expected value** that is the same for every scenario. When you have a data-driven test where different scenarios should assert different values, you can drive the assertion from a **Scenario Table column** instead.

### Supported assertion actions

The following assertion actions support variable mode:

| Action          | What it asserts                 |
| --------------- | ------------------------------- |
| `toContainText` | Element contains the given text |
| `toHaveText`    | Element text exactly matches    |
| `toHaveValue`   | Form input has the given value  |
| `toHaveCount`   | Number of matching elements     |
| `toHaveURL`     | Current page URL matches        |

<Note>
  `toHaveAttribute` (requires two fields: attribute name and expected value) and `getAttribute` (retrieves a value rather than asserting) do not yet support variable mode.
</Note>

### Setting up a scenario-driven assertion

1. Add a step and choose an assertion action (e.g. `toHaveText`)
2. Enter the element **Selector**
3. In the **Value** field, click the **`{ }`** toggle — it turns blue to indicate variable mode
4. Type the **Scenario Table column key** that holds the expected value for each scenario (e.g. `expectedTitle`)
5. Make sure your Scenario Table has a column with that exact key name and a value in each row

The AI generates conditional assertion code that reads the expected value from the scenario data at runtime.

### Skip assertion when scenario value is empty

When a step is in variable mode, a **"Skip assertion when scenario value is empty"** checkbox appears below the Value field.

| Checkbox state        | Generated behaviour                                                                                               |
| --------------------- | ----------------------------------------------------------------------------------------------------------------- |
| **Checked** (default) | The assertion is wrapped in a guard — it is skipped entirely for any scenario row where the column value is blank |
| **Unchecked**         | The assertion always runs, even if the scenario value is empty                                                    |

Use the checkbox when some scenarios genuinely do not need to assert that field. Leave it unchecked when a missing value should be treated as a test failure.

### Example

**Steps:**

| Action     | Selector         | Value                              | Mode     |
| ---------- | ---------------- | ---------------------------------- | -------- |
| navigate   |                  | `https://app.example.com/products` | literal  |
| click      | `#search`        |                                    |          |
| type       | `#search`        | `query`                            | variable |
| toHaveText | `.product-title` | `expectedTitle`                    | variable |
| toHaveURL  |                  | `expectedUrl`                      | variable |

**Scenario Table:**

| Scenario Title | query   | expectedTitle    | expectedUrl         |
| -------------- | ------- | ---------------- | ------------------- |
| Laptop search  | laptop  | Best Laptop 2025 | /products?q=laptop  |
| Monitor search | monitor | 4K Monitor       | /products?q=monitor |
| No-URL check   | tablet  | Smart Tablet     | *(blank)*           |

With "Skip assertion when scenario value is empty" checked on the `toHaveURL` step, the URL assertion runs for the first two scenarios and is skipped for the third.

***

### Link to manual test case

Expand the **Link to manual test case** section to optionally associate this script with your manual test management records.

<ParamField path="Jira Tickets" type="multiselect">
  Optional. Link Jira tickets if your Jira integration is configured.
</ParamField>

<ParamField path="Module(s)" type="select">
  Optional. Associate the script with one or more modules in your project.
</ParamField>

<ParamField path="Test Case" type="select">
  Optional. Link to a specific manual test case for traceability.
</ParamField>

### 3. Generate the script

Click **Generate Test Script**. The AI will produce a Playwright script based on your inputs, shown in the right panel.

<Tip>
  The more precise your selectors and actions, the better the generated script. Use specific IDs or data attributes where possible.
</Tip>

### 4. Review and edit

You can edit the generated script directly in the code editor before saving. This is useful for adjusting selectors, adding assertions, or tweaking logic.

### 5. Save the script

Click **Save Test Script**. The script is saved to your project's script history and is ready to execute.

***

## Managing saved scripts

Navigate to **Test Builder → History** to see all saved automation scripts for your project.

From the history list you can:

* **View** the full script and its metadata
* **Edit** the script code and update it
* **Execute** one or more scripts
* **Regenerate** a stale script (see below)
* **Delete** scripts you no longer need

Each entry shows the script title, language, linked manual test case (if any), who generated it and when.

### Stale scripts

When a [Flow Library](/qa/flow-library) flow that a script references has its **steps or parameters changed**, that script is automatically marked as **Stale**. A yellow warning badge appears next to the script title in the history list.

A stale script is still executable — the existing generated code has not changed. The badge is a signal that the flow it was built from has since been updated, so the script may no longer reflect the current flow logic.

#### Regenerating a stale script

Regeneration is supported for all script languages (JavaScript and C#).

To bring a stale script up to date:

1. In the history list, find the script showing the **Stale** badge
2. Click the **Regenerate** button (reload icon) in the Actions column
3. Confirm in the prompt — the existing script will be overwritten
4. The system re-resolves all flow references using the latest flow steps and re-calls the AI to produce a fresh script

<Warning>
  Regenerating overwrites the currently saved script. If you have manually edited the script after it was first generated, those edits will be lost. Save any customisations elsewhere before regenerating.
</Warning>

<Note>
  Regeneration requires every flow referenced by the script to be in **Active** status. If a flow was set to Draft after the script was created, regeneration will fail with an error. Reactivate the flow in the [Flow Library](/qa/flow-library), then regenerate again.
</Note>

<Tip>
  If a flow changes frequently, consider whether its steps are stable enough to be a flow. Alternatively, use more granular flows — for example, a separate "Login" flow and a separate "Navigate to checkout" flow — so a change to one only marks scripts that actually use it as stale.
</Tip>

***

## Executing automation scripts

### 1. Select scripts to run

In the history list, use the **checkboxes** to select one or more scripts.

### 2. Click Execute

Click the **Execute** button. The scripts are queued and run via the Playwright service.

<Note>
  The Execute button is disabled while a run is already in progress. You'll see an "Execution is in progress" indicator until it completes.
</Note>

### 3. View results

Once execution completes, go to [UI Test Runs](/qa/ui-test-runs) to see pass/fail counts and download the full HTML report.

***

## Tips for better automation

<AccordionGroup>
  <Accordion title="Create flows for repeated sequences">
    If you find yourself typing the same login or navigation steps in every script, extract them into a flow in the Flow Library. Insert the flow instead — it's faster to build and easier to maintain if selectors change.
  </Accordion>

  <Accordion title="Use stable selectors">
    Prefer IDs (`#elementId`) or data attributes (`[data-testid='login-btn']`) over class names. These are less likely to break when the UI changes.
  </Accordion>

  <Accordion title="Keep scripts focused">
    Each script should test one flow. Avoid combining unrelated actions — it makes failures harder to diagnose.
  </Accordion>

  <Accordion title="Use scenario data for data-driven tests">
    Instead of creating multiple scripts for similar flows, add multiple rows to the scenario table. The same script runs once per scenario with different data. Use the `{ }` variable toggle on assertion steps to assert different expected values per scenario — for example, asserting that a search for "laptop" lands on a different page title than a search for "monitor".
  </Accordion>

  <Accordion title="Link to your manual test case">
    Linking a script to its manual test case keeps your test suite organised and makes it easy to trace which automation covers which requirement. Use the **Link to manual test case** section at the bottom of the form.
  </Accordion>
</AccordionGroup>

***

## What's next?

<CardGroup cols={2}>
  <Card title="Flow Library" icon="layer-group" href="/qa/flow-library">
    Create reusable step sequences to share across scripts
  </Card>

  <Card title="Execution History" icon="chart-bar" href="/qa/execution-history">
    View automation execution results and download reports
  </Card>
</CardGroup>
