> For the complete documentation index, see [llms.txt](https://docs.bugbug.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bugbug.io/editing-tests/variables.md).

# Variables

BugBug variables: kinds of variables, naming and syntax rules, where you can use them, built-in variables, JavaScript variables, profiles and the default profile, secret values, overriding values per

## What are variables?

Variables are named values that you use in test steps as `{{name}}`. BugBug replaces each variable with its value when the step runs.

Use variables to:

* Run the same tests on several environments, for example `{{hostname}}/login`.
* Keep values used in many tests in one place, such as emails, product names or ZIP codes.
* Generate unique data, for example a new email address on every run.
* Save a value from the page and use it later in the test.

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FeYzk3QfYNkJEsGJxTIJM%2F21.03.2023%2012_11_58.png?alt=media&amp;token=bd1ed665-5f4f-4c9a-bb23-cae5e5660564" alt="Variable hostname used in a Go to URL step"><figcaption><p>Example: variable "hostname" used in a URL</p></figcaption></figure>

{% hint style="info" %}
**In short**

* Variables are created in the **Variables** tab. Their values there belong to the **DEFAULT** profile.
* Other [profiles](#profiles) can only override variables that already exist. An empty value in a profile means "use the default value".
* `{{name}}` works in step fields and selectors, not inside JavaScript code. In code, use `variables.name`.
* Only plain names work: `{{user.email}}` or filters such as `{{name | upcase}}` aren't supported.
* BugBug has no data sets. To run the same test with different data, use profiles or per-run overrides.
  {% endhint %}

### Kinds of variables

| Kind                                                                      | Where it comes from                                                                                                                                                  | Value                                                          |
| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| Text variable                                                             | Created in the **Variables** tab                                                                                                                                     | Fixed text. Can include other variables.                       |
| [JavaScript variable](#javascript-variables)                              | Created in the **Variables** tab with type **Custom JavaScript**                                                                                                     | Computed by your code before each step that uses it            |
| [Built-in variable](#use-built-in-variables-for-dynamic-or-random-values) | Provided by BugBug                                                                                                                                                   | Run data or a generated value                                  |
| Local variable                                                            | Saved during a run with a [Set variable](/editing-tests/actions.md#set-variable) step                                                                                | Value from the page, a text or your code                       |
| [Profile](#profiles) value                                                | Set in a profile                                                                                                                                                     | Replaces a variable's default value for runs with that profile |
| Override                                                                  | Passed when you start a run from the [CLI](#override-variables-and-profiles-from-the-command-line-cli) or the [API](#override-variables-when-starting-a-run-via-api) | Replaces a variable's value for one run                        |

A local variable with the same name as another variable replaces it for the rest of the run.

## Rules for variables

* **Syntax.** Put the name in double curly brackets: `{{hostname}}`. You can mix variables with text: `{{hostname}}/v1/index.html`.
* **Only the name.** Inside the brackets, write only the variable's name. Property access such as `{{user.email}}` and filters such as `{{name | upcase}}` aren't supported; BugBug looks for a variable with that whole text as its name and fails with `VARIABLE_DOES_NOT_EXIST`. To use part of a value, cut it out with a [Set variable](#save-values-during-a-run) step with **Value** set to **Custom JavaScript**.
* **Names** are case-sensitive, up to 50 characters, without spaces. We recommend [camelCase](https://en.wikipedia.org/wiki/Camel_case), for example `userEmail`. You can't use the name of a built-in variable.
* **Values** of text variables have up to 5000 characters. Every value is text.
* **Variables inside variables.** A variable's value can use other variables, for example `{{baseUrl}}/admin`, up to 3 levels deep. A variable can't use itself.
* **Escaping.** To use `{{` and `}}` literally, wrap the text in `{% raw %}` and `{% endraw %}`.

### Where you can use variables

You can use variables in:

* URLs in **Go to URL** and **New tab**, including basic auth username and password
* Values of **Type text**, **Change value**, **Select option** and **Set variable**
* Expected values of assertions and If conditions
* Custom [selectors](/preventing-failed-tests/selectors.md), for example `//button[text()="{{productName}}"]`, including local variables saved earlier in the run

`{{name}}` isn't replaced inside JavaScript code. In code, use the [`variables` object](#use-the-variables-argument-in-your-javascript-function).

### Errors

| Error code                        | When it happens                                                                                                                                  |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `VARIABLE_DOES_NOT_EXIST`         | The step uses a variable that doesn't exist, for example because of a typo, different letter case, or a local variable that hasn't been set yet. |
| `VARIABLE_NESTING_LIMIT_EXCEEDED` | Variables are nested more than 3 levels deep.                                                                                                    |
| `VALUE_COMPUTING_ERROR`           | The variable syntax is wrong, for example `{variable}` or `{{variable}`.                                                                         |

See all [error codes](/debugging-tests/error-codes.md).

## Using text variables

### Create custom text variables

Go to the **Variables** tab and click **New variable**.

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2F2KQwTRNtCsfA6rJ2CTwh%2FnewVariable_new.png?alt=media&amp;token=cca5eb19-b48e-4123-9db2-307aab8e9380" alt="New variable button in the Variables tab"><figcaption></figcaption></figure>

Add a name and a value for your variable.

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FxehmJ0ZANjm4Gt0UGXQv%2F1newVar2.png?alt=media&amp;token=f7f06d24-f181-40b0-9181-678f551ae94e" alt="New variable form with name and value"><figcaption></figcaption></figure>

Click **Create variable** to save it.

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FXogYdHSLR558bX3EMYSx%2F1newVar3.png?alt=media&amp;token=1f747217-bf8d-4581-8275-19286183f76a" alt="Create variable button"><figcaption></figcaption></figure>

### Secret variables

To keep a value such as a password hidden, mark the variable as secret. Its value is masked in the app and in API responses.

A secret variable is used like any other variable: `{{password}}` in a step types the real value, and your JavaScript code gets the real value in `variables.password`. Secret only hides the value from people reading the project.

### Use variables in tests

Type the variable name in curly brackets in any supported field of a step.

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2F0rMfCwY1CjysQI3Amlho%2FZrzut%20ekranu%202023-03-24%20125442.png?alt=media&amp;token=0478e2f3-897c-4cd6-87ac-d5079d217c2f" alt="Variables used in selectors and assertions"><figcaption><p>Use variables in selectors, assertions, etc.</p></figcaption></figure>

**Combining variables with curly brackets**

To put curly brackets around a variable's value, escape them with `{% raw %}` and `{% endraw %}`:

* variable `projectName` = `Foo`
* field value: `{{ projectName }}{% raw %} {Put this text in brackets}{% endraw %}`
* result: `Foo {Put this text in brackets}`

### Use built-in variables for dynamic or random values

Built-in variables are provided by BugBug. Some change on every step, some stay the same for the whole run.

| Built-in variable   | Value                                                                           | Changes            |
| ------------------- | ------------------------------------------------------------------------------- | ------------------ |
| `testRunId`         | ID of the current test run (UUID)                                               | Once per run       |
| `testId`            | ID of the test (UUID)                                                           | Never              |
| `testName`          | Name of the test                                                                | Never              |
| `suiteRunId`        | ID of the suite run (UUID), when the test runs in a suite                       | Once per suite run |
| `suiteName`         | Name of the suite, when the test runs in a suite                                | Never              |
| `scheduleId`        | ID of the schedule, when the run was started by a schedule                      | Never              |
| `scheduleName`      | Name of the schedule, when the run was started by a schedule                    | Never              |
| `profileName`       | Name of the profile used in the run                                             | Never              |
| `runMode`           | `local` or `server` (cloud)                                                     | Never              |
| `timestamp`         | Current Unix time in milliseconds, for example `1645710937798`                  | On every step      |
| `randomNumber`      | Random 10-digit number                                                          | On every step      |
| `randomName`        | Random 8-letter name                                                            | On every step      |
| `randomNumberFixed` | Random 10-digit number                                                          | Once per run       |
| `randomNameFixed`   | Random 8-letter name                                                            | Once per run       |
| `vercelUrl`         | Unique URL of the Vercel deployment, in Vercel-triggered runs                   | Once per run       |
| `vercelBranchUrl`   | First deployment alias URL from Vercel, in Vercel-triggered runs. Can be empty. | Once per run       |

Use a value that changes **once per run** when you need the same unique value in several steps, for example `user{{randomNumberFixed}}@example.com` in a registration form and later in the login form.

`timestamp`, `randomNumber` and `randomName` get a new value for every step. Within one step the value is the same: if a step uses `{{timestamp}}` twice, both places get the same number.

**Example: always load a fresh page.** Add a changing value to the URL so the browser doesn't use a cached copy, for example `{{hostname}}/pricing?nocache={{timestamp}}`. The **Reload page** step reloads the page normally and doesn't bypass the browser cache.

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FfJfFAIGfICSZDi0ZIOeR%2FZrzut%20ekranu%202023-03-20%20111515.png?alt=media&amp;token=6af6e495-b35f-4d96-a43f-1345d9408c13" alt="Built-in variables in the variable picker"><figcaption></figcaption></figure>

### Recording and working with variables

You can insert variables while recording, and save values from the page as local variables. See [Local variables](/editing-tests/local-variables.md).

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FFDlqqL5U1IM7gdyr5ioH%2FZrzut%20ekranu%202023-04-03%20120138.png?alt=media&amp;token=713c1990-5c94-453b-9bc0-deb0cb3c723d" alt="Variables options in the recording overlay"><figcaption><p>Two options for variables in the overlay</p></figcaption></figure>

### Save values during a run

A [Set variable](/editing-tests/actions.md#set-variable) step saves a local variable. Choose where the value comes from in the **Value** field:

| **Value** in the app  | In YAML and the API | Saved value                                                                                             |
| --------------------- | ------------------- | ------------------------------------------------------------------------------------------------------- |
| **From element**      | `element`           | For `input` and `textarea`: the value. For `select`: the selected option. For other elements: the text. |
| **Text**              | `value`             | A text, which can include other variables.                                                              |
| **Custom JavaScript** | `evaluate`          | The result of your [JavaScript code](/editing-tests/custom-javascript-actions.md), as text.             |

The saved value is shown in the step's details in the run.

To save an attribute, such as a link's `href`, use **Custom JavaScript**:

```javascript
return document.querySelector('a.confirm').getAttribute('href');
```

A Set variable step saves one variable. If your code returns an object, the variable holds its JSON text; the object's keys don't become separate variables. To use one property, return only that property, or parse the JSON in a later step:

```javascript
return JSON.parse(variables.user).email;
```

## JavaScript variables

JavaScript variables compute their value with your code.

#### Use JavaScript variables for:

* Getting data from an API, for example SMS codes or magic links
* Calculations
* Unique strings that must meet validation rules, such as tax numbers or postal codes
* Values that depend on conditions, for example different text at night and during the day

#### **To create a JavaScript variable**

1. Go to the **Variables** tab and click **New variable**.
2. Change the type to **Custom JavaScript**.
3. Enter the code that returns the value.

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2Fs8QnU5UugZAWtYSpaakw%2FvariableSettings_new.png?alt=media&amp;token=7725c7d0-b68d-49ac-9d76-f3877f8a9f2c" alt="Custom JavaScript variable form"><figcaption><p>Variable settings</p></figcaption></figure>

### How JavaScript variables work

* **Write only the body of the function.** The editor shows the signature `async function(variables)` above the code field; you write what goes inside it. The code must contain `return`, and you can use `await`.
* **The value is computed before each step that uses the variable.** Every step that uses it runs the code again, so the value can change between steps. To compute a value once per run, use a [Set variable](/editing-tests/actions.md#set-variable) step with **Value** set to **Custom JavaScript** instead. See [When JavaScript variables are evaluated](/editing-tests/custom-javascript-actions.md#when-javascript-variables-are-evaluated).
* **The code runs in the tested page,** with access to `document`, `window` and `localStorage`.
* **Objects and arrays become JSON text.**
* **The code is checked when you save it.** Code with syntax errors or without `return` can't be saved.

### Example JavaScript variable functions

Return a simple text:

```javascript
const firstName = 'John';
const lastName = 'Smith';
return firstName + lastName;
```

Return a different value on Sundays:

```javascript
const day = new Date().getDay(); // 0 = Sunday, 1 = Monday, ..., 6 = Saturday
if (day === 0) {
  return 'Delivery in 48 hours';
}
return 'Delivery in 24 hours';
```

### Use the "variables" argument in your JavaScript function

The `variables` object contains built-in variables, your text variables with the values of the run's profile and overrides, and local variables saved earlier in the run. Secret variables are included with their real values. Use it to combine and calculate values:

```javascript
return variables.userEmail + variables.testRunId;
```

```javascript
return Number(variables.userHeightInCentimeters) + 20;
```

Most values in `variables` are text, so convert them with `Number()` before calculating.

If you run a Run custom JavaScript step with `console.log(variables)`, you get an output like this:

```
{
    hostname: "https://marmelab.com/react-admin-demo/"
    profileName: "Base"
    runMode: "local"
    scheduleId: null //only for scheduled runs
    scheduleName: null //only for scheduled runs
    suiteId: "54bd4384-ad9c-4e83-946f-111392ed0a82"
    suiteName: "All tests"
    suiteRunId: "18e1e3c3-ec2a-45c9-b817-8f48a56a0807"
    testId: "37e64599-31a9-4707-9fed-a64cdec24294"
    testName: "Test"
    testRunId: "6498c9bd-81a5-412f-a275-2c7f1cfc4d45"
    timestamp: 1665667075470
    username: "demo"
}
```

{% hint style="warning" %}
JavaScript variables aren't computed in the `variables` object: they have the text value `NOT_COMPUTED`. To use one in code, save it first with a Set variable step with **Value** set to **Text** and the text `{{name}}`, or use `localStorage` to pass values between JavaScript variables, as shown below.
{% endhint %}

### Use localStorage to pass on data between variables

1. At the end of the first variable, store the result in `localStorage`:

```javascript
const name = variables.firstName + variables.lastName;
localStorage.setItem('bugbugUserName', name);
return name;
```

2. In the next variable, read it from `localStorage`:

```javascript
const name = localStorage.getItem('bugbugUserName');
return name === 'Carl' ? 'Hello Carl' : 'Hello';
```

## Override variables when starting a run via API

When you start a test or a suite through the [Public API](/integrations/public-api.md), you can choose the profile and override variable values for that run:

```json
{
  "testId": "<test id>",
  "runProfileId": "<profile id>",
  "variables": [
    { "key": "hostname", "value": "https://stage.acme.com" }
  ]
}
```

Without `runProfileId`, the run uses the profile assigned to the test or suite. You can override only variables that exist in the project; an unknown key is rejected.

## Data-driven testing

BugBug doesn't have data sets for running one test once per row of data. To run the same tests with different data:

* **One profile per data set.** Create a profile for each set of values and run the test or suite with each profile.
* **Overrides per run.** Start runs from the [CLI](#override-variables-and-profiles-from-the-command-line-cli) or the [API](#override-variables-when-starting-a-run-via-api), passing different values each time, for example in a loop in your CI script.
* **Data from your API.** Fetch the test data in a [Set variable](/editing-tests/actions.md#set-variable) step with **Value** set to **Custom JavaScript**.

## User registration and login using the BugBug Testing Inbox

The [BugBug Testing Inbox](/editing-tests/testing-inbox.md) receives emails sent during a test, so you can test sign-up, email verification, password reset and one-time codes. See [Testing Inbox](/editing-tests/testing-inbox.md) for the full guide.

### Use the BugBug Testing Inbox to generate a unique email address

Use the built-in variable `testRunId` in the address: `{{testRunId}}@bugbug-inbox.com`. It's the same in all steps of one run and new in the next run, so every run registers a new user and reads only its own emails. Open the inbox with an [Open inbox](/editing-tests/actions.md#open-inbox) step whose value is only the name, `{{testRunId}}`.

## Profiles

### What are profiles?

Profiles are sets of variable values. When you run a test or suite with a profile, its values replace the default values of your variables. This is useful when [working with multiple development environments](#work-with-different-development-environments).

BugBug creates the first profile, **Base**, marked **DEFAULT**. It provides the default values of your variables. Other profiles use these values unless they override them.

{% hint style="info" %}
The profile menu in the test appears when you have at least 2 profiles.
{% endhint %}

![Profile menu next to the Run button](https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FUrAZiXTITShS4lPbEWlI%2Fimage.png?alt=media\&token=03154cf6-a084-4523-bbe1-e2dd25750686)

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FPzxcCgXllhhgMhHkCwHG%2Fnew%20profile.png?alt=media&amp;token=95e11ba1-031d-4a8e-b31e-60732dc49e2c" alt="Profiles section in the Variables tab"><figcaption><p>To add, remove and edit profiles go to the "Variables" tab</p></figcaption></figure>

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FyyPRzALolmimuNPJoBLq%2FZrzut%20ekranu%202023-03-21%20152825.png?alt=media&amp;token=ceb83aea-7c45-4338-8d53-23743af97ae3" alt="Overriding variables in profile settings"><figcaption><p>Override variables in the profile settings. Leave an empty field to keep the default value.</p></figcaption></figure>

### How profile values work

* **The DEFAULT profile holds your variables.** Variables you create in the **Variables** tab are the DEFAULT profile's variables, with their default values.
* **Other profiles only override.** A profile can set a value only for a variable that already exists. To use a new variable in a profile, create it in the **Variables** tab first. The API rejects a profile value for an unknown variable.
* **Empty means default.** A variable that a profile leaves empty gets its default value.
* **The DEFAULT profile can't be deleted or replaced.** Each project has exactly one. When you delete another profile, the tests and suites that used it switch to the DEFAULT profile.

### Which profile a run uses

| How the run starts                                                        | Profile                                                                                          |
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| **Run** in the test editor                                                | The profile chosen next to the **Run** button. It's saved with the test.                         |
| Tests list                                                                | The profile you choose for that run. If you don't choose one, the DEFAULT profile.               |
| Suite                                                                     | The profile saved in the suite settings.                                                         |
| [Schedule](/running-tests/schedules.md)                                   | Each suite runs with the profile saved in its own settings. Schedules don't have a profile.      |
| [Public API](/integrations/public-api.md) and [CLI](/integrations/cli.md) | `runProfileId` (API) or `--profile` (CLI). Without it, the profile saved with the test or suite. |
| [MCP](/ai-testing/mcp.md)                                                 | `profileName` of `bugbug_run_test`. Without it, the test's own profile.                          |

### Choose the profile for new tests and suites

1. Go to **Variables → Profiles**.
2. Find **New tests and suites will use profile** above the profile list.
3. Select the profile you want to use.

New tests and suites use this profile. You can choose a different profile when creating a suite. Existing tests and suites keep their profiles, and the **DEFAULT** profile still provides the default values.

### Run a test with a profile to override variables

1. Create a profile in the **Variables** tab.
2. Open the test.
3. Choose the profile in the menu next to the **Run** button.

You can also choose the profile [from the command line](#override-variables-and-profiles-from-the-command-line-cli) or [through the API](#override-variables-when-starting-a-run-via-api).

{% hint style="info" %}
The profile you choose in the test editor is saved with the test and used when you run or record from the editor. When you run the test from the tests list, choose the profile for that run.
{% endhint %}

{% hint style="info" %}
**Tip:** Make your tests pass on all profiles. Don't create tests that work only with one profile.
{% endhint %}

### Run a suite with a profile

Each suite runs its tests with its own profile, also when a schedule starts it. For example, a "Production smoke tests" suite and a "Staging all tests" suite can run different tests with different variables.

1. Go to **Suites** and open a suite.
2. Choose the profile for this suite.

{% hint style="info" %}
The suite always runs with this profile; the choice is saved in the suite settings.
{% endhint %}

<figure><img src="https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FdQGIdHRxuoHKoopfMcml%2Fprofile.png?alt=media&amp;token=f8343800-6334-4ba6-9ae7-5c4337ff4b8a" alt="Profile selection in suite settings"><figcaption></figcaption></figure>

### Work with different development environments

Say you have 3 environments that differ only by URL:

| Environment | URL              |
| ----------- | ---------------- |
| Production  | `acme.com`       |
| Staging     | `stage.acme.com` |
| Local       | `localhost:3000` |

**Prepare the variables and profiles**

1. Create a variable `hostname` with the default value `https://acme.com`.
2. Create 2 profiles: `Staging` and `Local`.
3. In `Staging`, override `hostname` with `https://stage.acme.com`.
4. In `Local`, override `hostname` with `https://localhost:3000`.

#### Update the URLs with your variable

1. In your tests, find the **Go to URL** steps.
2. Replace `acme.com` with `{{hostname}}`.

**Tip:** Combine the variable with the rest of the URL, for example `{{hostname}}/registration`.

Now [run the tests with different profiles](#run-a-test-with-a-profile-to-override-variables) to switch between environments.

![](https://3168433179-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKixgeBPbLvnD0l1eiV%2Fuploads%2FL9chpQmQrcDRZqlePYfh%2Fimage.png?alt=media\&token=891f04a1-ffdb-4215-b979-25dfaa011e3f)

### Override variables and profiles from the command line (CLI)

With the [BugBug CLI](/integrations/cli.md) you can run tests in your build pipeline and override variables or the profile with parameters, for example `--variable val1=value` and `--profile "Staging"`. See the [CLI documentation](/integrations/cli.md).

## FAQ

<details>

<summary>Does a variable have to exist before a profile can set it?</summary>

Yes. Create the variable in the **Variables** tab first. A profile can only override existing variables; leaving its field empty keeps the default value.

</details>

<details>

<summary>What does the DEFAULT profile mean, and which profile is used when I don't choose one?</summary>

The DEFAULT profile (first called **Base**) holds the default values of all variables, and other profiles override some of them. A run without a chosen profile uses the profile saved with the test or suite; from the tests list, the DEFAULT profile. See [Which profile a run uses](#which-profile-a-run-uses). To set which profile new tests and suites get, use **New tests and suites will use profile**.

</details>

<details>

<summary>Can JavaScript read profile and secret variables?</summary>

Yes. `variables.name` has the value from the run's profile, including secret variables with their real values. JavaScript variables are the exception: they have the value `NOT_COMPUTED` in code.

</details>

<details>

<summary>Can a variable hold a JSON object and can I use {{user.email}}?</summary>

A variable can hold JSON as text, but `{{user.email}}` isn't supported. Save the property you need with a **Set variable** step with **Value** set to **Custom JavaScript**, for example `return JSON.parse(variables.user).email;`, and use that variable.

</details>

<details>

<summary>Can I use variables in custom selectors?</summary>

Yes, including local variables saved earlier in the run, for example `//tr[contains(., "{{orderId}}")]`.

</details>

<details>

<summary>Is {{timestamp}} different every time I use it?</summary>

It changes from step to step. Within one step it has the same value everywhere. For one value for the whole run, use `randomNumberFixed` or save the timestamp with a **Set variable** step.

</details>

<details>

<summary>Does BugBug support data sets or data-driven testing?</summary>

Not as data sets. Use a profile per set of data, per-run overrides from the CLI or API, or fetch the data in a Set variable step. See [Data-driven testing](#data-driven-testing).

</details>

<details>

<summary>Can I use variables in the basic auth password of Go to URL?</summary>

Yes. The username and password of **Go to URL** and **New tab** accept variables, for example `{{basicAuthPassword}}`. Mark the variable as secret to hide its value.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.bugbug.io/editing-tests/variables.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
