Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions .doc-detective/tests/environment-variables-settings.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{
"specId": "environment-variables-settings",
"description": "Guards the Environment Variables settings view against UI drift. The `## Add environment variables` and `## Update and delete variables` walkthroughs in src/content/docs/docs/scale/environment-variables.mdx name each control by its visible label -- Key Name, Value, Secret, Add Variable, Update, Delete -- and promise the Value field masks once Secret is on; these labels and the page's screenshots went stale once before, so this spec asserts them. Non-destructive: it checks presence, labels, and masking and never submits the form or deletes a variable.",
"tests": [
{
"testId": "env-vars-settings-page-and-variables-table",
"description": "A bare /settings link lands on the Environment Variables view, which shows the variables table with Key, Value, Created, and Actions columns and both an Update and a Delete control on every row. Save and Cancel stay hidden on load (`## Update and delete variables`).",
"before": "login.spec.json",
"steps": [
{
"description": "Open the Settings page the docs link to. It 307-redirects to the Environment Variables view.",
"goTo": "https://app.gopromptless.ai/settings"
},
{
"description": "Wait for the Environment Variables view to render",
"find": {
"elementText": "/Environment Variables/",
"timeout": 20000
}
},
{
"description": "Settings opens on the Environment Variables view and the documented name is present",
"runBrowserScript": {
"script": "const own = (el) => Array.from(el.childNodes).filter((n) => n.nodeType === 3).map((n) => n.textContent).join(' ').replace(/\\s+/g, ' ').trim(); const named = Array.from(document.querySelectorAll('body *')).some((el) => own(el) === 'Environment Variables'); return ['path=' + window.location.pathname, 'envVarsTabName=' + (named ? 'present' : 'missing')].join(' ');",
"output": "path=/settings/env-vars envVarsTabName=present",
"timeout": 15000
}
},
{
"description": "The variables table has the four documented columns in the documented order",
"runBrowserScript": {
"script": "const cells = document.querySelectorAll('thead th').length ? document.querySelectorAll('thead th') : document.querySelectorAll('[role=columnheader]'); if (!cells.length) return 'headers=none-found'; const headers = Array.from(cells).map((c) => (c.textContent || '').replace(/\\s+/g, ' ').trim()).filter(Boolean); return 'headers=' + headers.join('|');",
"output": "headers=Key|Value|Created|Actions",
"timeout": 15000
}
},
{
"description": "Every row carries an Update and a Delete control, and neither Save nor Cancel is present before an Update is clicked",
"runBrowserScript": {
"script": "const table = document.querySelector('table'); if (!table) return 'table=missing'; const label = (el) => (el.textContent || '').replace(/\\s+/g, ' ').trim().toLowerCase(); const controls = (root) => Array.from(root.querySelectorAll('button, a, [role=button]')); const rows = Array.from(table.querySelectorAll('tbody tr')); const has = (row, name) => controls(row).some((el) => label(el) === name); const complete = rows.length > 0 && rows.every((row) => has(row, 'update') && has(row, 'delete')); const anyIn = (name) => controls(table).some((el) => label(el) === name); return ['rows=' + rows.length, 'rowActions=' + (rows.length === 0 ? 'none' : complete ? 'complete' : 'incomplete'), 'saveOnLoad=' + (anyIn('save') ? 'present' : 'absent'), 'cancelOnLoad=' + (anyIn('cancel') ? 'present' : 'absent')].join(' ');",
"output": "rowActions=complete saveOnLoad=absent cancelOnLoad=absent",
"timeout": 15000
}
}
]
},
{
"testId": "env-vars-add-variable-form-secret-toggle",
"description": "The Add Variable form sits inline below the variables table with nothing to expand, labels its two inputs Key Name and Value as the docs call them, and masks the Value field as you type once the Secret toggle is on. The submit control is checked for existence by its Add Variable label and never clicked, so the run creates no variable.",
"before": "login.spec.json",
"steps": [
{
"description": "Open the Environment Variables settings page",
"goTo": "https://app.gopromptless.ai/settings"
},
{
"description": "Wait for the Add Variable form's Key Name input to render",
"find": {
"selector": "input[placeholder='e.g. TEST_ACCOUNT_USERNAME']",
"timeout": 20000
}
},
{
"description": "The Add Variable form is already present with nothing to expand: both documented inputs exist, the Value field starts unmasked, the Secret label matches its documented wording, and the submit control reads Add Variable",
"runBrowserScript": {
"script": "const key = document.querySelector('input[placeholder=\"e.g. TEST_ACCOUNT_USERNAME\"]'); const value = document.querySelector('input[placeholder=\"Variable value\"]'); const own = (el) => Array.from(el.childNodes).filter((n) => n.nodeType === 3).map((n) => n.textContent).join(' ').replace(/\\s+/g, ' ').trim(); let form = null; if (key && value) { const ancestors = new Set(); for (let el = key; el; el = el.parentElement) ancestors.add(el); for (let el = value; el; el = el.parentElement) { if (ancestors.has(el)) { form = el; break; } } } const labelled = (name) => form ? (Array.from(form.querySelectorAll('*')).some((el) => own(el) === name) ? 'present' : 'missing') : 'no-form'; const secret = Array.from(document.querySelectorAll('label')).find((l) => (l.textContent || '').replace(/\\s+/g, ' ').trim() === 'Secret (value will be hidden after saving)'); const submit = Array.from(document.querySelectorAll('button, input[type=submit]')).find((el) => (el.textContent || el.value || '').replace(/\\s+/g, ' ').trim().toUpperCase() === 'ADD VARIABLE'); return ['keyInput=' + (key ? 'present' : 'missing'), 'valueInput=' + (value ? 'present' : 'missing'), 'keyLabel=' + labelled('Key Name'), 'valueLabel=' + labelled('Value'), 'valueType=' + (value ? value.type : 'n-a'), 'secretLabel=' + (secret ? 'present' : 'missing'), 'submit=' + (submit ? 'present' : 'missing')].join(' ');",
"output": "keyInput=present valueInput=present keyLabel=present valueLabel=present valueType=text secretLabel=present submit=present",
"timeout": 15000
}
},
{
"description": "Focus the Key Name input",
"find": {
"selector": "input[placeholder='e.g. TEST_ACCOUNT_USERNAME']",
"click": true,
"timeout": 15000
}
},
{
"description": "Type an inert sentinel key that is never submitted",
"type": "DOC_DETECTIVE_ENV_VARS_SPEC_NOT_SAVED"
},
{
"description": "Turn on the Secret toggle by clicking its label",
"find": {
"elementText": "/^Secret \\(value will be hidden after saving\\)$/",
"click": true,
"timeout": 15000
}
},
{
"description": "The Value field became a masked input, which matches what the docs promise",
"runBrowserScript": {
"script": "const value = document.querySelector('input[placeholder=\"Variable value\"]'); return 'valueType=' + (value ? value.type : 'missing');",
"output": "valueType=password",
"timeout": 15000
}
},
{
"description": "Focus the now-masked Value field",
"find": {
"selector": "input[placeholder='Variable value']",
"click": true,
"timeout": 15000
}
},
{
"description": "Type an inert value; nothing here submits the form",
"type": "doc-detective-not-saved"
},
{
"description": "The value stayed masked while being typed, and the sentinel key never reached the variables table -- so this run created no environment variable",
"runBrowserScript": {
"script": "const value = document.querySelector('input[placeholder=\"Variable value\"]'); const table = document.querySelector('table'); const cells = table ? Array.from(table.querySelectorAll('tbody td')) : []; const leaked = cells.some((td) => (td.textContent || '').includes('DOC_DETECTIVE_ENV_VARS_SPEC_NOT_SAVED')); return ['valueStillMasked=' + (value ? (value.type === 'password' ? 'yes' : 'no') : 'missing'), 'sentinelInTable=' + (leaked ? 'yes' : 'no')].join(' ');",
"output": "valueStillMasked=yes sentinelInTable=no",
"timeout": 15000
}
}
]
}
]
}
20 changes: 9 additions & 11 deletions src/content/docs/docs/scale/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type: reference
tags:
- scale
- reference
timestamp: "2026-07-10T17:59:48Z"
timestamp: "2026-07-27T00:00:00Z"
sidebar:
hidden: false
order: 34
Expand All @@ -20,19 +20,17 @@ Environment variables store credentials, API keys, and configuration values that
## Add environment variables

<Steps>
1. **Open Settings.** Navigate to the [Settings page](https://app.gopromptless.ai/settings) in your Promptless dashboard.
1. **Open Settings.** Navigate to the [Settings page](https://app.gopromptless.ai/settings) in your Promptless dashboard. Settings opens on **Environment Variables**, which also appears in the tab row.

2. **Find Environment Variables.** Select the **Environment Variables** section to view and manage your variables.
2. **Enter a key and value.** The **Add Variable** form sits on the page below your existing variables. Type a **Key Name** and a **Value**. Use clear, descriptive names that indicate the variable's purpose.

3. **Add a Variable.** Click the **Add Variable** button. Enter a name and value for your variable. Use clear, descriptive names that indicate the variable's purpose.
3. **Mark sensitive values as secret.** For passwords, API keys, and other sensitive values, turn on the **Secret** toggle, which masks the **Value** field as you type.

4. **Mark Sensitive Values as Secret.** For passwords, API keys, and other sensitive values, check the **Secret** option. Secret values are encrypted and hidden in the dashboard after saving.

5. **Save Changes.** Click **Save** to store your environment variables.
4. **Submit the variable.** Click **Add Variable**. The new variable appears in the variables table above the form.
</Steps>

<figure>
<img src="https://promptless-customer-doc-assets.s3.us-east-2.amazonaws.com/docs-images/org_2lvkgU9erOFxYhtEVVC0ymPrPdF/env-vars-settings-page-613d84b6.png" alt="Environment Variables settings page showing existing variables and the Add Variable form" />
<img src="https://promptless-customer-doc-assets.s3.us-east-2.amazonaws.com/docs-images/org_3DaVKUzHgjyjaODgCPaDmjXezqp/env-vars-settings-page-279aa2a4.png" alt="Promptless Settings page with Environment Variables selected, showing the variables table with Key, Value, Created, and Actions columns, Update and Delete buttons on each row, and an empty Add Variable form below the table" />

<figcaption>Environment Variables settings page</figcaption>
</figure>
Expand All @@ -48,7 +46,7 @@ Environment variables store credentials, API keys, and configuration values that
</Aside>

<figure>
<img src="https://promptless-customer-doc-assets.s3.us-east-2.amazonaws.com/docs-images/org_2lvkgU9erOFxYhtEVVC0ymPrPdF/env-vars-add-form-6a49cb82.png" alt="Add Variable form with Secret checkbox enabled" />
<img src="https://promptless-customer-doc-assets.s3.us-east-2.amazonaws.com/docs-images/org_3DaVKUzHgjyjaODgCPaDmjXezqp/env-vars-add-form-a3c369f3.png" alt="Add Variable form, outlined in red, with the Key Name field set to MY_API_TOKEN, a masked value, and the Secret toggle turned on" />

<figcaption>Adding a secret environment variable</figcaption>
</figure>
Expand All @@ -71,8 +69,8 @@ For [Promptless Capture](/docs/get-the-most-out/screenshots), add these variable

## Update and delete variables

To update an existing variable, locate it in the Environment Variables section and edit its value. For secret variables, you'll need to re-enter the entire value since the original is not displayed.
To update an existing variable, locate it in the variables table, click the **Update** button in the **Actions** column, edit the value, and click **Save**. For secret variables, re-enter the entire value — Promptless doesn't display the original.

To delete a variable, click the delete icon next to the variable. Deleted variables are immediately removed and will no longer be available to the Promptless agent.
To delete a variable, click the **Delete** button in its row of the **Actions** column. Deleted variables are immediately removed and are no longer available to the Promptless agent.

Need help? Contact us at [help@gopromptless.ai](mailto\:help@gopromptless.ai).
Loading