feat: assign and delete inbox artifacts
This commit is contained in:
@@ -151,6 +151,18 @@ async function runReadyScenario(cdp, url) {
|
||||
await clickText(cdp, '.inbox-header .btn', 'Вставить из буфера')
|
||||
await assertText(cdp, 'pasted-smoke.png', 'inbox: clipboard image captured')
|
||||
await assertText(cdp, 'Изображение', 'inbox: clipboard image kind visible')
|
||||
await clickInboxItemButton(cdp, 'smoke-drop-folder', 'Разложить')
|
||||
await waitForSelector(cdp, '.modal input[type="text"]')
|
||||
await setInputValue(cdp, '.modal input[type="text"]', 'Smoke')
|
||||
await waitForSelector(cdp, '.assign-search-result')
|
||||
await assertEval(cdp, `document.querySelector('.assign-search-result')?.innerText.includes('Smoke Project')`, 'inbox: assign target search works')
|
||||
await clickText(cdp, '.assign-search-result', 'Smoke Project')
|
||||
await clickText(cdp, '.modal-actions .btn', 'Разложить')
|
||||
await waitForGone(cdp, '.modal-overlay')
|
||||
await assertEval(cdp, `!document.querySelector('.inbox-screen')?.innerText.includes('smoke-drop-folder')`, 'inbox: assigned item leaves inbox')
|
||||
await clickInboxItemButton(cdp, 'pasted-smoke.png', 'Удалить')
|
||||
await clickText(cdp, '.overlay .btn', 'Удалить')
|
||||
await assertEval(cdp, `!document.querySelector('.inbox-screen')?.innerText.includes('pasted-smoke.png')`, 'inbox: deleted item leaves inbox')
|
||||
await screenshot(cdp, 'inbox.png')
|
||||
await clickText(cdp, '.inbox-item', 'Inbox Smoke Item')
|
||||
await assertText(cdp, 'Inbox Smoke Item', 'inbox: item opens from list')
|
||||
@@ -392,6 +404,24 @@ async function clickFolderOpenButton(cdp, name) {
|
||||
await sleep(300)
|
||||
}
|
||||
|
||||
async function clickInboxItemButton(cdp, title, buttonText) {
|
||||
const ok = await evalValue(cdp, `
|
||||
(() => {
|
||||
const norm = (value) => (value || '').replace(/\\s+/g, ' ').trim();
|
||||
const row = [...document.querySelectorAll('.inbox-item')]
|
||||
.find((node) => norm(node.innerText || node.textContent).includes(${JSON.stringify(title)}));
|
||||
if (!row) return false;
|
||||
const btn = [...row.querySelectorAll('button')]
|
||||
.find((node) => norm(node.innerText || node.textContent).includes(${JSON.stringify(buttonText)}));
|
||||
if (!btn) return false;
|
||||
btn.click();
|
||||
return true;
|
||||
})()
|
||||
`)
|
||||
if (!ok) throw new Error(`Inbox item button not found: ${title} -> ${buttonText}`)
|
||||
await sleep(250)
|
||||
}
|
||||
|
||||
async function evalValue(cdp, expression) {
|
||||
const result = await cdp.send('Runtime.evaluate', {
|
||||
expression,
|
||||
@@ -688,6 +718,20 @@ function wailsMockSource() {
|
||||
return node?.children || [];
|
||||
}
|
||||
|
||||
function detachNode(id, items = state.nodes) {
|
||||
const idx = items.findIndex((node) => node.id === id);
|
||||
if (idx >= 0) {
|
||||
const [node] = items.splice(idx, 1);
|
||||
return node;
|
||||
}
|
||||
for (const item of items) {
|
||||
if (!item.children) continue;
|
||||
const found = detachNode(id, item.children);
|
||||
if (found) return found;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function readyStatus() {
|
||||
return {
|
||||
status: 'ready',
|
||||
@@ -762,6 +806,24 @@ function wailsMockSource() {
|
||||
state.nodes.push(node);
|
||||
return clone({ ...node, captureKind: node.captureKind, captureSource: node.captureSource });
|
||||
},
|
||||
AssignInboxNode: async (nodeId, targetParentId) => {
|
||||
const node = detachNode(nodeId);
|
||||
const parent = findNode(targetParentId);
|
||||
if (!node || !parent) throw new Error('assign target not found');
|
||||
node.captureInbox = false;
|
||||
node.captureKind = '';
|
||||
node.captureSource = '';
|
||||
node.parent_id = targetParentId;
|
||||
parent.children = parent.children || [];
|
||||
parent.children.push(node);
|
||||
parent.has_children = true;
|
||||
return clone(node);
|
||||
},
|
||||
DeleteInboxNode: async (nodeId) => {
|
||||
const node = detachNode(nodeId);
|
||||
if (!node) throw new Error('inbox node not found');
|
||||
return true;
|
||||
},
|
||||
ListTrash: async () => clone({
|
||||
trashPath: '/tmp/verstak-smoke-vault/.verstak/trash',
|
||||
nodes: [{ id: 'node-trash', title: 'Trash Smoke Folder', type: 'folder', fsPath: 'Trash Smoke Folder', deletedAt: now }],
|
||||
@@ -773,7 +835,7 @@ function wailsMockSource() {
|
||||
SetTemplateEnabled: async () => true,
|
||||
GetNodeDetail: async (id) => clone(findNode(id) || fileNodeDetails[id] || null),
|
||||
GetNodeTitle: async (id) => findNode(id)?.title || '',
|
||||
SearchNodes: async (query) => allNodes().filter((node) => node.title.toLowerCase().includes(String(query || '').toLowerCase())).map((node) => ({ id: node.id, title: node.title, path: '/Smoke/' + node.title })),
|
||||
SearchNodes: async (query) => allNodes().filter((node) => node.title.toLowerCase().includes(String(query || '').toLowerCase())).map((node) => ({ id: node.id, title: node.title, path: '/Smoke/' + node.title, type: node.type })),
|
||||
CreateNodeFromTemplate: async (parentId, title, templateId) => {
|
||||
const id = 'node-created-' + Date.now();
|
||||
const parent = parentId ? findNode(parentId) : null;
|
||||
|
||||
Reference in New Issue
Block a user