diablo2-web/tests/challenger-m8-docking-stres...

361 lines
15 KiB
TypeScript

/**
* Empirical Challenger Stress Test Suite for Milestone M8:
* Widescreen Docking Mathematics, Boundary Conditions, and Resolution Scaling.
*
* @author teamwork_preview_challenger
* Target: `src/ui/hud-manager.ts` (`computeDockingLayout`, `computeHudLayout`)
*/
import { describe, it, expect } from 'vitest'
import {
computeDockingLayout,
computeHudLayout,
type DockingLayout,
} from '../src/ui/hud-manager.ts'
// Mock minimal window/DOM globals if running in headless node environment
class MockWindow extends EventTarget {
innerWidth = 1920
innerHeight = 1080
devicePixelRatio = 1
}
if (typeof globalThis.window === 'undefined') {
// @ts-ignore
globalThis.window = new MockWindow()
}
if (typeof globalThis.HTMLInputElement === 'undefined') {
// @ts-ignore
globalThis.HTMLInputElement = class HTMLInputElement {}
}
if (typeof globalThis.HTMLSelectElement === 'undefined') {
// @ts-ignore
globalThis.HTMLSelectElement = class HTMLSelectElement {}
}
// Deterministic 32-bit PRNG (Mulberry32) for reproducible fuzzing
function createPrng(seed: number = 0xdeadbeef) {
let s = seed >>> 0
return function nextFloat(): number {
s = (s + 0x6d2b79f5) | 0
let t = Math.imul(s ^ (s >>> 15), 1 | s)
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
}
// Independent Reference Oracle for Differential Testing
function referenceDockingOracle(w: number, h: number, dpr: number = 1): DockingLayout {
const safeW = Number.isFinite(w) && w > 0 ? w : 1
const safeH = Number.isFinite(h) && h > 0 ? h : 1
const safeDpr = Number.isFinite(dpr) && dpr > 0 ? dpr : 1
const uiScale = Math.min(safeW / 800, safeH / 600)
const offsetX = Math.max(0, (safeW - 800 * uiScale) / 2)
const offsetY = Math.max(0, safeH - 600 * uiScale)
const marginW = uiScale > 0 ? offsetX / uiScale : 0
const leftDockX = -marginW || 0
const rightDockX = 400 + marginW
const channelLeft = 400 - marginW
const channelRight = 400 + marginW
const channelWidthLogical = 2 * marginW
const channelWidthCss = 2 * offsetX
const isWidescreen = marginW > 0
return {
uiScale,
offsetX,
offsetY,
dpr: safeDpr,
physicalScale: uiScale * safeDpr,
physicalOffsetX: Math.round(offsetX * safeDpr),
physicalOffsetY: Math.round(offsetY * safeDpr),
marginW,
leftDockX,
rightDockX,
channelLeft,
channelRight,
channelWidthLogical,
channelWidthCss,
isWidescreen,
}
}
describe('Challenger M8: Widescreen Docking Mathematics Stress Test Suite', () => {
describe('1. Full Spectrum Resolution Matrix Stress Testing', () => {
const STANDARD_RESOLUTIONS: Array<{
name: string
w: number
h: number
expectedAspect: string
expectedWidescreen: boolean
}> = [
{ name: 'SVGA 4:3 (Classic)', w: 800, h: 600, expectedAspect: '4:3', expectedWidescreen: false },
{ name: 'XGA 4:3', w: 1024, h: 768, expectedAspect: '4:3', expectedWidescreen: false },
{ name: 'HD 16:9', w: 1280, h: 720, expectedAspect: '16:9', expectedWidescreen: true },
{ name: 'WXGA 16:10', w: 1280, h: 800, expectedAspect: '16:10', expectedWidescreen: true },
{ name: 'HD+ 16:9', w: 1366, h: 768, expectedAspect: '16:9', expectedWidescreen: true },
{ name: 'WSXGA 16:10', w: 1440, h: 900, expectedAspect: '16:10', expectedWidescreen: true },
{ name: 'HD+ 16:9', w: 1600, h: 900, expectedAspect: '16:9', expectedWidescreen: true },
{ name: 'FHD 1080p 16:9', w: 1920, h: 1080, expectedAspect: '16:9', expectedWidescreen: true },
{ name: 'QHD 1440p 16:9', w: 2560, h: 1440, expectedAspect: '16:9', expectedWidescreen: true },
{ name: 'UWQHD 21:9', w: 3440, h: 1440, expectedAspect: '21:9', expectedWidescreen: true },
{ name: '4K UHD 16:9', w: 3840, h: 2160, expectedAspect: '16:9', expectedWidescreen: true },
{ name: 'Super Ultrawide 32:9', w: 5120, h: 1440, expectedAspect: '32:9', expectedWidescreen: true },
]
it('evaluates computeDockingLayout accurately across all 12 standard resolutions', () => {
for (const res of STANDARD_RESOLUTIONS) {
const layout = computeDockingLayout(res.w, res.h)
expect(layout.isWidescreen, `${res.name} (${res.w}x${res.h}) widescreen flag`).toBe(
res.expectedWidescreen,
)
// Basic sanity
expect(layout.uiScale).toBeGreaterThan(0)
expect(layout.marginW).toBeGreaterThanOrEqual(0)
// Invariant: channelRight >= channelLeft and channelWidthLogical >= 0 (zero panel overlap)
expect(layout.channelRight).toBeGreaterThanOrEqual(layout.channelLeft)
expect(layout.channelWidthLogical).toBeGreaterThanOrEqual(0)
const overlap = Math.max(0, layout.channelLeft - layout.channelRight)
expect(overlap, `${res.name} panel overlap`).toBe(0)
// Invariant: leftDockX == -marginW and rightDockX == 400 + marginW
expect(layout.leftDockX).toBeCloseTo(-layout.marginW, 6)
expect(layout.rightDockX).toBeCloseTo(400 + layout.marginW, 6)
// Invariant: channelWidthCss == 2 * offsetX == cssW - 800 * uiScale
if (res.w / res.h >= 4 / 3 - 1e-6) {
expect(layout.channelWidthCss).toBeCloseTo(2 * layout.offsetX, 6)
expect(layout.channelWidthCss).toBeCloseTo(res.w - 800 * layout.uiScale, 6)
}
}
})
it('fuzzes across 300 randomly generated resolutions (widths 320 to 7680, heights 240 to 4320)', () => {
const prng = createPrng(0x1337c0de)
const FUZZ_COUNT = 300
for (let i = 0; i < FUZZ_COUNT; i++) {
// Generate diverse viewport sizes: widths 320..7680, heights 240..4320
const cssW = Math.round(320 + prng() * (7680 - 320))
const cssH = Math.round(240 + prng() * (4320 - 240))
const dpr = 0.5 + prng() * 3.5
const layout = computeDockingLayout(cssW, cssH, dpr)
const oracle = referenceDockingOracle(cssW, cssH, dpr)
// Differential assertion against oracle
expect(layout.uiScale).toBeCloseTo(oracle.uiScale, 8)
expect(layout.offsetX).toBeCloseTo(oracle.offsetX, 8)
expect(layout.offsetY).toBeCloseTo(oracle.offsetY, 8)
expect(layout.marginW).toBeCloseTo(oracle.marginW, 8)
expect(layout.leftDockX).toBeCloseTo(oracle.leftDockX, 8)
expect(layout.rightDockX).toBeCloseTo(oracle.rightDockX, 8)
expect(layout.channelLeft).toBeCloseTo(oracle.channelLeft, 8)
expect(layout.channelRight).toBeCloseTo(oracle.channelRight, 8)
expect(layout.channelWidthLogical).toBeCloseTo(oracle.channelWidthLogical, 8)
expect(layout.channelWidthCss).toBeCloseTo(oracle.channelWidthCss, 8)
expect(layout.isWidescreen).toBe(oracle.isWidescreen)
// Invariant 1: channelRight >= channelLeft and channelWidthLogical >= 0 (zero overlap)
expect(layout.channelRight).toBeGreaterThanOrEqual(layout.channelLeft)
expect(layout.channelWidthLogical).toBeGreaterThanOrEqual(0)
const overlap = Math.max(0, layout.channelLeft - layout.channelRight)
expect(overlap).toBe(0)
// Invariant 2: channelWidthCss == 2 * offsetX == cssW - 800 * uiScale for aspect >= 4:3
const aspectRatio = cssW / cssH
if (aspectRatio >= 4 / 3) {
expect(Math.abs(layout.channelWidthCss - 2 * layout.offsetX)).toBeLessThan(1e-6)
expect(Math.abs(layout.channelWidthCss - (cssW - 800 * layout.uiScale))).toBeLessThan(1e-6)
}
// Invariant 3: leftDockX == -marginW and rightDockX == 400 + marginW
expect(Math.abs(layout.leftDockX - (-layout.marginW))).toBeLessThan(1e-6)
expect(Math.abs(layout.rightDockX - (400 + layout.marginW))).toBeLessThan(1e-6)
}
})
})
describe('2. Classic 800x600 & 4:3 Bit-Exact Parity', () => {
it('verifies bit-exact D2 classic parity at 800x600', () => {
const docking = computeDockingLayout(800, 600)
// Bit-exact value assertions per spec
expect(docking.marginW).toBe(0)
expect(docking.leftDockX).toBe(0)
expect(docking.rightDockX).toBe(400)
expect(docking.channelWidthLogical).toBe(0)
expect(docking.channelLeft).toBe(400)
expect(docking.channelRight).toBe(400)
expect(docking.channelWidthCss).toBe(0)
expect(docking.isWidescreen).toBe(false)
expect(docking.uiScale).toBe(1.0)
expect(docking.offsetX).toBe(0)
expect(docking.offsetY).toBe(0)
})
it('verifies bit-exact 4:3 scaling parity at 1024x768', () => {
const docking = computeDockingLayout(1024, 768)
// Bit-exact value assertions per spec
expect(docking.marginW).toBe(0)
expect(docking.leftDockX).toBe(0)
expect(docking.rightDockX).toBe(400)
expect(docking.channelWidthLogical).toBe(0)
expect(docking.channelLeft).toBe(400)
expect(docking.channelRight).toBe(400)
expect(docking.channelWidthCss).toBe(0)
expect(docking.isWidescreen).toBe(false)
expect(docking.uiScale).toBe(1.28)
expect(docking.offsetX).toBe(0)
expect(docking.offsetY).toBe(0)
})
it('verifies 4:3 aspect ratio maintains zero margin across multiple standard 4:3 resolutions', () => {
const fourByThreeList = [
[640, 480],
[800, 600],
[1024, 768],
[1152, 864],
[1280, 960],
[1400, 1050],
[1600, 1200],
[2048, 1536],
]
for (const [w, h] of fourByThreeList) {
const d = computeDockingLayout(w, h)
expect(d.marginW).toBe(0)
expect(d.leftDockX).toBe(0)
expect(d.rightDockX).toBe(400)
expect(d.channelLeft).toBe(400)
expect(d.channelRight).toBe(400)
expect(d.channelWidthLogical).toBe(0)
expect(d.channelWidthCss).toBe(0)
expect(d.offsetX).toBe(0)
expect(d.isWidescreen).toBe(false)
}
})
})
describe('3. Extreme Viewport Boundary Cases', () => {
it('handles narrow and portrait viewports without negative marginW or NaN', () => {
const portraitViewports = [
{ name: '600x800', w: 600, h: 800 },
{ name: 'Mobile 360x640', w: 360, h: 640 },
{ name: 'Mobile FHD 1080x1920', w: 1080, h: 1920 },
{ name: 'Mobile HD 720x1280', w: 720, h: 1280 },
{ name: 'iPhone 390x844', w: 390, h: 844 },
{ name: 'Ultra-thin column 100x1000', w: 100, h: 1000 },
]
for (const vp of portraitViewports) {
const layout = computeDockingLayout(vp.w, vp.h)
expect(Number.isNaN(layout.marginW), `${vp.name} marginW is NaN`).toBe(false)
expect(Number.isFinite(layout.marginW), `${vp.name} marginW is finite`).toBe(true)
expect(layout.marginW, `${vp.name} marginW === 0`).toBe(0)
expect(layout.leftDockX, `${vp.name} leftDockX === 0`).toBe(0)
expect(layout.rightDockX, `${vp.name} rightDockX === 400`).toBe(400)
expect(layout.channelLeft, `${vp.name} channelLeft === 400`).toBe(400)
expect(layout.channelRight, `${vp.name} channelRight === 400`).toBe(400)
expect(layout.channelWidthLogical, `${vp.name} channelWidthLogical === 0`).toBe(0)
expect(layout.channelWidthCss, `${vp.name} channelWidthCss === 0`).toBe(0)
expect(layout.isWidescreen, `${vp.name} isWidescreen is false`).toBe(false)
expect(layout.offsetX, `${vp.name} offsetX === 0`).toBe(0)
expect(layout.offsetY, `${vp.name} offsetY >= 0`).toBeGreaterThanOrEqual(0)
}
})
it('handles zero, negative, and invalid numerical inputs gracefully without crashes or division by zero', () => {
const adversarialInputs = [
{ name: '0x0', w: 0, h: 0 },
{ name: '-100x600', w: -100, h: 600 },
{ name: '800x-600', w: 800, h: -600 },
{ name: '-500x-500', w: -500, h: -500 },
{ name: 'NaN x 600', w: NaN, h: 600 },
{ name: '800 x NaN', w: 800, h: NaN },
{ name: 'Infinity x 600', w: Infinity, h: 600 },
{ name: '800 x -Infinity', w: 800, h: -Infinity },
]
for (const adv of adversarialInputs) {
expect(() => {
const layout = computeDockingLayout(adv.w, adv.h)
expect(Number.isFinite(layout.uiScale), `${adv.name} uiScale is finite`).toBe(true)
expect(layout.uiScale, `${adv.name} uiScale > 0`).toBeGreaterThan(0)
expect(Number.isFinite(layout.marginW), `${adv.name} marginW is finite`).toBe(true)
expect(layout.marginW, `${adv.name} marginW >= 0`).toBeGreaterThanOrEqual(0)
expect(Number.isFinite(layout.leftDockX), `${adv.name} leftDockX is finite`).toBe(true)
expect(Number.isFinite(layout.rightDockX), `${adv.name} rightDockX is finite`).toBe(true)
expect(Number.isFinite(layout.channelLeft), `${adv.name} channelLeft is finite`).toBe(true)
expect(Number.isFinite(layout.channelRight), `${adv.name} channelRight is finite`).toBe(true)
expect(layout.channelRight).toBeGreaterThanOrEqual(layout.channelLeft)
}).not.toThrow()
}
})
it('scales layout dimensions cleanly across fractional DPIs (1.25, 1.5, 1.75, 2.0, 2.625)', () => {
const fractionalDprs = [1.25, 1.5, 1.75, 2.0, 2.625]
const baseResolutions = [
[800, 600],
[1920, 1080],
[2560, 1440],
[3440, 1440],
]
for (const [w, h] of baseResolutions) {
for (const dpr of fractionalDprs) {
const layout = computeDockingLayout(w, h, dpr)
// Verification of physical scaling metrics
expect(layout.dpr).toBe(dpr)
expect(layout.physicalScale).toBeCloseTo(layout.uiScale * dpr, 6)
expect(layout.physicalOffsetX).toBe(Math.round(layout.offsetX * dpr))
expect(layout.physicalOffsetY).toBe(Math.round(layout.offsetY * dpr))
// DPR should not alter logical docking metrics
const baseLayout = computeDockingLayout(w, h, 1)
expect(layout.marginW).toBeCloseTo(baseLayout.marginW, 8)
expect(layout.leftDockX).toBeCloseTo(baseLayout.leftDockX, 8)
expect(layout.rightDockX).toBeCloseTo(baseLayout.rightDockX, 8)
expect(layout.channelLeft).toBeCloseTo(baseLayout.channelLeft, 8)
expect(layout.channelRight).toBeCloseTo(baseLayout.channelRight, 8)
expect(layout.channelWidthLogical).toBeCloseTo(baseLayout.channelWidthLogical, 8)
expect(layout.channelWidthCss).toBeCloseTo(baseLayout.channelWidthCss, 8)
}
}
})
it('verifies extreme gargantuan (8K, 16K) and microscopic viewports', () => {
// 8K UHD: 7680x4320 (16:9)
const uhd8k = computeDockingLayout(7680, 4320)
expect(uhd8k.uiScale).toBeCloseTo(7.2, 4)
expect(uhd8k.offsetX).toBe(960)
expect(uhd8k.marginW).toBeCloseTo(133.333333, 4)
expect(uhd8k.channelWidthCss).toBe(1920)
expect(uhd8k.channelWidthLogical).toBeCloseTo(266.666667, 4)
// 16K: 15360x8640 (16:9)
const uhd16k = computeDockingLayout(15360, 8640)
expect(uhd16k.uiScale).toBeCloseTo(14.4, 4)
expect(uhd16k.offsetX).toBe(1920)
expect(uhd16k.marginW).toBeCloseTo(133.333333, 4)
expect(uhd16k.channelWidthCss).toBe(3840)
// Microscopic viewports
const micro = computeDockingLayout(1, 1)
expect(micro.uiScale).toBeGreaterThan(0)
expect(micro.marginW).toBe(0)
expect(micro.channelWidthLogical).toBe(0)
expect(micro.channelWidthCss).toBe(0)
})
})
})