- Updated branding from "SolaceScanScout" to "Solace" across various files including deployment scripts, API responses, and documentation. - Changed default base URL for Playwright tests and updated security headers to reflect the new branding. - Enhanced README and API documentation to include new authentication endpoints and product access details. This refactor aligns the project branding and improves clarity in the API documentation.
117 lines
4.0 KiB
JavaScript
117 lines
4.0 KiB
JavaScript
import { chromium } from 'playwright'
|
|
|
|
const baseUrl = (process.env.BASE_URL || 'https://explorer.d-bis.org').replace(/\/$/, '')
|
|
const addressUnderTest = process.env.SMOKE_ADDRESS || '0x99b3511a2d315a497c8112c1fdd8d508d4b1e506'
|
|
|
|
const checks = [
|
|
{ path: '/', expectTexts: ['SolaceScan', 'Recent Blocks', 'Open wallet tools'] },
|
|
{ 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: ['Chain 138 Liquidity Access', 'Explorer Access Points'] },
|
|
{ path: '/wallet', expectTexts: ['Wallet & MetaMask', 'Install Open Snap'] },
|
|
{ path: '/tokens', expectTexts: ['Tokens', 'Find A Token'] },
|
|
{ path: '/search', expectTexts: ['Search'], placeholder: 'Search by address, transaction hash, block number...' },
|
|
{ path: `/addresses/${addressUnderTest}`, expectTexts: [], anyOfTexts: ['Back to addresses', 'Address not found'] },
|
|
]
|
|
|
|
async function bodyText(page) {
|
|
return (await page.textContent('body')) || ''
|
|
}
|
|
|
|
async function hasShell(page) {
|
|
const homeLink = await page.getByRole('link', { name: /Go to explorer home/i }).isVisible().catch(() => false)
|
|
const supportText = await page.getByText(/Support:/i).isVisible().catch(() => false)
|
|
return homeLink && supportText
|
|
}
|
|
|
|
async function waitForBodyText(page, snippets, timeoutMs = 15000) {
|
|
if (!snippets || snippets.length === 0) {
|
|
return bodyText(page)
|
|
}
|
|
|
|
const deadline = Date.now() + timeoutMs
|
|
let lastText = ''
|
|
|
|
while (Date.now() < deadline) {
|
|
lastText = await bodyText(page)
|
|
if (snippets.every((snippet) => lastText.includes(snippet))) {
|
|
return lastText
|
|
}
|
|
await page.waitForTimeout(250)
|
|
}
|
|
|
|
return lastText
|
|
}
|
|
|
|
async function main() {
|
|
const browser = await chromium.launch({ headless: true })
|
|
const page = await browser.newPage()
|
|
let failures = 0
|
|
|
|
for (const check of checks) {
|
|
const url = `${baseUrl}${check.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 ${check.path}: HTTP ${response ? response.status() : 'no-response'}`)
|
|
failures += 1
|
|
continue
|
|
}
|
|
|
|
const text = await waitForBodyText(page, check.expectTexts)
|
|
const missing = check.expectTexts.filter((snippet) => !text.includes(snippet))
|
|
if (missing.length > 0) {
|
|
console.error(`FAIL ${check.path}: missing text ${missing.join(' | ')}`)
|
|
failures += 1
|
|
continue
|
|
}
|
|
|
|
if (check.anyOfTexts && !check.anyOfTexts.some((snippet) => text.includes(snippet))) {
|
|
console.error(`FAIL ${check.path}: expected one of ${check.anyOfTexts.join(' | ')}`)
|
|
failures += 1
|
|
continue
|
|
}
|
|
|
|
if (check.placeholder) {
|
|
const placeholderVisible = await page.getByPlaceholder(check.placeholder).isVisible().catch(() => false)
|
|
if (!placeholderVisible) {
|
|
console.error(`FAIL ${check.path}: missing placeholder ${check.placeholder}`)
|
|
failures += 1
|
|
continue
|
|
}
|
|
}
|
|
|
|
if (!(await hasShell(page))) {
|
|
console.error(`FAIL ${check.path}: shared explorer shell not visible`)
|
|
failures += 1
|
|
continue
|
|
}
|
|
|
|
console.log(`OK ${check.path}`)
|
|
} catch (error) {
|
|
console.error(`FAIL ${check.path}: ${error instanceof Error ? error.message : String(error)}`)
|
|
failures += 1
|
|
}
|
|
}
|
|
|
|
await browser.close()
|
|
|
|
if (failures > 0) {
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
console.log(`All ${checks.length} route checks passed for ${baseUrl}`)
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error(error instanceof Error ? error.stack || error.message : String(error))
|
|
process.exitCode = 1
|
|
})
|