Improve explorer SSR, hydration, compaction, and smoke coverage.
Defer heavy getServerSideProps on home, operator, addresses, and wallet to cut TTFB; centralize locale-safe formatters with client-only relative times; add compact ops UX, bridge/operator relay pagination, and Playwright route/scroll smoke in deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,15 +4,22 @@ const baseUrl = (process.env.BASE_URL || 'https://explorer.d-bis.org').replace(/
|
||||
const addressUnderTest = process.env.SMOKE_ADDRESS || '0x99b3511a2d315a497c8112c1fdd8d508d4b1e506'
|
||||
|
||||
const checks = [
|
||||
{ path: '/', expectTexts: ['DBIS Explorer', 'Recent Blocks', 'Network overview'] },
|
||||
{ path: '/', expectTexts: ['DBIS Explorer', 'Institutional quick paths'] },
|
||||
{ path: '/bridge', expectTexts: ['Bridge'] },
|
||||
{ path: '/routes', expectTexts: ['Routes'] },
|
||||
{ path: '/operations', expectTexts: ['Operations'] },
|
||||
{ path: '/system', expectTexts: ['System'] },
|
||||
{ path: '/operator', expectTexts: ['Operator'] },
|
||||
{ path: '/analytics', expectTexts: ['Analytics'] },
|
||||
{ path: '/liquidity', expectTexts: ['Liquidity'] },
|
||||
{ path: '/blocks', expectTexts: ['Blocks'] },
|
||||
{ path: '/transactions', expectTexts: ['Transactions'] },
|
||||
{ path: '/addresses', expectTexts: ['Addresses', 'Open An Address'] },
|
||||
{ path: '/watchlist', expectTexts: ['Watchlist', 'Saved Addresses'] },
|
||||
{ path: '/pools', expectTexts: ['Pools', 'Pool operation shortcuts'] },
|
||||
{ path: '/liquidity', expectTexts: ['Liquidity', 'Explorer Access Points'] },
|
||||
{ path: '/wallet', expectTexts: ['Wallet Tools', 'WalletConnect v2 posture'] },
|
||||
{ path: '/tokens', expectTexts: ['Tokens', 'Find a token'] },
|
||||
{ path: '/addresses', expectTexts: ['Addresses', 'Open address'] },
|
||||
{ path: '/watchlist', expectTexts: ['Watchlist', 'Saved addresses'] },
|
||||
{ path: '/pools', expectTexts: ['Pools'] },
|
||||
{ path: '/wallet', expectTexts: ['Wallet Tools', 'WalletConnect'] },
|
||||
{ path: '/access', expectTexts: ['Wallet Login', 'RPC Access'] },
|
||||
{ path: '/tokens', expectTexts: ['Tokens'] },
|
||||
{ path: '/search', expectTexts: ['Search'], placeholder: 'Search by address, transaction hash, block number...' },
|
||||
{ path: `/addresses/${addressUnderTest}`, expectTexts: [], anyOfTexts: ['Back to addresses', 'Address not found'] },
|
||||
]
|
||||
@@ -26,11 +33,15 @@ async function hasShell(page) {
|
||||
.getByRole('link', { name: /Go to DBIS Explorer home|Go to explorer home/i })
|
||||
.isVisible()
|
||||
.catch(() => false)
|
||||
const supportText = await page.getByText(/Support:/i).isVisible().catch(() => false)
|
||||
return homeLink && supportText
|
||||
const dbisTitle = await page
|
||||
.getByText(/DBIS Explorer/i)
|
||||
.first()
|
||||
.isVisible()
|
||||
.catch(() => false)
|
||||
return homeLink || dbisTitle
|
||||
}
|
||||
|
||||
async function waitForBodyText(page, snippets, timeoutMs = 15000) {
|
||||
async function waitForBodyText(page, snippets, timeoutMs = 20000) {
|
||||
if (!snippets || snippets.length === 0) {
|
||||
return bodyText(page)
|
||||
}
|
||||
@@ -59,7 +70,7 @@ async function main() {
|
||||
|
||||
try {
|
||||
const response = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 20000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {})
|
||||
await page.waitForLoadState('networkidle', { timeout: 8000 }).catch(() => {})
|
||||
|
||||
if (!response || !response.ok()) {
|
||||
console.error(`FAIL ${check.path}: HTTP ${response ? response.status() : 'no-response'}`)
|
||||
|
||||
90
frontend/scripts/smoke-scroll-height.mjs
Normal file
90
frontend/scripts/smoke-scroll-height.mjs
Normal file
@@ -0,0 +1,90 @@
|
||||
import { chromium } from 'playwright'
|
||||
|
||||
const baseUrl = (process.env.BASE_URL || 'https://explorer.d-bis.org').replace(/\/$/, '')
|
||||
const viewportHeight = Number(process.env.SMOKE_VIEWPORT_HEIGHT || 720)
|
||||
const maxViewportHeights = Number(process.env.SMOKE_MAX_VIEWPORT_HEIGHTS || 2.5)
|
||||
|
||||
const routeLimits = new Map(
|
||||
(process.env.SMOKE_SCROLL_ROUTE_LIMITS || ' /=4,/operator=4,/transactions=3')
|
||||
.split(',')
|
||||
.map((entry) => entry.trim())
|
||||
.filter(Boolean)
|
||||
.map((entry) => {
|
||||
const [path, limit] = entry.split('=')
|
||||
return [path, Number(limit)]
|
||||
}),
|
||||
)
|
||||
|
||||
function limitForRoute(path) {
|
||||
return routeLimits.get(path) ?? maxViewportHeights
|
||||
}
|
||||
|
||||
const routes = [
|
||||
'/',
|
||||
'/bridge',
|
||||
'/routes',
|
||||
'/operations',
|
||||
'/system',
|
||||
'/operator',
|
||||
'/analytics',
|
||||
'/liquidity',
|
||||
'/blocks',
|
||||
'/transactions',
|
||||
'/addresses',
|
||||
'/wallet',
|
||||
'/access',
|
||||
]
|
||||
|
||||
async function main() {
|
||||
const browser = await chromium.launch({ headless: true })
|
||||
const page = await browser.newPage({
|
||||
viewport: { width: 1280, height: viewportHeight },
|
||||
})
|
||||
let failures = 0
|
||||
|
||||
for (const path of routes) {
|
||||
const url = `${baseUrl}${path}`
|
||||
|
||||
try {
|
||||
const response = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 20000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {})
|
||||
|
||||
if (!response || !response.ok()) {
|
||||
console.error(`FAIL ${path}: HTTP ${response ? response.status() : 'no-response'}`)
|
||||
failures += 1
|
||||
continue
|
||||
}
|
||||
|
||||
const scrollHeight = await page.evaluate(() => document.documentElement.scrollHeight)
|
||||
const routeLimit = limitForRoute(path)
|
||||
const limit = viewportHeight * routeLimit
|
||||
|
||||
if (scrollHeight > limit) {
|
||||
console.error(
|
||||
`FAIL ${path}: scrollHeight ${scrollHeight}px exceeds ${routeLimit}× viewport (${Math.round(limit)}px)`,
|
||||
)
|
||||
failures += 1
|
||||
continue
|
||||
}
|
||||
|
||||
console.log(`OK ${path} (${scrollHeight}px)`)
|
||||
} catch (error) {
|
||||
console.error(`FAIL ${path}: ${error instanceof Error ? error.message : String(error)}`)
|
||||
failures += 1
|
||||
}
|
||||
}
|
||||
|
||||
await browser.close()
|
||||
|
||||
if (failures > 0) {
|
||||
process.exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
console.log(`Scroll-height smoke passed for ${routes.length} routes at ${viewportHeight}px viewport`)
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error instanceof Error ? error.stack || error.message : String(error))
|
||||
process.exitCode = 1
|
||||
})
|
||||
Reference in New Issue
Block a user