← back to Boomer Calculator
tests/calculator-ui.cjs
55 lines
const { chromium, webkit, firefox } = require('/Users/macstudio3/.npm-global/lib/node_modules/openclaw/node_modules/playwright-core')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const url = process.argv[2] || 'http://127.0.0.1:18764/'
const out = process.argv[3] || 'verification/TK-11230/calculator'
fs.mkdirSync(out,{recursive:true})
async function journey(browser, name, mobile) {
const ctx = await browser.newContext({viewport: mobile ? {width:390,height:844} : {width:1280,height:1000},hasTouch:mobile,recordVideo:{dir:path.join(out,'video')}})
await ctx.route(/googlesyndication\.com|doubleclick\.net/,r=>r.abort())
const page=await ctx.newPage(), errors=[]
page.on('pageerror',e=>errors.push(e.message))
const response=await page.goto(url,{waitUntil:'networkidle'});assert.equal(response.status(),200)
const button=(name)=>page.getByRole('button',{name,exact:true})
const press=async(values)=>{for(const v of values) mobile ? await button(v).tap() : await button(v).click()}
const display=()=>page.getByRole('status').innerText()
await press(['0','*','5','=']);assert.equal(await display(),'0')
await press(['C','2','+','3','*','4','=']);assert.equal(await display(),'14')
await press(['+','1','=']);assert.equal(await display(),'15')
await press(['C','(','2','+','3',')','*','4','=']);assert.equal(await display(),'20')
await press(['C','sin','3','0',')','=']);assert.equal(await display(),'0.5')
await press(['C','1','/','0','=']);assert.match(await page.locator('p[role=alert]').innerText(),/divide by zero/)
await press(['C','7','*','8','=']);assert.equal(await display(),'56')
await page.screenshot({path:path.join(out,`${name}-arithmetic.png`),fullPage:true})
await button('🏠 Mortgage').click();await button('Calculate').click();assert.match(await page.locator('p[role=alert]').innerText(),/home price/)
await page.getByLabel('Home Price ($)',{exact:true}).fill('500000');await page.getByLabel('Down Payment ($)',{exact:true}).fill('100000');await page.getByLabel('Rate (%)',{exact:true}).fill('6.5')
await button('Calculate').click();assert.ok((await page.locator('body').innerText()).includes('$2528.27'))
await page.getByLabel('Rate (%)',{exact:true}).fill('0');assert.ok(!(await page.locator('body').innerText()).includes('$2528.27'))
await button('Calculate').click();assert.ok((await page.locator('body').innerText()).includes('$1111.11'))
await page.getByLabel('Down Payment ($)',{exact:true}).fill('500001');await button('Calculate').click();assert.match(await page.locator('p[role=alert]').innerText(),/down payment/)
await button('Reset').click();assert.equal(await page.getByLabel('Home Price ($)',{exact:true}).inputValue(),'')
await button('💪 BMI').click();await page.getByLabel('Weight (lbs)',{exact:true}).fill('150');await page.getByLabel('Height (in)',{exact:true}).fill('67');await button('Calculate').click();assert.ok((await page.locator('body').innerText()).includes('23.5'))
await button('kg / cm').click();assert.equal(await page.getByLabel('Weight (kg)',{exact:true}).inputValue(),'');assert.ok(!(await page.locator('body').innerText()).includes('23.5'))
await page.getByLabel('Weight (kg)',{exact:true}).fill('70');await page.getByLabel('Height (cm)',{exact:true}).fill('175');await button('Calculate').click();assert.ok((await page.locator('body').innerText()).includes('22.9'))
await page.getByLabel('Height (cm)',{exact:true}).fill('0');await button('Calculate').click();assert.match(await page.locator('p[role=alert]').innerText(),/greater than zero/)
await button('💵 Tip').click();await page.getByLabel('Bill ($)',{exact:true}).fill('100');await page.getByLabel('People',{exact:true}).fill('4');await button('20%').click();await button('Calculate').click()
for(const amount of ['$20.00','$120.00','$30.00'])assert.ok((await page.locator('body').innerText()).includes(amount))
await page.screenshot({path:path.join(out,`${name}-tip.png`),fullPage:true})
await page.getByLabel('People',{exact:true}).fill('1.5');await button('Calculate').click();assert.match(await page.locator('p[role=alert]').innerText(),/whole number/)
assert.equal(await page.evaluate(()=>document.documentElement.scrollWidth>innerWidth),false)
assert.deepEqual(errors,[])
await ctx.close()
return {name,status:'PASS',mobile,assertions:['HTTP 200','precedence','continuation','parentheses','sine degrees','division error and recovery','mortgage valid and zero interest','missing/invalid inputs','stale results clear on edits','BMI imperial and metric','unit switch reset','tips and splits','fractional people rejected','no overflow','zero JS errors']}
}
;(async()=>{
const results=[]
for(const [name,engine,options,mobile] of [['chrome-desktop',chromium,{channel:'chrome'},false],['chrome-touch',chromium,{channel:'chrome'},true],['webkit',webkit,{},true],['firefox',firefox,{},false]]){
let browser
try{browser=await engine.launch({headless:true,...options})}catch(e){if(name.startsWith('chrome'))throw e;results.push({name,status:'SKIP',reason:e.message.split('\n')[0]});continue}
try{results.push(await journey(browser,name,mobile))}finally{await browser.close()}
}
fs.writeFileSync(path.join(out,'browser-proof.json'),JSON.stringify({timestamp:new Date().toISOString(),url,adRequestsBlocked:true,results},null,2))
console.log(JSON.stringify(results,null,2))
})().catch(e=>{console.error(e);process.exit(1)})