Skip to content

Commit 1420d46

Browse files
Merge pull request #210 from oriontech-me/feature/issue-185-prompt-template-component-regression
test(core-components): consolidate prompt template regression spec
2 parents 5d3d73c + 2b409a4 commit 1420d46

6 files changed

Lines changed: 450 additions & 396 deletions

File tree

QA-CHECKLIST.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,10 @@
165165
- [x] Dismiss button on the Files field clears the value → `core-components/chat-input-files-field-regression.spec.ts`
166166

167167
#### 3.2 Prompt Template
168-
- [-] Prompt with variables in curly braces
169-
- [-] Prompt modal
170-
- [-] Dynamic port generated when adding a variable to the prompt
171-
- [-] Removing a variable from the prompt deletes the corresponding port
168+
- [x] Prompt with variables in curly braces`core-components/prompt-template-component-regression.spec.ts`
169+
- [x] Prompt modal opens, accepts edits, and changes persist → `core-components/prompt-template-component-regression.spec.ts`
170+
- [x] Dynamic port generated when adding a variable to the prompt`core-components/prompt-template-component-regression.spec.ts`
171+
- [x] Removing a variable from the prompt deletes the corresponding port`core-components/prompt-template-component-regression.spec.ts`
172172

173173
#### 3.3 API Request (HTTP)
174174
- [x] Renders on canvas with URL and API Response handles → `core-components/api-request-component-regression.spec.ts`

QA-SCENARIOS-GUIDE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,11 +520,11 @@
520520

521521
## 10. Core Components — Prompt Template
522522

523-
**Files:** `core/regression/generalBugs-prompt.spec.ts`, `core/features/prompt-dynamic-variables.spec.ts`
523+
**Files:** `core-components/prompt-template-component-regression.spec.ts`
524524

525525
---
526526

527-
### 10.1 Prompt with variables in curly braces `[-]`
527+
### 10.1 Prompt with variables in curly braces `[x]`
528528

529529
**Objective:** Verify that `{name}` variables in the prompt create dynamic handles.
530530

@@ -539,7 +539,7 @@
539539

540540
---
541541

542-
### 10.2 Removing variable from prompt deletes corresponding port `[-]`
542+
### 10.2 Removing variable from prompt deletes corresponding port `[x]`
543543

544544
**Step by step:**
545545
1. Create prompt with variable `{name}` (handle `name` created).
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# Prompt Template Component — Regression
2+
3+
**Last validated:** Langflow 1.10.x
4+
5+
---
6+
7+
## What this test validates *(required)*
8+
9+
Validates the **Prompt Template** component end-to-end via 6 scenarios:
10+
11+
1. **Canvas rendering** — the node renders on a blank flow with the correct `prompt` output handle.
12+
2. **Dynamic input handles from `{variable}` placeholders** — typing `{name}` and `{profession}` in the template creates one input handle per placeholder, named after the variable.
13+
3. **Removing a variable removes its handle** — replacing `Hello {name}!` with `Hello world!` drops the `name` handle and decreases the total handle count.
14+
4. **Replacing a variable updates handles in place** — switching `{role}` for `{title}` while keeping `{name}` causes the old handle to disappear and the new one to appear.
15+
5. **Clearing all variables removes every dynamic handle** — replacing `{a} and {b} and {c}` with a variable-free string drops the dynamic handle count to zero.
16+
6. **Modal persistence (UI + backend)** — text entered in the prompt modal and saved via `genericModalBtnSave` is still present (in the sanitized preview and in the textarea after re-entering edit mode) when the modal is reopened, **and** the autosaved flow at `GET /api/v1/flows/{id}` contains the same string in `node.data.node.template.template.value` for the Prompt Template node.
17+
18+
If any of these tests fails, the Prompt Template component is broken in one of its core contracts: rendering on the canvas, the regex that extracts `{variable}` placeholders from the template, the dynamic handle generation, or the modal's save-and-persist flow.
19+
20+
---
21+
22+
## Tags *(required)*
23+
24+
All 6 tests: `@stable` `@release` `@regression` `@components`
25+
26+
---
27+
28+
## Step by step *(required)*
29+
30+
Every test starts with `addPromptComponent(page)` which:
31+
1. Bootstraps the app (`awaitBootstrapTest`)
32+
2. Clicks `blank-flow`
33+
3. Fills `sidebar-search-input` with `prompt` and waits for `add-component-button-prompt-template`
34+
4. Clicks the add button
35+
5. Calls `adjustScreenView(page)`
36+
6. Asserts exactly one node is on the canvas
37+
38+
Tests 2–6 use the helper `setPromptTemplate(page, value)` which:
39+
1. Clicks `button_open_prompt_modal`
40+
2. If the sanitized preview `edit-prompt-sanitized` is visible (post-save state), clicks it to re-enter edit mode
41+
3. Waits for the textarea `modal-promptarea_prompt_template` (unique to the prompt modal, used as anchor instead of `[role="dialog"]`) to be visible
42+
4. Selects all in the textarea (`Ctrl+A`) and fills `value`
43+
5. Clicks `genericModalBtnSave` and waits for the textarea testid to be hidden — that disappearance is the reliable signal that the modal closed. Downstream assertions then auto-retry on the expected handle state.
44+
45+
### 1. `renders on canvas with output handle`
46+
- Asserts `title-Prompt Template` is visible.
47+
- Asserts the right-side `handle-prompt template-shownode-prompt-right` handle is visible.
48+
- Asserts exactly one node on the canvas (`react-flow__node` count === 1).
49+
50+
### 2. `variables in curly braces generate dynamic input handles`
51+
- Calls `setPromptTemplate` with `Hello {name}, your job is {profession}.`.
52+
- Asserts both `handle-prompt template-shownode-name-left` and `handle-prompt template-shownode-profession-left` are visible.
53+
- Asserts the dynamic-handle locator (`-shownode-*-left` only) has count exactly 2 — sanity check that no extra handles leaked in.
54+
55+
### 3. `removing a variable removes its input handle`
56+
- Sets the template to `Hello {name}!` and asserts the `name` handle is visible and the dynamic-handle count is exactly 1.
57+
- Sets the template to `Hello world!`.
58+
- Asserts the `name` handle has zero matches and the dynamic-handle count is exactly 0.
59+
60+
### 4. `replacing a variable updates handles accordingly`
61+
- Sets the template to `Hello {name}, you are {role}.` and asserts both `name` and `role` handles are visible.
62+
- Sets the template to `Hello {name}, you are {title}.`.
63+
- Asserts `name` is still visible, `role` has zero matches, and `title` is visible.
64+
65+
### 5. `clearing the template removes all dynamic handles`
66+
- Sets the template to `{a} and {b} and {c}` and asserts the dynamic-handle count is exactly 3.
67+
- Sets the template to `No variables here.`.
68+
- Asserts the dynamic-handle count is exactly 0.
69+
70+
### 6. `modal edits persist in UI and in saved flow`
71+
- Sets the template to `Persisted prompt text {topic}.` via `setPromptTemplate`.
72+
- Asserts `handle-prompt template-shownode-topic-left` is visible (confirms save succeeded).
73+
- **UI layer:** reopens the modal, asserts `edit-prompt-sanitized` contains the saved text, clicks the preview to re-enter edit mode, asserts the textarea has the exact saved value via `toHaveValue`.
74+
- **Backend layer:** extracts the flow id from the URL, then polls `GET /api/v1/flows/{id}` via `page.request` (inherits session cookies — the endpoint requires session auth) until the Prompt Template node's `template.template.value` equals the saved string. Catches regressions where the modal shows the value but autosave does not flush it to the database.
75+
76+
---
77+
78+
## Validation criterion *(required)*
79+
80+
- `title-Prompt Template` is visible after adding the component to a blank flow
81+
- The right-side output handle `handle-prompt template-shownode-prompt-right` is visible
82+
- For each `{variable}` saved in the template, a corresponding left-side handle `handle-prompt template-shownode-{variable}-left` is rendered
83+
- Removing a `{variable}` from the template removes the corresponding handle
84+
- Replacing one variable with another removes the old handle and creates a new one
85+
- Saving a template via `genericModalBtnSave` makes the value retrievable on the next modal open — both in the sanitized preview and in the textarea after re-entering edit mode
86+
- The autosaved flow at `GET /api/v1/flows/{id}` contains the saved template string at `node.data.node.template.template.value` for the Prompt Template node
87+
88+
---
89+
90+
## External dependencies *(required)*
91+
92+
- `src/frontend/src/modals/promptModal/``genericModalBtnSave` button, `edit-prompt-sanitized` preview, and the textarea that holds the editable template; changes here break tests 2–6
93+
- `src/frontend/src/CustomNodes/GenericNode/components/parameterRenderComponent/components/promptAreaComponent/``button_open_prompt_modal` trigger on the node inspector; breaks tests 2–6
94+
- `src/lfx/src/lfx/interface/utils.py``extract_input_variables_from_prompt()`: derives the variable list from the template string using Python's `string.Formatter().parse()` (not a regex); breaks tests 2–5
95+
- `src/lfx/src/lfx/base/prompts/api_utils.py``validate_prompt()` and `_check_input_variables()`: validation layer around the extracted variables; breaks tests 2–5
96+
- `src/lfx/src/lfx/components/models_and_agents/prompt.py``PromptComponent` definition (`display_name="Prompt Template"`, template field) and `update_build_config()` that synchronizes template ↔ input fields; breaks tests 2–6 and the backend assertion in test 6
97+
- `src/frontend/src/CustomNodes/GenericNode/` — dynamic handle rendering for `handle-{component}-shownode-{var}-left`; breaks tests 1–5
98+
- `GET /api/v1/flows/{id}` — flow read endpoint backing the autosave round-trip; the response shape `data.nodes[].data.node.template.template.value` is what test 6 asserts. A rename of the inner `template.template` nesting, or a change to `node.data.type` away from `"Prompt Template"`, breaks the backend assertion.
99+
100+
---
101+
102+
## What this test does not cover *(optional)*
103+
104+
- Prompt rendering/execution behind an LLM (covered by `llm-agents` specs such as `memory-history-regression.spec.ts`)
105+
- Tool Mode interaction (covered by `tool-mode.spec.ts`)
106+
- Cross-component data flow (covered by `flow-functionality/` specs)
107+
- Variable name validation (e.g., reserved keywords, special characters)
108+
109+
---
110+
111+
## Preconditions *(optional)*
112+
113+
- Langflow running and accessible at `PLAYWRIGHT_BASE_URL`
114+
- No API key required — the Prompt Template component is a pure templating layer with no LLM calls
115+
- Auto-login mode is assumed: test 6 uses `page.request.get` so the backend call inherits the page's session cookies. In an environment with explicit auth, the test should still work because the page is authenticated via the normal login flow before the assertion runs.
116+
117+
---
118+
119+
## When to review this test *(optional)*
120+
121+
- If the `button_open_prompt_modal`, `genericModalBtnSave`, or `edit-prompt-sanitized` testids are renamed in the prompt modal frontend
122+
- If the dynamic handle testid pattern (`handle-prompt template-shownode-{var}-left`) changes — e.g., if `"prompt template"` (with space) is replaced by `"prompt-template"` (with dash) or a different node-type slug
123+
- If the `{variable}` extraction regex in `extract_input_variables_from_prompt` changes its handling of escape sequences, whitespace, or nested braces
124+
125+
---
126+
127+
## Notes *(optional)*
128+
129+
- Test 6 (modal persistence) asserts persistence at three layers: the sanitized preview (`edit-prompt-sanitized`, which is the post-save render), the textarea value reached by clicking back into edit mode, and the autosaved flow JSON fetched via `GET /api/v1/flows/{id}`. All three must match the saved string for the test to pass.
130+
- The `setPromptTemplate` helper deliberately handles the post-save "preview" state by detecting `edit-prompt-sanitized` and clicking through it. This is what makes the helper safe to call multiple times in a row (tests 3, 4, 5 all rely on this).
131+
- All assertions use the literal node-type slug `"prompt template"` (with space) in the testid, matching how the frontend renders the type. The leading space inside `handle-prompt template-...` is intentional and not a typo.

0 commit comments

Comments
 (0)