Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3e4855abb | ||
|
|
63fd1fe243 |
@@ -57,6 +57,26 @@ test('library groups reusable negatives under one positive without exposing nega
|
||||
for(const item of rows.items) await expect(page.locator(`article[data-prompt-id="${item.id}"] .card-meta > span`).nth(1)).toHaveText(`${item.run_count} run${item.run_count===1?'':'s'}`);
|
||||
});
|
||||
|
||||
// #464: a starved renderer (headless WebKit under CPU load, a background tab) can hold animation frames for seconds;
|
||||
// a loaded page of prompts is shown without waiting for one.
|
||||
test('a held animation frame does not hide a loaded page of prompts, the first or a later one',async({page,request})=>{
|
||||
await expect(await request.post('/__test__/reset',{data:{native_library:true,extra_prompts:45}})).toBeOK();
|
||||
const {total}=await(await request.get('/prompt_manager/library?limit=100')).json();
|
||||
await page.addInitScript(()=>{
|
||||
const request=window.requestAnimationFrame.bind(window),cancel=window.cancelAnimationFrame.bind(window);
|
||||
const held=new Map(),real=new Map();let holding=true,next=0;
|
||||
window.requestAnimationFrame=callback=>{const id=--next;if(holding)held.set(id,callback);else real.set(id,request(callback));return id;};
|
||||
window.cancelAnimationFrame=id=>{held.delete(id);if(real.has(id))cancel(real.get(id));real.delete(id);};
|
||||
window.__releaseAnimationFrames=()=>{holding=false;for(const [id,callback] of held)real.set(id,request(callback));held.clear();};
|
||||
});
|
||||
await page.goto(route);
|
||||
const more=page.getByRole('button',{name:'Load more prompts',exact:true});
|
||||
await expect(more).toHaveAttribute('aria-disabled','false');await expect(cards(page)).toHaveCount(40);
|
||||
await more.evaluate(node=>node.click());await expect(page.locator('.library-status')).toHaveText('You’re all caught up.');
|
||||
await expect(cards(page)).toHaveCount(total);
|
||||
await page.evaluate(()=>window.__releaseAnimationFrames());await nextFrame(page);
|
||||
await expect(cards(page)).toHaveCount(total);await expect(page.locator('.library-row-spacer')).toHaveCount(0);
|
||||
});
|
||||
test('history displays the selected full negative beneath its positive and filters one shared physical gallery',async({page,request})=>{
|
||||
const rows=await(await request.get('/prompt_manager/library')).json();const cat=rows.items.find(item=>item.text==='Cat portrait');
|
||||
const data=await(await request.get(`/prompt_manager/library/${cat.id}`)).json();
|
||||
|
||||
@@ -394,7 +394,10 @@ export function mountLibrary(main,api,parentScope,{positiveId,savedState=null,on
|
||||
const hidden=hiddenSave!==null && !next.loading && !next.error && !next.hasMore && !next.items.some(item=>item.id===hiddenSave)?' The saved prompt is hidden by the current filters.':'';
|
||||
message.textContent=(next.error?'Prompt library could not be loaded. Retry.':next.loading?'Loading prompt library…':!next.items.length?'No matching prompts. Try changing the filters.':!next.hasMore?'You’re all caught up.':'')+hidden;
|
||||
message.setAttribute('role',next.error?'alert':'status');retry.hidden=!next.error;more.hidden=!next.hasMore || !!next.error;more.setAttribute('aria-disabled',String(next.loading));
|
||||
schedule();scheduleLoad();
|
||||
// #464: a loaded page is laid out now, not on the next frame: a starved renderer (a background tab, headless
|
||||
// WebKit under load) can hold frames for seconds, which left a loaded shelf empty. Measurements still flush per frame.
|
||||
if(batch && grid.isConnected) {cancelAnimationFrame(frame);flush();} else schedule();
|
||||
scheduleLoad();
|
||||
}
|
||||
const stream=createLibraryStream({api,onChange:render,restore:restorable?{filters,state:restorable.state}:undefined});
|
||||
function maybeLoad() {
|
||||
|
||||
Reference in New Issue
Block a user