"use strict";(globalThis.webpackChunkproject_public_docs=globalThis.webpackChunkproject_public_docs||[]).push([[413],{6785(e,t,n){n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"overview","title":"GhostQA","description":"AI-powered visual GUI testing via natural language","source":"@site/docs/overview.md","sourceDirName":".","slug":"/","permalink":"/rob/ghostqa/","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"slug":"/","sidebar_position":1},"sidebar":"docs"}');var r=n(4848),i=n(8453);const a={slug:"/",sidebar_position:1},c="GhostQA",o={},l=[{value:"Overview",id:"overview",level:2},{value:"Features",id:"features",level:2},{value:"Quick Start",id:"quick-start",level:2},{value:"Installation",id:"installation",level:3},{value:"Example Test Spec",id:"example-test-spec",level:3},{value:"Architecture",id:"architecture",level:2},{value:"Core Components",id:"core-components",level:3},{value:"Related Projects",id:"related-projects",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.header,{children:(0,r.jsx)(t.h1,{id:"ghostqa",children:"GhostQA"})}),"\n",(0,r.jsx)(t.p,{children:"AI-powered visual GUI testing via natural language"}),"\n",(0,r.jsx)(t.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(t.p,{children:"GhostQA enables testing of desktop GUI applications (PyQt, GTK, etc.) using AI vision agents. Instead of writing brittle UI test scripts, describe expected behavior in natural language and let AI verify it visually."}),"\n",(0,r.jsx)(t.p,{children:"The system works by running target applications inside Docker containers with headless display (Xvfb) and noVNC for remote access. AI agents connect to the exposed URL and interact with the application based on natural language test specifications."}),"\n",(0,r.jsx)(t.h2,{id:"features",children:"Features"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"Natural Language Tests"})," - Write test specs in YAML/Markdown describing expected behavior"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"AI Vision Agents"})," - Support for ChatGPT Agent Mode, Claude Computer Use, and browser-use"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"Docker Isolation"})," - Apps run in containers with Xvfb + noVNC for headless GUI testing"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"Screenshot Capture"})," - Automatic screenshot collection during test execution"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"Multiple Agent Support"})," - Flexible architecture supporting various AI backends"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"CLI Interface"})," - Simple commands to run apps, execute tests, and build images"]}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"quick-start",children:"Quick Start"}),"\n",(0,r.jsx)(t.h3,{id:"installation",children:"Installation"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-bash",children:'# Clone and install\ngit clone https://gitea.brrd.tech/rob/ghostqa.git\ncd ghostqa\npip install -e ".[dev]"\n\n# Build the base Docker image\nghostqa build\n\n# Run an app in test mode\nghostqa run --app development-hub --port 6080\n\n# Execute tests\nghostqa test specs/dashboard.yaml --agent claude --url http://localhost:6080\n'})}),"\n",(0,r.jsx)(t.h3,{id:"example-test-spec",children:"Example Test Spec"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-yaml",children:'name: Dashboard displays project list\napp: development-hub\nsteps:\n - action: wait_for_window\n timeout: 10s\n - action: verify\n prompt: "Is there a list of projects visible on the left side?"\n expected: true\n - action: click\n prompt: "Click on the first project in the list"\n - action: verify\n prompt: "Does the right panel show a dashboard with todos and goals?"\n expected: true\n'})}),"\n",(0,r.jsx)(t.h2,{id:"architecture",children:"Architecture"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{children:'\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Docker Container \u2502\n\u2502 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\n\u2502 \u2502 Target App \u2502\u2500\u2500\u25b6\u2502 Xvfb + noVNC \u2502\u2500\u2500\u253c\u2500\u2500\u25b6 Public URL (Cloudflare)\n\u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n \u2502\n \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n \u2502 AI Agent \u2502\n \u2502 (ChatGPT, Claude, etc.) \u2502\n \u2502 \u2502\n \u2502 "Click Projects, \u2502\n \u2502 verify 5 items shown" \u2502\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n'})}),"\n",(0,r.jsx)(t.h3,{id:"core-components",children:"Core Components"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"Component"}),(0,r.jsx)(t.th,{children:"Purpose"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"docker.runner"})}),(0,r.jsx)(t.td,{children:"Build and manage Docker containers with noVNC"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"docker.base"})}),(0,r.jsx)(t.td,{children:"Base image builder with Xvfb, x11vnc, noVNC"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"agents.base"})}),(0,r.jsx)(t.td,{children:"Abstract interface for AI vision agents"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"specs.parser"})}),(0,r.jsx)(t.td,{children:"Parse natural language test specifications"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"specs.models"})}),(0,r.jsx)(t.td,{children:"Test spec and step data models"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:(0,r.jsx)(t.code,{children:"runner"})}),(0,r.jsx)(t.td,{children:"Execute tests, coordinate agents and containers"})]})]})]}),"\n",(0,r.jsx)(t.h2,{id:"related-projects",children:"Related Projects"}),"\n",(0,r.jsx)(t.p,{children:"This project is part of the development ecosystem:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://pages.brrd.tech/rob/CmdForge/",children:"CmdForge"})," - AI-powered CLI tool builder"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://pages.brrd.tech/rob/CascadingDev/",children:"CascadingDev"})," - Cascading Development Framework"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://pages.brrd.tech/rob/orchestrated-discussions/",children:"Orchestrated Discussions"})," - AI Discussion Framework"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://pages.brrd.tech/rob/artifact-editor/",children:"Artifact Editor"})," - Code Artifact Editor"]}),"\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.a,{href:"https://pages.brrd.tech/rob/ramble/",children:"Ramble"})," - Voice Note Transcription"]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453(e,t,n){n.d(t,{R:()=>a,x:()=>c});var s=n(6540);const r={},i=s.createContext(r);function a(e){const t=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]);