import { describe, it, afterEach, expect, $, $$, click, sleep, closeAll, csrf } from './runner.js?v=3'; describe('Bucket Context Menu', () => { afterEach(async () => { document.getElementById('bucket-ctx')?.classList.add('hidden'); await closeAll(); }); it('right-click bucket opens context menu', async () => { // Create a test bucket const b = await fetch('api/buckets', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf() }, body: JSON.stringify({ name: '__test_bctx__' }), }).then(r => r.json()); await window._reloadAll?.(); await sleep(200); const tab = document.querySelector(`#bucket-bar [data-bucket="${b.id}"]`); if (!tab) return; tab.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, clientX: 100, clientY: 50 })); await sleep(150); const ctx = document.getElementById('bucket-ctx'); expect(ctx).toExist(); expect(ctx.classList.contains('hidden')).toBe(false); }); it('bucket context menu has rename action', async () => { const b = await fetch('api/buckets', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf() }, body: JSON.stringify({ name: '__test_bctx_rename__' }), }).then(r => r.json()); await window._reloadAll?.(); await sleep(200); const tab = document.querySelector(`#bucket-bar [data-bucket="${b.id}"]`); if (!tab) return; tab.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, clientX: 100, clientY: 50 })); await sleep(150); const renameBtn = document.querySelector('[data-baction="rename"]'); expect(renameBtn).toExist(); }); it('bucket context menu has color action', async () => { const b = await fetch('api/buckets', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf() }, body: JSON.stringify({ name: '__test_bctx_color__' }), }).then(r => r.json()); await window._reloadAll?.(); await sleep(200); const tab = document.querySelector(`#bucket-bar [data-bucket="${b.id}"]`); if (!tab) return; tab.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, clientX: 100, clientY: 50 })); await sleep(150); expect(document.querySelector('[data-baction="color"]')).toExist(); }); it('empty bucket shows single delete option', async () => { const b = await fetch('api/buckets', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf() }, body: JSON.stringify({ name: '__test_bctx_empty__' }), }).then(r => r.json()); await window._reloadAll?.(); await sleep(200); const tab = document.querySelector(`#bucket-bar [data-bucket="${b.id}"]`); if (!tab) return; tab.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, clientX: 100, clientY: 50 })); await sleep(150); // Empty bucket: only delete-keep, no delete-all expect(document.querySelector('[data-baction="delete-keep"]')).toExist(); expect(document.querySelector('[data-baction="delete-all"]')).toBe(null); }); it('bucket with cards shows both delete options', async () => { const b = await fetch('api/buckets', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf() }, body: JSON.stringify({ name: '__test_bctx_full__' }), }).then(r => r.json()); await fetch('api/cards', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrf() }, body: JSON.stringify({ title: '__test_bctx_card__', body: '', color: '#38bdf8', bucket_id: b.id }), }); await window._reloadAll?.(); await sleep(200); const tab = document.querySelector(`#bucket-bar [data-bucket="${b.id}"]`); if (!tab) return; tab.dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, clientX: 100, clientY: 50 })); await sleep(150); expect(document.querySelector('[data-baction="delete-keep"]')).toExist(); expect(document.querySelector('[data-baction="delete-all"]')).toExist(); }); it('move-left disabled on first bucket', async () => { await window._reloadAll?.(); await sleep(200); // data-bucket-drag is present on BOTH regular and super-bucket // tiles but not on the fixed filters (all/current/favorites/…). // Using it instead of [data-bucket] avoids missing super-bucket // tiles which carry data-bucket-super instead. const tabs = $$('#bucket-bar [data-bucket-drag]'); if (!tabs.length) return; tabs[0].dispatchEvent(new MouseEvent('contextmenu', { bubbles: true, clientX: 100, clientY: 50 })); await sleep(150); const moveLeft = document.querySelector('[data-baction="move-left"]'); if (moveLeft) { expect(moveLeft.classList.contains('opacity-30') || moveLeft.classList.contains('pointer-events-none')).toBe(true); } }); });