repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
The Living OS cockpit
stars
latest
clone command
git clone gitlawb://did:key:z6Mku78K...XywC/living-os-cockp...git clone gitlawb://did:key:z6Mku78K.../living-os-cockp...59751530feat: surface worker supervisor health in live work4h ago| #1 | import { expect, test } from '@playwright/test'; |
| #2 | |
| #3 | type CameraSnapshot = { |
| #4 | position: { x: number; y: number; z: number }; |
| #5 | target: { x: number; y: number; z: number }; |
| #6 | }; |
| #7 | |
| #8 | declare global { |
| #9 | interface Window { |
| #10 | __vaultGraph3DDebug?: { |
| #11 | ready: boolean; |
| #12 | nodeCount: number; |
| #13 | snapshotCamera: () => CameraSnapshot | null; |
| #14 | setCamera: (position: CameraSnapshot['position'], target: CameraSnapshot['target']) => void; |
| #15 | firstNodeScreenPoint: () => { x: number; y: number; id: string } | null; |
| #16 | nodeScreenPoints: () => Array<{ x: number; y: number; id: string }>; |
| #17 | }; |
| #18 | } |
| #19 | } |
| #20 | |
| #21 | function distance(a: CameraSnapshot['position'], b: CameraSnapshot['position']) { |
| #22 | return Math.hypot(a.x - b.x, a.y - b.y, a.z - b.z); |
| #23 | } |
| #24 | |
| #25 | async function waitForGraph(page: any) { |
| #26 | await page.goto('/'); |
| #27 | const graphFrame = page.getByTestId('vault-graph-3d'); |
| #28 | await expect(graphFrame).toBeVisible(); |
| #29 | await graphFrame.scrollIntoViewIfNeeded(); |
| #30 | |
| #31 | await page.waitForFunction(() => Boolean(window.__vaultGraph3DDebug?.ready && window.__vaultGraph3DDebug.nodeCount > 0)); |
| #32 | await page.waitForFunction(() => Boolean(window.__vaultGraph3DDebug?.firstNodeScreenPoint?.())); |
| #33 | return graphFrame; |
| #34 | } |
| #35 | |
| #36 | async function wheelGraph(page: any, graphFrame: any, deltaY = -620) { |
| #37 | const graphBox = await graphFrame.boundingBox(); |
| #38 | expect(graphBox).not.toBeNull(); |
| #39 | await page.mouse.move(graphBox!.x + graphBox!.width / 2, graphBox!.y + graphBox!.height / 2); |
| #40 | await page.mouse.wheel(0, deltaY); |
| #41 | await page.waitForTimeout(1000); |
| #42 | } |
| #43 | |
| #44 | async function clickVisibleNode(page: any) { |
| #45 | const points = await page.evaluate(() => window.__vaultGraph3DDebug?.nodeScreenPoints() ?? []); |
| #46 | expect(points.length).toBeGreaterThan(0); |
| #47 | for (const point of points.slice(0, 20)) { |
| #48 | await page.mouse.click(point.x, point.y); |
| #49 | if (await page.getByTestId('vault-note-view').count()) break; |
| #50 | } |
| #51 | await expect(page.getByTestId('vault-note-view')).toBeVisible(); |
| #52 | } |
| #53 | |
| #54 | test('wheel zoom on the vault graph does not reset back to the base camera', async ({ page }) => { |
| #55 | const graphFrame = await waitForGraph(page); |
| #56 | |
| #57 | const initial = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #58 | expect(initial).not.toBeNull(); |
| #59 | |
| #60 | await wheelGraph(page, graphFrame, -720); |
| #61 | |
| #62 | const before = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #63 | expect(before).not.toBeNull(); |
| #64 | expect(distance(before!.position, initial!.position)).toBeGreaterThan(8); |
| #65 | |
| #66 | await page.waitForTimeout(900); |
| #67 | |
| #68 | const after = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #69 | expect(after).not.toBeNull(); |
| #70 | expect(distance(after!.position, before!.position)).toBeLessThan(2); |
| #71 | expect(distance(after!.target, before!.target)).toBeLessThan(2); |
| #72 | }); |
| #73 | |
| #74 | test('scroll click and scroll again preserve the vault graph camera', async ({ page }) => { |
| #75 | const graphFrame = await waitForGraph(page); |
| #76 | |
| #77 | await wheelGraph(page, graphFrame, -680); |
| #78 | const afterFirstScroll = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #79 | expect(afterFirstScroll).not.toBeNull(); |
| #80 | |
| #81 | await clickVisibleNode(page); |
| #82 | await page.waitForTimeout(250); |
| #83 | |
| #84 | const afterClick = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #85 | expect(afterClick).not.toBeNull(); |
| #86 | expect(distance(afterClick!.position, afterFirstScroll!.position)).toBeLessThan(2); |
| #87 | expect(distance(afterClick!.target, afterFirstScroll!.target)).toBeLessThan(2); |
| #88 | |
| #89 | await wheelGraph(page, graphFrame, -420); |
| #90 | const afterSecondScroll = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #91 | expect(afterSecondScroll).not.toBeNull(); |
| #92 | expect(distance(afterSecondScroll!.position, afterClick!.position)).toBeGreaterThan(4); |
| #93 | |
| #94 | await page.waitForTimeout(900); |
| #95 | |
| #96 | const settled = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #97 | expect(settled).not.toBeNull(); |
| #98 | expect(distance(settled!.position, afterSecondScroll!.position)).toBeLessThan(2); |
| #99 | expect(distance(settled!.target, afterSecondScroll!.target)).toBeLessThan(2); |
| #100 | }); |
| #101 | |
| #102 | test('clicking a vault graph node opens the note without resetting the camera', async ({ page }) => { |
| #103 | const graphFrame = await waitForGraph(page); |
| #104 | |
| #105 | await wheelGraph(page, graphFrame, -620); |
| #106 | |
| #107 | const before = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #108 | expect(before).not.toBeNull(); |
| #109 | |
| #110 | await clickVisibleNode(page); |
| #111 | await page.waitForTimeout(250); |
| #112 | |
| #113 | const after = await page.evaluate(() => window.__vaultGraph3DDebug?.snapshotCamera()); |
| #114 | expect(after).not.toBeNull(); |
| #115 | expect(distance(after!.position, before!.position)).toBeLessThan(2); |
| #116 | expect(distance(after!.target, before!.target)).toBeLessThan(2); |
| #117 | }); |
| #118 |