@ihyeon/flow-qa 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/dist/src/ui/public/app.js +19 -3
- package/dist/src/ui/public/i18n.js +5 -0
- package/dist/src/ui/public/index.html +1 -1
- package/docs/mobile.md +1 -1
- package/docs/releases.md +18 -0
- package/docs/ui.md +11 -3
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -16,7 +16,7 @@ CLI와 `127.0.0.1` 전용 웹 UI를 제공합니다. UI는 영어로 시작하
|
|
|
16
16
|
Node.js 24.x(24.22.1 이상) 또는 26.12.1 이상이 필요합니다. 브라우저는 첫 웹 실행 전에 설치합니다.
|
|
17
17
|
|
|
18
18
|
```sh
|
|
19
|
-
npm install -g @ihyeon/flow-qa@0.2.
|
|
19
|
+
npm install -g @ihyeon/flow-qa@0.2.9
|
|
20
20
|
flow-qa browser install
|
|
21
21
|
flow-qa ui --demo
|
|
22
22
|
```
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Flow QA is available as a CLI and a web UI bound to `127.0.0.1`. Provide a targe
|
|
|
16
16
|
Node.js 24.x (24.22.1 or later) or 26.12.1 or later is required. Install Chromium before the first web run:
|
|
17
17
|
|
|
18
18
|
```sh
|
|
19
|
-
npm install -g @ihyeon/flow-qa@0.2.
|
|
19
|
+
npm install -g @ihyeon/flow-qa@0.2.9
|
|
20
20
|
flow-qa browser install
|
|
21
21
|
flow-qa ui --demo
|
|
22
22
|
```
|
|
@@ -143,7 +143,16 @@
|
|
|
143
143
|
const reqTitle = el('h3', '', t('app.requirements')); host.append(reqTitle);
|
|
144
144
|
const reqList = el('ol', 'compact-list'); for (const req of suite.requirements || []) reqList.append(el('li', '', `${req.id} · ${req.text}`)); host.append(reqList);
|
|
145
145
|
host.append(el('h3', 'case-title', t('app.caseSteps')));
|
|
146
|
-
|
|
146
|
+
const cases = suite.cases || [];
|
|
147
|
+
if (cases.length) {
|
|
148
|
+
const actions = el('div', 'actions');
|
|
149
|
+
const expand = el('button', 'button quiet', t('scenario.expandCases')); expand.type = 'button'; expand.id = 'expand-cases';
|
|
150
|
+
expand.addEventListener('click', () => host.querySelectorAll('details.case-review').forEach((detail) => { detail.open = true; }));
|
|
151
|
+
const collapse = el('button', 'button quiet', t('scenario.collapseCases')); collapse.type = 'button'; collapse.id = 'collapse-cases';
|
|
152
|
+
collapse.addEventListener('click', () => host.querySelectorAll('details.case-review').forEach((detail) => { detail.open = false; }));
|
|
153
|
+
actions.append(expand, collapse); host.append(actions);
|
|
154
|
+
}
|
|
155
|
+
for (const [index, item] of cases.entries()) {
|
|
147
156
|
const detail = el('details', 'case-review'); detail.open = openCases ? !!openCases[index] : index === 0;
|
|
148
157
|
detail.append(el('summary', '', `${item.id} · ${item.title}${item.questions?.length ? ` · ${t('app.caseBlocked')}` : ''}`));
|
|
149
158
|
detail.append(el('p', 'hint', t('app.linkedRequirements', { ids: (item.requirementIds || []).join(', ') || t('app.none') })));
|
|
@@ -217,8 +226,14 @@
|
|
|
217
226
|
const runs = app.state?.runs || [];
|
|
218
227
|
if (!runs.length) { host.append(el('p', 'empty', t(app.state?.active ? 'app.historyActiveEmpty' : 'app.historyEmpty'))); return; }
|
|
219
228
|
const status = $('history-status-filter').value;
|
|
220
|
-
const
|
|
221
|
-
|
|
229
|
+
const query = $('history-search').value.trim().toLowerCase();
|
|
230
|
+
const matchingRuns = runs.filter((run) => {
|
|
231
|
+
const matchesStatus = !status || run.status === status;
|
|
232
|
+
const matchesSearch = !query || [run.suiteId, run.runId, run.target?.name]
|
|
233
|
+
.some((field) => String(field ?? '').toLowerCase().includes(query));
|
|
234
|
+
return matchesStatus && matchesSearch;
|
|
235
|
+
});
|
|
236
|
+
if (!matchingRuns.length) { host.append(el('p', 'empty', t(query ? 'app.historyNoSearchMatches' : 'app.historyNoStatusMatches'))); return; }
|
|
222
237
|
for (const run of matchingRuns) {
|
|
223
238
|
const row = el('div', 'list-row'); const copy = el('div'); copy.append(el('strong', '', `${run.suiteId} · ${i18n.status(run.status)}`), el('small', '', t('app.runMeta', { date: formatDate(run.startedAt), target: targetDisplay(run.target), passed: run.passedCount ?? 0, total: run.caseCount ?? 0, id: run.runId })));
|
|
224
239
|
const button = el('button', 'button', t('app.viewReport')); button.type = 'button'; button.disabled = run.status === 'running' || run.status === 'stopping'; button.addEventListener('click', () => loadReport(run.runId)); row.append(copy, button); host.append(row);
|
|
@@ -400,6 +415,7 @@
|
|
|
400
415
|
window.addEventListener('beforeunload', warnBeforeUnload);
|
|
401
416
|
document.querySelectorAll('[data-view]').forEach((button) => button.addEventListener('click', () => view(button.dataset.view)));
|
|
402
417
|
$('library-search').addEventListener('input', renderLibrary);
|
|
418
|
+
$('history-search').addEventListener('input', renderHistory);
|
|
403
419
|
$('history-status-filter').addEventListener('change', renderHistory);
|
|
404
420
|
$('nav-toggle').addEventListener('click', () => { const open = $('sidebar').classList.toggle('nav-open'); $('nav-toggle').setAttribute('aria-expanded', String(open)); });
|
|
405
421
|
$('library-shortcut').addEventListener('click', () => view('library'));
|
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
'scenario.prompt': ['Download generation prompt', '생성 프롬프트 다운로드'],
|
|
37
37
|
'scenario.reviewTitle': ['Review cases', '케이스 검토'],
|
|
38
38
|
'scenario.reviewHelp': ['Open each case to inspect its actions and expected results.', '각 케이스를 펼쳐 행동과 기대 결과를 살펴보세요.'],
|
|
39
|
+
'scenario.expandCases': ['Expand all cases', '케이스 모두 펼치기'],
|
|
40
|
+
'scenario.collapseCases': ['Collapse all cases', '케이스 모두 접기'],
|
|
39
41
|
'scenario.importFiles': ['Import case files', '케이스 파일 가져오기'],
|
|
40
42
|
'scenario.importJson': ['TC JSON', 'TC JSON'],
|
|
41
43
|
'scenario.importMarkdown': ['Source Markdown (optional)', '원본 Markdown (선택)'],
|
|
@@ -77,6 +79,8 @@
|
|
|
77
79
|
'history.intro': ['Only runs that actually started appear here. Once results are saved, you can view the detailed report.', '실제로 시작된 실행만 표시합니다. 결과가 저장되면 상세 보고서를 볼 수 있습니다.'],
|
|
78
80
|
'history.title': ['Runs', '실행 목록'],
|
|
79
81
|
'history.help': ['Check the completed report for the final status.', '상태는 완료된 보고서 기준으로 확인하세요.'],
|
|
82
|
+
'history.searchLabel': ['Search runs', '실행 기록 검색'],
|
|
83
|
+
'history.searchPlaceholder': ['Suite ID, run ID, or target name', '스위트 ID, 실행 ID 또는 대상 이름'],
|
|
80
84
|
'history.statusFilter': ['Run status', '실행 상태'],
|
|
81
85
|
'history.statusAll': ['All statuses', '전체 상태'],
|
|
82
86
|
'history.report': ['Detailed report', '상세 보고서'],
|
|
@@ -214,6 +218,7 @@
|
|
|
214
218
|
'app.historyActiveEmpty': ['First run in progress. Its report will appear here when complete.', '첫 실행을 처리 중입니다. 완료되면 이곳에 보고서가 표시됩니다.'],
|
|
215
219
|
'app.historyEmpty': ['No runs yet. Validate cases and select a target to start the first run.', '아직 실행 기록이 없습니다. 케이스를 검증하고 대상을 선택해 첫 실행을 시작하세요.'],
|
|
216
220
|
'app.historyNoStatusMatches': ['No runs match this status. Choose another status or All statuses.', '이 상태에 해당하는 실행이 없습니다. 다른 상태나 전체 상태를 선택하세요.'],
|
|
221
|
+
'app.historyNoSearchMatches': ['No runs match your search and status filters. Change the search or status.', '검색어와 상태 조건에 맞는 실행이 없습니다. 검색어나 상태를 바꿔보세요.'],
|
|
217
222
|
'app.noTarget': ['no target', '대상 없음'],
|
|
218
223
|
'app.runMeta': ['{date} · {target} · {passed}/{total} passed · {id}', '{date} · {target} · {passed}/{total} 통과 · {id}'],
|
|
219
224
|
'app.viewReport': ['View report', '보고서 보기'],
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
</section>
|
|
93
93
|
<section id="view-history" class="view" hidden>
|
|
94
94
|
<div class="page-heading"><p class="eyebrow" data-i18n="history.eyebrow">03 / RUNS</p><h1 data-i18n="nav.history">Run history</h1><p data-i18n="history.intro">Only runs that actually started appear here. Once results are saved, you can view the detailed report.</p></div>
|
|
95
|
-
<section class="list-section"><div class="section-head"><span class="section-number">01</span><div><h2 data-i18n="history.title">Runs</h2><p data-i18n="history.help">Check the completed report for the final status.</p></div></div><div class="section-body form-stack"><label for="history-status-filter" data-i18n="history.statusFilter">Run status</label><select id="history-status-filter" aria-controls="history-list"><option value="" data-i18n="history.statusAll">All statuses</option><option value="passed" data-i18n="status.passed">passed</option><option value="failed" data-i18n="status.failed">failed</option><option value="blocked" data-i18n="status.blocked">blocked</option><option value="error" data-i18n="status.error">error</option><option value="interrupted" data-i18n="status.interrupted">interrupted</option></select><div id="history-list" class="list-body"></div></div></section>
|
|
95
|
+
<section class="list-section"><div class="section-head"><span class="section-number">01</span><div><h2 data-i18n="history.title">Runs</h2><p data-i18n="history.help">Check the completed report for the final status.</p></div></div><div class="section-body form-stack"><label for="history-search" data-i18n="history.searchLabel">Search runs</label><input id="history-search" type="search" aria-controls="history-list" placeholder="Suite ID, run ID, or target name" data-i18n-placeholder="history.searchPlaceholder"><label for="history-status-filter" data-i18n="history.statusFilter">Run status</label><select id="history-status-filter" aria-controls="history-list"><option value="" data-i18n="history.statusAll">All statuses</option><option value="passed" data-i18n="status.passed">passed</option><option value="failed" data-i18n="status.failed">failed</option><option value="blocked" data-i18n="status.blocked">blocked</option><option value="error" data-i18n="status.error">error</option><option value="interrupted" data-i18n="status.interrupted">interrupted</option></select><div id="history-list" class="list-body"></div></div></section>
|
|
96
96
|
<section id="report-panel" class="report-panel" hidden><div class="section-head"><span class="section-number">02</span><div><h2 data-i18n="history.report">Detailed report</h2><p id="report-heading"></p></div></div><div class="section-body"><div class="actions"><button type="button" id="report-md" class="button" data-i18n="history.downloadMarkdown">Download Markdown</button><button type="button" id="report-json" class="button quiet" data-i18n="history.downloadJson">Download JSON</button></div><p class="hint" data-i18n="history.evidenceHint">The report summarizes results. Open or download screenshots and recordings from each attempt. Evidence files are not included in report downloads.</p><div id="report-content"></div></div></section>
|
|
97
97
|
</section>
|
|
98
98
|
<section id="view-settings" class="view" hidden>
|
package/docs/mobile.md
CHANGED
|
@@ -9,7 +9,7 @@ Choose **Mobile** on the scenario screen, describe the flow, and generate or dow
|
|
|
9
9
|
With the installed CLI:
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
npm install -g @ihyeon/flow-qa@0.2.
|
|
12
|
+
npm install -g @ihyeon/flow-qa@0.2.9
|
|
13
13
|
flow-qa init ./my-qa
|
|
14
14
|
# Write your mobile flow in my-qa/flows/my-flow.md first.
|
|
15
15
|
flow-qa plan flows/my-flow.md --platform mobile --prompt-only --workspace ./my-qa
|
package/docs/releases.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
The alpha entries below are historical release records. They document earlier package versions and checks.
|
|
4
4
|
|
|
5
|
+
## 0.2.9: search run history
|
|
6
|
+
|
|
7
|
+
Adds Search runs to run history, matching suite IDs, run IDs, and target names with case-insensitive partial search. Surrounding whitespace is ignored, and the search combines with the existing status filter. Clearing the query preserves the selected status. The current query stays through navigation, language changes, and automatic history updates; open reports and downloads remain available. Search covers only the most recent 50 reports already loaded by the UI.
|
|
8
|
+
|
|
9
|
+
Locally verified on macOS with Node.js 24.22.1 on 2026-11-02: 92 tests, type checking, UI syntax and design-system audit, and real Chromium search checks using report fixtures alongside a real passing run. All three fields, Korean target names, case and whitespace handling, combined status filtering, empty results, clearing, navigation, language changes, new reports, filtered report opening and download, and a 390px viewport passed. Existing UI and demo checks, package validation, and a fresh tarball installation with three passing browser cases also passed. No model calls were used.
|
|
10
|
+
|
|
11
|
+
- Package: [`@ihyeon/flow-qa@0.2.9`](https://www.npmjs.com/package/@ihyeon/flow-qa/v/0.2.9)
|
|
12
|
+
- Release: [GitHub 0.2.9](https://github.com/hyeonse-swing/flow-qa/releases/tag/v0.2.9)
|
|
13
|
+
|
|
14
|
+
## 0.2.8: expand and collapse all case details
|
|
15
|
+
|
|
16
|
+
Adds Expand all cases and Collapse all cases to Scenario case review. The controls appear when cases are available and change only the case details. Individual toggles, the first-case-open default on loading, and expansion state across language changes and navigation remain available. Bulk actions preserve the draft, JSON editor disclosure, review confirmation, and execution readiness.
|
|
17
|
+
|
|
18
|
+
Locally verified on macOS with Node.js 24.22.1 on 2026-10-28: 92 tests, type checking, UI syntax and design-system audit, and real Chromium checks for empty and loaded reviews, bulk and individual toggles, mixed expansion state across language changes, keyboard activation, navigation, unchanged draft/review state, and a 390px viewport. Existing UI and demo checks, package validation, and a fresh tarball installation with three passing browser cases also passed. No model calls were used.
|
|
19
|
+
|
|
20
|
+
- Package: [`@ihyeon/flow-qa@0.2.8`](https://www.npmjs.com/package/@ihyeon/flow-qa/v/0.2.8)
|
|
21
|
+
- Release: [GitHub 0.2.8](https://github.com/hyeonse-swing/flow-qa/releases/tag/v0.2.8)
|
|
22
|
+
|
|
5
23
|
## 0.2.7: filter run history by status
|
|
6
24
|
|
|
7
25
|
Adds a Run status selector to run history for passed, failed, blocked, error, and interrupted reports. All statuses restores the loaded list, and a separate message explains when the selected status has no matches. The selected status stays through navigation, language changes, and automatic report updates. This filters the UI's existing most recent 50 reports and preserves the open report, downloads, and scenario review state.
|
package/docs/ui.md
CHANGED
|
@@ -7,7 +7,7 @@ Describe a user flow, review cases, and configure a target when ready to run. We
|
|
|
7
7
|
Node.js 24.x (24.22.1 or later) or 26.12.1 or later is required. Node 25 is unsupported. Upgrade the Node runtime and restart any running UI process; updating Flow QA alone does not patch Node. Install Flow QA and start the web demo:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
npm install -g @ihyeon/flow-qa@0.2.
|
|
10
|
+
npm install -g @ihyeon/flow-qa@0.2.9
|
|
11
11
|
flow-qa browser install
|
|
12
12
|
flow-qa ui --demo
|
|
13
13
|
```
|
|
@@ -30,9 +30,9 @@ The UI starts in **English**, regardless of browser language. Switch to **한국
|
|
|
30
30
|
|
|
31
31
|
1. **Scenario:** Choose Web or Mobile and describe the initial state, actions, screen elements, and expected results. No target is required yet. If a planner is ready, ask it to create cases. Without a model, download the planning prompt and paste a JSON response from an AI you already use.
|
|
32
32
|
2. **Connections:** When ready, register a target name and web URL, or choose iOS/Android and enter an installed app's bundle/package ID and device. Planner and execution agent models have separate settings. Saving settings does not start an app or model request.
|
|
33
|
-
3. **Review and save cases:** Expand each case to read preconditions, actions, expected results, and unresolved questions. Editing the JSON keeps the linked flow; if that source flow changes, design the cases again. Planning and running are separate actions. Editing inputs or connection settings alone does not call a model.
|
|
33
|
+
3. **Review and save cases:** Expand each case, or use **Expand all cases**, to read preconditions, actions, expected results, and unresolved questions. **Collapse all cases** returns to the case titles. Editing the JSON keeps the linked flow; if that source flow changes, design the cases again. Planning and running are separate actions. Editing inputs or connection settings alone does not call a model.
|
|
34
34
|
4. **Run QA:** Review the saved case file, select a matching web/mobile target, and check the review confirmation before running. If the file or target settings change after review, reload and review them again. Fixed steps need no agent model. `act` and `assertAgent` require a compatible agent; missing models and unresolved questions are reported as blocked cases.
|
|
35
|
-
5. **Case library and Run history:** Save cases as new files, search by title, suite ID, or file name, and load them again.
|
|
35
|
+
5. **Case library and Run history:** Save cases as new files, search by title, suite ID, or file name, and load them again. Search run history by suite ID, run ID, or target name, combine it with a status filter, then open run details to see each case, attempt, and evidence; download the Markdown or JSON report.
|
|
36
36
|
|
|
37
37
|
The top bar shows planning, running, and stopping states, plus a cancel button. A late planning response cannot change the draft after cancellation. The UI does not estimate progress inside an individual browser action. If the server disconnects, reconnect; runs started in another tab also appear. Refreshing settings rereads targets and models, so save edits first.
|
|
38
38
|
|
|
@@ -46,6 +46,10 @@ From version `0.2.2`, the UI requests the browser's leave-page confirmation when
|
|
|
46
46
|
|
|
47
47
|
From version `0.2.4`, loading a suite from the library or importing valid case files also asks before replacing unsaved scenario or case content. **New JSON draft** asks before clearing unsaved JSON and keeps the scenario text. Cancel keeps the current content and selected import files. Unchanged saved cases and ordinary navigation between screens do not prompt; invalid imports still show their validation error without replacing anything.
|
|
48
48
|
|
|
49
|
+
### Expand or collapse case review
|
|
50
|
+
|
|
51
|
+
From version `0.2.8`, **Expand all cases** and **Collapse all cases** control the case details in Scenario. Individual case titles still toggle their own details. Language changes and navigation preserve which cases are open; loading a new suite keeps the original first-case-open default. These controls only change the view: they do not approve cases, modify the draft, or change the JSON editor disclosure. Review confirmation is still required before execution.
|
|
52
|
+
|
|
49
53
|
### Search saved cases
|
|
50
54
|
|
|
51
55
|
From version `0.2.6`, **Case library** filters saved suites as you type in **Search saved suites**. Search matches part of a title, suite ID, or file name, ignores letter case and surrounding whitespace, and supports Korean text. Clear the field to show all suites. The query stays while navigating, changing language, or receiving updated saved cases; it resets when the page reloads. Search covers the listed top-level case files, not individual steps or source Markdown.
|
|
@@ -54,6 +58,10 @@ From version `0.2.6`, **Case library** filters saved suites as you type in **Sea
|
|
|
54
58
|
|
|
55
59
|
From version `0.2.7`, **Run history → Run status** filters the loaded reports by passed, failed, blocked, error, or interrupted. Choose **All statuses** to restore the list. The selection stays while navigating, changing language, or receiving updated reports, and resets on page reload. The filter applies to the most recent 50 reports loaded by the UI; it does not search older history or individual case results. Filtering keeps the report already open and its downloads available.
|
|
56
60
|
|
|
61
|
+
### Search run history
|
|
62
|
+
|
|
63
|
+
From version `0.2.9`, **Run history → Search runs** matches part of a suite ID, run ID, or target name. Matching ignores letter case and surrounding whitespace, and supports Korean target names. Search combines with **Run status**; clear the search to return to the selected status. The query stays through navigation, language changes, and automatic report updates, and resets on page reload. Search covers the most recent 50 reports loaded by the UI, not older records, target URLs, or individual case content. Changing the query keeps the open report and its downloads available.
|
|
64
|
+
|
|
57
65
|
### Import existing case files
|
|
58
66
|
|
|
59
67
|
From version `0.2.1`, select a `flow-qa/suite-1` JSON file and, when it declares a source, its Markdown file in case review, then choose **Import case files**. The two file controls let you select files from different folders. For an error-to-test export, select `cases/error-to-test.json` and `flows/error-to-test.md`. A JSON file without a source can be imported alone or with a Markdown file.
|