The .network host was retired 2026-07-27 and no longer resolves at all, so every reference to it named an address that cannot answer. The brand host is .cloud, matching kms.zoo.cloud and the rest of the white-label convention. Left alone deliberately, because rewriting them would invert what they say: the LLM.md line that RECORDS the retirement, the e2e spec that ASSERTS kms.lux.network must not resolve, and the recorded applies + cluster backups, which are faithful accounts of what was applied and are not config. Co-authored-by: Hanzo Dev <[email protected]>
100 lines
4.3 KiB
TypeScript
100 lines
4.3 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
import { httpStatus, snap } from './helpers'
|
|
|
|
// ── Lux Cloud — Subdomain Reachability ───────────────────────────────
|
|
// lux.cloud is the unified Lux cloud platform domain. Each subdomain
|
|
// should return 200 (or a valid redirect) via Cloudflare.
|
|
//
|
|
// Infra:
|
|
// lux.cloud root → bootnode/bootnode-web (white-labeled "Lux" client-side)
|
|
// api.lux.cloud → bootnode/bootnode-api
|
|
// console.lux.cloud → hanzo/console
|
|
// id.lux.cloud → hanzo/hanzo-login (IAM, alias of lux.id)
|
|
// kms.lux.cloud → hanzo/kms (alias of kms.lux.cloud)
|
|
// mpc.lux.cloud → lux-mpc/mpc-dashboard (alias of mpc.lux.network)
|
|
// nodes.lux.cloud → bootnode/bootnode-web (alias of web3.hanzo.ai)
|
|
|
|
const LUX_CLOUD_HOSTS = [
|
|
'https://lux.cloud',
|
|
'https://www.lux.cloud',
|
|
'https://api.lux.cloud',
|
|
'https://console.lux.cloud',
|
|
'https://id.lux.cloud',
|
|
'https://kms.lux.cloud',
|
|
'https://mpc.lux.cloud',
|
|
'https://nodes.lux.cloud',
|
|
]
|
|
|
|
test.describe('Lux Cloud — Subdomain Reachability', () => {
|
|
for (const url of LUX_CLOUD_HOSTS) {
|
|
test(`${url} returns HTTP 200/3xx`, async ({ request }) => {
|
|
const status = await httpStatus(request, url)
|
|
console.log(` ${url}: ${status}`)
|
|
expect([200, 301, 302, 307, 308]).toContain(status)
|
|
})
|
|
}
|
|
})
|
|
|
|
// ── Lux Cloud — Brand Rendering ──────────────────────────────────────
|
|
test.describe('Lux Cloud — Brand + Content', () => {
|
|
test('lux.cloud renders Lux brand via client-side hydration', async ({ page }) => {
|
|
await page.goto('https://lux.cloud', { waitUntil: 'domcontentloaded', timeout: 30_000 })
|
|
await page.waitForTimeout(3000) // hydration
|
|
const title = await page.title()
|
|
console.log(` title: ${title}`)
|
|
// After hydration, brand detection picks up lux.cloud → Lux brand
|
|
expect(title.length).toBeGreaterThan(0)
|
|
await snap(page, 'lux-cloud-home')
|
|
})
|
|
|
|
test('mpc.lux.cloud shows Lux MPC title', async ({ page }) => {
|
|
await page.goto('https://mpc.lux.cloud', { waitUntil: 'domcontentloaded', timeout: 30_000 })
|
|
await page.waitForTimeout(2000)
|
|
const title = await page.title()
|
|
console.log(` mpc title: ${title}`)
|
|
expect(title.toLowerCase()).toContain('lux')
|
|
await snap(page, 'mpc-lux-cloud')
|
|
})
|
|
|
|
test('id.lux.cloud serves login page', async ({ page }) => {
|
|
await page.goto('https://id.lux.cloud', { waitUntil: 'domcontentloaded', timeout: 30_000 })
|
|
await page.waitForTimeout(2000)
|
|
const bodyText = (await page.textContent('body')) || ''
|
|
expect(bodyText.length).toBeGreaterThan(50)
|
|
await snap(page, 'id-lux-cloud-login')
|
|
})
|
|
})
|
|
|
|
// ── Lux Cloud — API Health ───────────────────────────────────────────
|
|
test.describe('Lux Cloud — API Endpoints', () => {
|
|
test('api.lux.cloud responds', async ({ request }) => {
|
|
const status = await httpStatus(request, 'https://api.lux.cloud/health', 10_000)
|
|
console.log(` api health: ${status}`)
|
|
// Expect 200 or 404 if /health not wired, but not 5xx/timeout
|
|
expect(status).toBeLessThan(500)
|
|
})
|
|
|
|
test('nodes.lux.cloud dashboard loads', async ({ request }) => {
|
|
const status = await httpStatus(request, 'https://nodes.lux.cloud/dashboard', 15_000)
|
|
console.log(` nodes dashboard: ${status}`)
|
|
expect([200, 301, 302, 307, 308]).toContain(status)
|
|
})
|
|
})
|
|
|
|
// ── Lux Cloud — IAM Integration ──────────────────────────────────────
|
|
test.describe('Lux Cloud — IAM (lux.id) Flow', () => {
|
|
test('id.lux.cloud signup link resolves', async ({ page }) => {
|
|
await page.goto('https://id.lux.cloud/signup', { waitUntil: 'domcontentloaded', timeout: 30_000 })
|
|
const url = page.url()
|
|
console.log(` signup URL: ${url}`)
|
|
expect(url).toContain('lux.cloud')
|
|
})
|
|
|
|
test('id.lux.cloud and lux.id serve equivalent content', async ({ request }) => {
|
|
const a = await httpStatus(request, 'https://id.lux.cloud', 10_000)
|
|
const b = await httpStatus(request, 'https://lux.id', 10_000)
|
|
console.log(` id.lux.cloud=${a} lux.id=${b}`)
|
|
expect(a).toBe(b)
|
|
})
|
|
})
|