-
Notifications
You must be signed in to change notification settings - Fork 1
docs: refresh app view screenshots and add manual capture workflow #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # App Views | ||
|
|
||
| This page shows up-to-date screenshots for the main app panels. | ||
|
|
||
| ## Start Panel (Config) | ||
|
|
||
|  | ||
|
|
||
| ## Select Files Panel | ||
|
|
||
|  | ||
|
|
||
| ## Select Files Panel (With Selection) | ||
|
|
||
|  | ||
|
|
||
| ## Select Files Panel (Resized) | ||
|
|
||
|  | ||
|
|
||
| ## Processed Output Panel | ||
|
|
||
|  | ||
|
|
||
| ## Refresh Screenshots | ||
|
|
||
| ```bash | ||
| npm run docs:screenshots | ||
| ``` | ||
|
|
||
| This command runs the Playwright capture flow and updates screenshots in `docs/images/`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Repository Analysis | ||
|
|
||
| ## src/App.tsx | ||
|
|
||
| ```ts | ||
| export function App() { | ||
| return <main>Hello AI Code Fusion</main>; | ||
| } | ||
| ``` | ||
|
|
||
| Tokens: 120 | ||
|
|
||
| ## src/features/feature-24/ui/Feature24Panel.tsx | ||
|
|
||
| ```ts | ||
| export function Feature24Panel() { | ||
| return <section>Panel content</section>; | ||
| } | ||
| ``` | ||
|
|
||
| Tokens: 240 | ||
|
|
||
| --END-- |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <repository totalFiles="2" totalTokens="360"> | ||
| <file path="src/App.tsx" tokens="120"><![CDATA[ | ||
| export function App() { | ||
| return <main>Hello AI Code Fusion</main>; | ||
| } | ||
| ]]></file> | ||
| <file path="src/features/feature-24/ui/Feature24Panel.tsx" tokens="240"><![CDATA[ | ||
| export function Feature24Panel() { | ||
| return <section>Panel content</section>; | ||
| } | ||
| ]]></file> | ||
| </repository> |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,8 @@ const { chromium } = require('playwright'); | |||||
|
|
||||||
| const ROOT_DIR = path.join(__dirname, '..'); | ||||||
| const RENDERER_DIR = path.join(ROOT_DIR, 'src', 'renderer'); | ||||||
| const SCREENSHOT_DIR = path.join(ROOT_DIR, 'dist', 'qa', 'screenshots'); | ||||||
| const DEFAULT_SCREENSHOT_DIR = path.join('dist', 'qa', 'screenshots'); | ||||||
| const SCREENSHOT_DIR = resolveOutputDirectory(process.env.UI_SCREENSHOT_DIR); | ||||||
| const PORT = Number(process.env.UI_SCREENSHOT_PORT || 4173); | ||||||
| const DEFAULT_SCREENSHOT_NAME = `ui-${process.platform}-${process.arch}.png`; | ||||||
| const FIXED_MTIME = 1700000000000; | ||||||
|
|
@@ -58,6 +59,21 @@ function sanitizeScreenshotName(nameCandidate) { | |||||
| return withExtension; | ||||||
| } | ||||||
|
|
||||||
| function resolveOutputDirectory(dirCandidate) { | ||||||
| const rawDir = | ||||||
| typeof dirCandidate === 'string' && dirCandidate.trim() | ||||||
| ? dirCandidate.trim() | ||||||
| : DEFAULT_SCREENSHOT_DIR; | ||||||
| const absoluteDir = path.resolve(ROOT_DIR, rawDir); | ||||||
| const relativeToRoot = path.relative(ROOT_DIR, absoluteDir); | ||||||
|
|
||||||
| if (relativeToRoot.startsWith('..') || path.isAbsolute(relativeToRoot)) { | ||||||
| throw new Error(`Invalid screenshot directory: ${rawDir}`); | ||||||
| } | ||||||
|
|
||||||
| return absoluteDir; | ||||||
| } | ||||||
|
|
||||||
| function resolveOutputPath(fileName) { | ||||||
| const targetPath = path.resolve(SCREENSHOT_DIR, fileName); | ||||||
| const relativeToRoot = path.relative(SCREENSHOT_DIR, targetPath); | ||||||
|
|
@@ -313,12 +329,14 @@ const SCREENSHOTS = { | |||||
| sourceTab: resolveOutputPath(`${SCREENSHOT_BASE_NAME}-source.png`), | ||||||
| sourceSelected: resolveOutputPath(`${SCREENSHOT_BASE_NAME}-source-selected.png`), | ||||||
| sourceSelectedResized: resolveOutputPath(`${SCREENSHOT_BASE_NAME}-source-selected-resized.png`), | ||||||
| processedTab: resolveOutputPath(`${SCREENSHOT_BASE_NAME}-processed.png`), | ||||||
| }; | ||||||
|
|
||||||
| const UI_SELECTORS = { | ||||||
| appRoot: '#app', | ||||||
| configTab: '[data-tab="config"]', | ||||||
| sourceTab: '[data-tab="source"]', | ||||||
| processedTabActive: '[data-tab="processed"][aria-selected="true"]', | ||||||
| secretScanningToggle: '#enable-secret-scanning', | ||||||
| suspiciousFilesToggle: '#exclude-suspicious-files', | ||||||
| sourceFolderExpandButton: 'button[aria-label="Expand folder src"]', | ||||||
|
|
@@ -331,6 +349,7 @@ const UI_SELECTORS = { | |||||
| refreshFileListButton: 'button[title="Refresh the file list"]', | ||||||
| fileTreeScrollContainer: '.file-tree .overflow-auto', | ||||||
| processSelectedFilesButton: '[data-testid="process-selected-files-button"]', | ||||||
| processedContent: '#processed-content', | ||||||
| }; | ||||||
|
|
||||||
| async function setupMockElectronApi(page) { | ||||||
|
|
@@ -358,20 +377,65 @@ async function setupMockElectronApi(page) { | |||||
| const tree = excludeSensitiveFiles ? mockFilteredDirectoryTree : mockDirectoryTree; | ||||||
| return cloneTree(tree); | ||||||
| }, | ||||||
| analyzeRepository: async () => ({ | ||||||
| totalFiles: 0, | ||||||
| totalTokens: 0, | ||||||
| files: [], | ||||||
| }), | ||||||
| processRepository: async () => ({ | ||||||
| content: '', | ||||||
| stats: { | ||||||
| totalFiles: 0, | ||||||
| totalTokens: 0, | ||||||
| analyzeRepository: async (options = {}) => { | ||||||
| const selectedFilePaths = Array.isArray(options?.selectedFiles) ? options.selectedFiles : []; | ||||||
| const filesInfo = selectedFilePaths.map((filePath, index) => { | ||||||
| const normalizedPath = String(filePath); | ||||||
| const relativePath = normalizedPath.startsWith(`${mockRootPath}/`) | ||||||
| ? normalizedPath.slice(mockRootPath.length + 1) | ||||||
| : normalizedPath; | ||||||
| return { | ||||||
|
Comment on lines
+380
to
+387
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Path prefix stripping in Using |
||||||
| path: relativePath, | ||||||
| tokens: 120 * (index + 1), | ||||||
| isBinary: false, | ||||||
| }; | ||||||
| }); | ||||||
|
|
||||||
| return { | ||||||
| totalFiles: filesInfo.length, | ||||||
| totalTokens: filesInfo.reduce((sum, file) => sum + file.tokens, 0), | ||||||
| filesInfo, | ||||||
| }; | ||||||
| }, | ||||||
| processRepository: async (options = {}) => { | ||||||
| const inputFilesInfo = Array.isArray(options?.filesInfo) ? options.filesInfo : []; | ||||||
| const filesInfo = inputFilesInfo.map((file, index) => ({ | ||||||
| path: String(file?.path || `src/file-${index + 1}.ts`), | ||||||
| tokens: | ||||||
| Number.isFinite(file?.tokens) && Number(file.tokens) > 0 ? Number(file.tokens) : 120 * (index + 1), | ||||||
| isBinary: false, | ||||||
| })); | ||||||
| const totalTokens = filesInfo.reduce((sum, file) => sum + file.tokens, 0); | ||||||
| const exportFormat = options?.options?.exportFormat === 'xml' ? 'xml' : 'markdown'; | ||||||
| const content = | ||||||
| exportFormat === 'xml' | ||||||
| ? [ | ||||||
| '<?xml version="1.0" encoding="UTF-8"?>', | ||||||
| `<repository totalFiles="${filesInfo.length}" totalTokens="${totalTokens}">`, | ||||||
| ...filesInfo.map( | ||||||
| (file) => | ||||||
| ` <file path="${file.path}" tokens="${file.tokens}"><![CDATA[// Preview for ${file.path}]]></file>` | ||||||
| ), | ||||||
| '</repository>', | ||||||
| ].join('\n') | ||||||
| : [ | ||||||
| '# Repository Analysis', | ||||||
| '', | ||||||
| ...filesInfo.map( | ||||||
| (file) => `## ${file.path}\n\n\`\`\`ts\n// Preview for ${file.path}\n\`\`\`\nTokens: ${file.tokens}\n` | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The mock data generation for the markdown format includes a trailing newline (
Suggested change
|
||||||
| ), | ||||||
| '--END--', | ||||||
| ].join('\n'); | ||||||
|
|
||||||
| return { | ||||||
| content, | ||||||
| exportFormat, | ||||||
| totalTokens, | ||||||
| processedFiles: filesInfo.length, | ||||||
| skippedFiles: 0, | ||||||
| processedFiles: 0, | ||||||
| }, | ||||||
| }), | ||||||
| filesInfo, | ||||||
| }; | ||||||
| }, | ||||||
| countFilesTokens: async (options) => { | ||||||
| const filePaths = Array.isArray(options?.filePaths) ? options.filePaths : []; | ||||||
| const results = {}; | ||||||
|
|
@@ -569,6 +633,33 @@ async function captureAppStateScreenshots(page) { | |||||
| await runStep('Capture resized screenshot with deep tree expanded', async () => { | ||||||
| await page.screenshot({ path: SCREENSHOTS.sourceSelectedResized, fullPage: true }); | ||||||
| }); | ||||||
|
|
||||||
| await runStep('Return to desktop viewport before processing', async () => { | ||||||
| await page.setViewportSize({ width: 1440, height: 900 }); | ||||||
| }); | ||||||
|
|
||||||
| await runStep('Wait for process button to be enabled', async () => { | ||||||
| await page.waitForFunction((selector) => { | ||||||
| const button = document.querySelector(selector); | ||||||
| if (!(button instanceof HTMLButtonElement)) { | ||||||
| return false; | ||||||
| } | ||||||
| return !button.disabled && /process selected files/i.test(button.textContent || ''); | ||||||
| }, UI_SELECTORS.processSelectedFilesButton); | ||||||
| }); | ||||||
|
|
||||||
| await runStep('Process selected files', async () => { | ||||||
| await page.locator(UI_SELECTORS.processSelectedFilesButton).first().click(); | ||||||
| }); | ||||||
|
|
||||||
| await runStep('Wait for processed panel to render', async () => { | ||||||
| await page.waitForSelector(UI_SELECTORS.processedTabActive, { timeout: 10000 }); | ||||||
| await page.waitForSelector(UI_SELECTORS.processedContent, { timeout: 10000 }); | ||||||
| }); | ||||||
|
|
||||||
| await runStep('Capture processed tab screenshot', async () => { | ||||||
| await page.screenshot({ path: SCREENSHOTS.processedTab, fullPage: true }); | ||||||
| }); | ||||||
| } | ||||||
|
|
||||||
| async function captureScreenshot() { | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. Docs screenshots miss css build
🐞 Bug⛯ ReliabilityAgent Prompt
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools