Files
goodbuddy/tests/workspace-files-layout.electron.test.ts
T
mesalogo ab85e72f01 fix: keep workspace file controls visible while scrolling
Scroll the file list independently so view selection, refresh, creation actions and directory navigation remain visible. Keep the selected Files entry available in projects without Git.

Add component coverage and 16 Electron layout scenarios for themes, window sizes and scroll retention. Focused tests, typecheck and lint passed; the full test run timed out after 200 seconds.

Release note: Workspace file controls remain visible while scrolling, and projects without Git retain the Files entry.
2026-09-30 17:33:16 +08:00

51 lines
2.6 KiB
TypeScript

// @vitest-environment node
import { spawn } from 'node:child_process'
import { createRequire } from 'node:module'
import { copyFile, mkdtemp, readFile, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { createServer } from 'vite'
import react from '@vitejs/plugin-react'
import { expect, it } from 'vitest'
it('docks workspace Files controls while long Git and non-Git directories scroll', async () => {
const directory = await mkdtemp(join(tmpdir(), 'goodbuddy-files-layout-'))
const server = await createServer({
configFile: false, root: resolve('.'), cacheDir: join(directory, 'vite'),
plugins: [react(), { name: 'workspace-files-layout', configureServer(server) {
server.middlewares.use('/files.html', async (_request, response) => {
response.setHeader('Content-Type', 'text/html')
response.end(await server.transformIndexHtml('/files.html',
'<html><body><div id="root"></div><script type="module" src="/tests/support/workspace-files-layout.tsx"></script></body></html>'))
})
} }],
optimizeDeps: { entries: ['tests/support/workspace-files-layout.tsx'] },
server: { host: '127.0.0.1', port: 0, watch: null }
})
try {
await server.listen()
const driver = join(directory, 'driver.mjs')
await copyFile(resolve('tests/support/workspace-files-layout-driver.mjs'), driver)
const env: NodeJS.ProcessEnv = { ...process.env, GB_LAYOUT_DIRECTORY: directory,
GB_LAYOUT_URL: server.resolvedUrls!.local[0] + 'files.html' }
delete env.ELECTRON_RUN_AS_NODE
const child = spawn(createRequire(import.meta.url)('electron'), [driver], { env, stdio: ['ignore', 'pipe', 'pipe'] })
let output = ''
child.stdout.on('data', data => { output += data })
child.stderr.on('data', data => { output += data })
const timeout = setTimeout(() => child.kill(), 90000)
try {
const code = await new Promise((resolve, reject) => { child.once('exit', resolve); child.once('error', reject) })
const result = await readFile(join(directory, 'result.json'), 'utf8').catch(() => output)
expect(code, result).toBe(0)
const parsed = JSON.parse(result)
expect(parsed.passed).toBe(true)
expect(parsed.observations).toHaveLength(16)
process.stdout.write('Workspace Files: 16 Electron geometry scenarios; Git/non-Git, light/dark, four sizes, native wheel/click, hide/show retention; model calls: 0\n')
} finally { clearTimeout(timeout) }
} finally {
await server.close()
await rm(directory, { recursive: true, force: true })
}
}, 120000)