diff --git a/TESTING.md b/TESTING.md index 6f8c450d..77c28aaa 100644 --- a/TESTING.md +++ b/TESTING.md @@ -2852,7 +2852,7 @@ hand-off and the comparisons) and `library-editor-visual.spec.mjs` with the rena ### Delete review and prompt-page polish (#512) -Found in the live test of #505/#507/#509. **D162** (beyond the concept, maintainer ruling 2026-10-29: delete was hard to +Found in the live test of #505/#507/#509. **D163** (beyond the concept, maintainer ruling 2026-10-29: delete was hard to find on a prompt's page): the prompt page heading ends with a **"⋯" More menu** button after Send to ComfyUI (`more-menu.mjs`: `aria-haspopup="menu"`, `aria-expanded`; Enter, Space or ArrowDown opens it on its first item, ArrowUp on its last; arrows, Home and End move; Escape closes it and returns focus to ⋯; Tab, an outside press or a choice diff --git a/tests/browser/concept-inventory.mjs b/tests/browser/concept-inventory.mjs index a1091b86..19edf093 100644 --- a/tests/browser/concept-inventory.mjs +++ b/tests/browser/concept-inventory.mjs @@ -421,7 +421,7 @@ export function measureInventory(scope) { description:when(description,()=>({className:description.className,text:description.textContent,...font(description),...edges(description)})), actions:when(actions,()=>({...layout(actions),...edges(actions), fullWidth:px(rect(actions).width)===px(rect(heading).width),stacked:copy?rect(actions).top>=rect(copy).bottom-0.5:null, - // D162: a closed menu's items are not heading actions. + // D163: a closed menu's items are not heading actions. buttons:[...actions.querySelectorAll('button')].filter(node=>!node.closest('[role="menu"]')).map(node=>({text:node.textContent.trim(),primary:node.classList.contains('ca-primary'), ...font(node),...edges(node),minHeight:getComputedStyle(node).minHeight,height:px(rect(node).height)}))}))}; } diff --git a/tests/browser/history-concept.spec.mjs b/tests/browser/history-concept.spec.mjs index c29517e3..ffd96385 100644 --- a/tests/browser/history-concept.spec.mjs +++ b/tests/browser/history-concept.spec.mjs @@ -26,7 +26,7 @@ const SECTIONS=['heading','history','noPageScroll']; */ export function mapHistoryConcept(reference) { const {history}=reference.oracle; - // D162 (#512): the heading as laid out with the More menu button (the oracle's heading). + // D163 (#512): the heading as laid out with the More menu button (the oracle's heading). return {...reference,heading:reference.oracle.heading,history:{...history, // D24: "N tracked runs" is the recorded window's `recorded_run_count`; the fixture records one run per image, so // the concept's "4 tracked runs" holds by construction (asserted on both documents below). @@ -121,7 +121,7 @@ async function conceptAsRecorded(page) { const add=[...document.querySelectorAll('.timeline-panel .row-actions > button')].find(node=>node.textContent==='+ Add negative'); const archived=add.cloneNode(false);archived.removeAttribute('data-action');archived.removeAttribute('data-prompt'); archived.setAttribute('aria-pressed','false');archived.textContent=label;add.after(archived); - // D162 (#512): the heading ends with the "⋯" More menu button, drawn as the concept's Edit metadata button. + // D163 (#512): the heading ends with the "⋯" More menu button, drawn as the concept's Edit metadata button. const edit=[...document.querySelectorAll('#main > .heading .heading-actions > button')].find(node=>node.textContent.trim()==='Edit metadata'); const moreButton=edit.cloneNode(false);moreButton.removeAttribute('data-action');moreButton.textContent='⋯';edit.parentElement.append(moreButton); window.__historyOracle={timeline,order:[...lanes].reverse(),texts,archived,moreButton}; diff --git a/tests/browser/workspace-library-delete.spec.mjs b/tests/browser/workspace-library-delete.spec.mjs index cc45b51d..6b6f0329 100644 --- a/tests/browser/workspace-library-delete.spec.mjs +++ b/tests/browser/workspace-library-delete.spec.mjs @@ -462,10 +462,10 @@ test('a failed review keeps the selection, and a selection nothing can change op expect(byText(await items(request),'Library extra 0000')).toBeDefined(); }); -// #512 (live test of #505/#507/#509): the prompt page's "⋯" More menu (D162), a gone prompt's page, single-prompt titles. +// #512 (live test of #505/#507/#509): the prompt page's "⋯" More menu (D163), a gone prompt's page, single-prompt titles. const more=page=>page.locator('#workspace-main .heading-actions').getByRole('button',{name:'More actions for this prompt',exact:true}); const moreMenu=page=>page.getByRole('menu',{name:'More actions for this prompt'}); -test('the prompt page\'s More menu opens Delete prompt…, by mouse and keyboard, and closes on Escape or outside (#512 D162)',async({page,request})=>{ +test('the prompt page\'s More menu opens Delete prompt…, by mouse and keyboard, and closes on Escape or outside (#512 D163)',async({page,request})=>{ const dual=byText(await items(request),'Dual role portrait'); await page.goto(`/prompt_manager/workspace#/library/${dual.id}`); const heading=page.locator('#workspace-main .heading-actions > button, #workspace-main .heading-actions > .more-menu > button'); @@ -495,7 +495,7 @@ test('the prompt page\'s More menu opens Delete prompt…, by mouse and keyboard expect(byText(await items(request),'Dual role portrait')?.id).toBe(dual.id); }); -test('the More menu fits a 390px viewport and works by touch (#512 D162)',async({page,request})=>{ +test('the More menu fits a 390px viewport and works by touch (#512 D163)',async({page,request})=>{ const dual=byText(await items(request),'Dual role portrait'); await page.setViewportSize({width:390,height:844}); await page.goto(`/prompt_manager/workspace#/library/${dual.id}`); diff --git a/tests/browser/workspace-library-editor.spec.mjs b/tests/browser/workspace-library-editor.spec.mjs index 22b12e7b..9cb16241 100644 --- a/tests/browser/workspace-library-editor.spec.mjs +++ b/tests/browser/workspace-library-editor.spec.mjs @@ -541,7 +541,7 @@ test('new from Images cancel preserves browse',async({page})=>{ test('history heading follows the concept and sends the selected saved pair',async({page})=>{ const f=page.fixture;await openHistory(page,f.positive_id); const actions=headingActions(page).locator('button:not([role="menuitem"])'); - // D162 (#512): the More menu button follows Send to ComfyUI. + // D163 (#512): the More menu button follows Send to ComfyUI. expect(await visibleNames(actions)).toEqual(['← Prompt library','Edit metadata','Send to ComfyUI','⋯']); await expect(page.getByRole('link',{name:'Back to library',exact:true})).toHaveCount(0); const send=actions.nth(2);await expect(send).toHaveClass(/\bsend\b/);await expect(send.locator('svg')).toHaveCount(1); diff --git a/web/js/workspace/library.mjs b/web/js/workspace/library.mjs index 00868e64..4b221ca1 100644 --- a/web/js/workspace/library.mjs +++ b/web/js/workspace/library.mjs @@ -492,7 +492,7 @@ export function mountLibrary(main,api,parentScope,{positiveId,savedState=null,on const actions=headingActions(main,history); const back=createButton('← Prompt library'),edit=createButton('Edit metadata'),send=createButton('','send'); send.append(createWorkspaceIcon('send'),el('span','Send to ComfyUI'));send.disabled=true; - // D162 (#512, maintainer 2026-10-29): a "⋯" More menu after Send to ComfyUI holds Delete prompt…, so delete is + // D163 (#512, maintainer 2026-10-29): a "⋯" More menu after Send to ComfyUI holds Delete prompt…, so delete is // findable on the page; Edit metadata keeps its own Delete prompt… (D161). const moreMenu=createMoreMenu({scope,label:'More actions for this prompt',items:[{label:'Delete prompt…',danger:true,onSelect:()=>deletePrompt(moreMenu.button)}]}); actions.append(back,edit,send,moreMenu.element); diff --git a/web/js/workspace/more-menu.mjs b/web/js/workspace/more-menu.mjs index 3d6fbd0c..da3fa31e 100644 --- a/web/js/workspace/more-menu.mjs +++ b/web/js/workspace/more-menu.mjs @@ -1,7 +1,7 @@ import { createButton } from '../shared/toolkit/core.js'; /** - * A "⋯" (More) menu button for a page heading (D162, #512; the concept has no menu, so it uses the concept's button + * A "⋯" (More) menu button for a page heading (D163, #512; the concept has no menu, so it uses the concept's button * and surface styles). The button carries `aria-haspopup="menu"` and `aria-expanded`; Enter, Space or ArrowDown opens * the menu on its first item, ArrowUp on its last; ArrowUp/ArrowDown/Home/End move between items; Escape closes it and * returns focus to the button; Tab, an outside pointer press or choosing an item closes it. A held button diff --git a/web/js/workspace/workspace.css b/web/js/workspace/workspace.css index dfc76582..c602f8b5 100644 --- a/web/js/workspace/workspace.css +++ b/web/js/workspace/workspace.css @@ -483,7 +483,7 @@ pre.prompt-text { font: inherit; font-size: 12px; line-height: 1.75; margin-bloc .tagging-modal .tag-action-notice > span { flex: 1 1 16em; } .tag-image-preview.tag-preview-empty { display: grid; place-items: center; padding: 8px; text-align: center; font-size: 12px; color: var(--ca-muted); background: var(--ca-field); box-sizing: border-box; /* D147 */ } -/* D162 (#512): the prompt page's "⋯" More menu. The concept has no menu; it uses the concept's button, surface, border +/* D163 (#512): the prompt page's "⋯" More menu. The concept has no menu; it uses the concept's button, surface, border and toast shadow, opens under its button, right-aligned so it stays inside a 390px viewport. */ .more-menu { position: relative; display: inline-flex; } .more-menu-list {