Promote React Arco client into apps
This commit is contained in:
143
apps/senlinai-acro-react/scripts/visual-check.mjs
Normal file
143
apps/senlinai-acro-react/scripts/visual-check.mjs
Normal file
@@ -0,0 +1,143 @@
|
||||
import { createServer } from 'vite'
|
||||
import { chromium } from 'playwright'
|
||||
|
||||
const port = Number(process.env.VISUAL_CHECK_PORT ?? 4175)
|
||||
|
||||
const server = await createServer({
|
||||
root: process.cwd(),
|
||||
server: {
|
||||
host: '127.0.0.1',
|
||||
port,
|
||||
strictPort: true,
|
||||
},
|
||||
})
|
||||
|
||||
await server.listen()
|
||||
|
||||
const browser = await chromium.launch({ headless: true })
|
||||
const page = await browser.newPage({ viewport: { width: 1440, height: 1024 }, deviceScaleFactor: 1 })
|
||||
const errors = []
|
||||
page.on('console', (message) => {
|
||||
if (message.type() === 'error') errors.push(message.text())
|
||||
})
|
||||
|
||||
await page.goto(`http://127.0.0.1:${port}/`, { waitUntil: 'networkidle' })
|
||||
await page.screenshot({ path: 'test-results/login-react-acro.png', fullPage: true })
|
||||
await page.locator('.login-form-panel .arco-btn-primary').click()
|
||||
await page.waitForSelector('.workbench-shell')
|
||||
await page.waitForTimeout(700)
|
||||
await page.screenshot({ path: 'test-results/workbench-react-acro-light.png', fullPage: true })
|
||||
await page.locator('.topbar-actions .arco-btn').first().click()
|
||||
await page.screenshot({ path: 'test-results/workbench-react-acro-dark.png', fullPage: true })
|
||||
|
||||
const metrics = await page.evaluate(() => {
|
||||
const statusbar = document.querySelector('.statusbar')
|
||||
const search = document.querySelector('.global-search')
|
||||
const rail = document.querySelector('.project-rail')
|
||||
const railChildren = rail?.querySelector('.arco-layout-sider-children')
|
||||
const dashboard = document.querySelector('.dashboard-button')
|
||||
const project = document.querySelector('.project-button')
|
||||
const create = document.querySelector('.create-project')
|
||||
const firstBadge = document.querySelector('.project-badge .arco-badge-number')
|
||||
const railItems = [...document.querySelectorAll('.dashboard-button, .project-button, .create-project')]
|
||||
const rect = (node) => {
|
||||
const box = node?.getBoundingClientRect()
|
||||
return box ? { left: box.left, right: box.right, top: box.top, width: box.width, height: box.height } : null
|
||||
}
|
||||
const railBox = rail?.getBoundingClientRect()
|
||||
const itemRects = railItems.map(rect).filter(Boolean)
|
||||
const horizontalInsets = railBox && project
|
||||
? {
|
||||
left: project.getBoundingClientRect().left - railBox.left,
|
||||
right: railBox.right - project.getBoundingClientRect().right,
|
||||
}
|
||||
: null
|
||||
const verticalGaps = itemRects.slice(1).map((item, index) => item.top - (itemRects[index].top + itemRects[index].height))
|
||||
const overflowState = (node) => node
|
||||
? {
|
||||
clientWidth: node.clientWidth,
|
||||
scrollWidth: node.scrollWidth,
|
||||
clientHeight: node.clientHeight,
|
||||
scrollHeight: node.scrollHeight,
|
||||
overflowX: getComputedStyle(node).overflowX,
|
||||
overflowY: getComputedStyle(node).overflowY,
|
||||
}
|
||||
: null
|
||||
|
||||
return {
|
||||
statusbarHeight: statusbar?.getBoundingClientRect().height,
|
||||
searchHeight: search?.getBoundingClientRect().height,
|
||||
projectRailWidth: rail?.getBoundingClientRect().width,
|
||||
dashboardButton: rect(dashboard),
|
||||
projectButton: rect(project),
|
||||
createProjectButton: rect(create),
|
||||
firstProjectBadge: rect(firstBadge),
|
||||
horizontalInsets,
|
||||
verticalGaps,
|
||||
projectRailOverflow: overflowState(rail),
|
||||
projectRailChildrenOverflow: overflowState(railChildren),
|
||||
overflowX: document.documentElement.scrollWidth > document.documentElement.clientWidth,
|
||||
}
|
||||
})
|
||||
|
||||
await browser.close()
|
||||
await server.close()
|
||||
|
||||
console.log(JSON.stringify({ metrics, errors }, null, 2))
|
||||
|
||||
const failures = []
|
||||
if (errors.length) failures.push(`console errors: ${errors.join('; ')}`)
|
||||
if (metrics.statusbarHeight !== 32) failures.push(`expected statusbar height 32, got ${metrics.statusbarHeight}`)
|
||||
if (metrics.searchHeight !== 42) failures.push(`expected search height 42, got ${metrics.searchHeight}`)
|
||||
if (metrics.overflowX) failures.push('expected no horizontal overflow')
|
||||
if (!metrics.projectRailWidth || metrics.projectRailWidth < 88) {
|
||||
failures.push(`expected project rail at least 88px wide, got ${metrics.projectRailWidth}`)
|
||||
}
|
||||
if (!metrics.projectButton) failures.push('missing project button')
|
||||
if (!metrics.horizontalInsets || Math.abs(metrics.horizontalInsets.left - metrics.horizontalInsets.right) > 1) {
|
||||
failures.push(`expected equal rail horizontal insets, got ${JSON.stringify(metrics.horizontalInsets)}`)
|
||||
}
|
||||
if (metrics.verticalGaps.some((gap) => gap !== 12)) {
|
||||
failures.push(`expected all project rail vertical gaps to be 12px, got ${JSON.stringify(metrics.verticalGaps)}`)
|
||||
}
|
||||
for (const [name, overflow] of [
|
||||
['project rail', metrics.projectRailOverflow],
|
||||
['project rail children', metrics.projectRailChildrenOverflow],
|
||||
]) {
|
||||
if (
|
||||
!overflow ||
|
||||
overflow.overflowX !== 'hidden' ||
|
||||
overflow.overflowY !== 'hidden'
|
||||
) {
|
||||
failures.push(`expected ${name} scrollbars to be hidden with no overflow, got ${JSON.stringify(overflow)}`)
|
||||
}
|
||||
}
|
||||
if (
|
||||
!metrics.firstProjectBadge ||
|
||||
metrics.firstProjectBadge.right > metrics.projectRailWidth ||
|
||||
metrics.firstProjectBadge.left < 0
|
||||
) {
|
||||
failures.push(`expected first project badge to stay inside the project rail, got ${JSON.stringify(metrics.firstProjectBadge)}`)
|
||||
}
|
||||
if (
|
||||
!metrics.dashboardButton ||
|
||||
metrics.dashboardButton.width !== metrics.projectButton?.width ||
|
||||
metrics.dashboardButton.height !== metrics.projectButton?.height
|
||||
) {
|
||||
failures.push(
|
||||
`dashboard button size ${JSON.stringify(metrics.dashboardButton)} does not match project button ${JSON.stringify(metrics.projectButton)}`,
|
||||
)
|
||||
}
|
||||
if (
|
||||
!metrics.createProjectButton ||
|
||||
metrics.createProjectButton.width !== metrics.projectButton?.width ||
|
||||
metrics.createProjectButton.height !== metrics.projectButton?.height
|
||||
) {
|
||||
failures.push(
|
||||
`create project button size ${JSON.stringify(metrics.createProjectButton)} does not match project button ${JSON.stringify(metrics.projectButton)}`,
|
||||
)
|
||||
}
|
||||
|
||||
if (failures.length) {
|
||||
throw new Error(failures.join('\n'))
|
||||
}
|
||||
Reference in New Issue
Block a user