oxedyne/daimond/dev/verify_tilering.mjs
5.3 KiB, 1 run
created by r2519314175:743, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | // The selected chat tile under the Breathe spacing: is its ring inside the box |
| 2 | // the list is entitled to clip? |
| 3 | // |
| 4 | // It counted its own reds all along and then exited 0, so the count reached |
| 5 | // nobody: `run_all.sh` reads the exit code. It exits on the count now. |
| 6 | // |
| 7 | // PROVED AGAINST TWO BREAKS FIRST, both applied as a stylesheet over the app's |
| 8 | // own — nothing on disk is touched: |
| 9 | // --break outerring the selected tile's ring is painted OUTSIDE its box, |
| 10 | // which is the defect this file is named for. |
| 11 | // --break flush the tiles are pushed flush to the list's edges, so the |
| 12 | // ring has nowhere to sit and the clip eats it. |
| 13 | // |
| 14 | // node dev/verify_tilering.mjs --break outerring # expected to FAIL |
| 15 | // node dev/verify_tilering.mjs --break flush # expected to FAIL |
| 16 | // node dev/verify_tilering.mjs # and then, clean |
| 17 | import { open, shot, newChat, errors } from './harness.mjs'; |
| 18 | |
| 19 | const ok = [], bad = []; |
| 20 | const check = (name, pass, detail) => { |
| 21 | (pass ? ok : bad).push(name + (detail ? ' — ' + detail : '')); |
| 22 | console.log((pass ? ' ok ' : ' FAIL ') + name + (detail ? ' — ' + detail : '')); |
| 23 | }; |
| 24 | |
| 25 | const BREAK = (() => { |
| 26 | const i = process.argv.indexOf('--break'); |
| 27 | return i > 0 ? String(process.argv[i + 1] || '') : ''; |
| 28 | })(); |
| 29 | const BREAKS = { |
| 30 | outerring: '#session-list .session-box.active, #session-list .session-box.active:hover' |
| 31 | + '{ box-shadow: 0 0 0 2px rgb(210,96,79) !important; }', |
| 32 | flush: '#session-list { padding-left: 0 !important; padding-right: 0 !important; }' |
| 33 | + '#session-list .session-box { margin-left: 0 !important; margin-right: 0 !important; }', |
| 34 | }; |
| 35 | if (BREAK && !BREAKS[BREAK]) { |
| 36 | console.error(`unknown break '${BREAK}'; known: ${Object.keys(BREAKS).join(', ')}`); |
| 37 | process.exit(2); |
| 38 | } |
| 39 | |
| 40 | const SP = new URL('shots/', import.meta.url).pathname; |
| 41 | const s = await open({ name: 'tile' }); |
| 42 | const { page } = s; |
| 43 | if (BREAK) console.log(`\n*** RUNNING UNDER --break ${BREAK}: failures below are the point ***\n`); |
| 44 | |
| 45 | // A chat first, while the app is in the state open() left it in, then the |
| 46 | // Breathe spacing applied in place -- a reload here loses the mock connection |
| 47 | // and the chat input never appears. |
| 48 | await newChat(s); |
| 49 | await page.waitForTimeout(400); |
| 50 | await page.evaluate(() => { |
| 51 | localStorage.setItem('daimond-skin', 'warm'); |
| 52 | document.documentElement.setAttribute('data-skin', 'warm'); |
| 53 | }); |
| 54 | await page.waitForTimeout(500); |
| 55 | if (BREAK) await page.addStyleTag({ content: BREAKS[BREAK] }); |
| 56 | // A CHAT tile, named by its list. `boxes[0]` was the first `.session-box` in the |
| 57 | // document, and the Diamonds rail is above the chats — so on any account with a |
| 58 | // Diamond this selected a Diamond tile, whose `closest('.session-list')` is null, |
| 59 | // and every measurement below came back null. It has been failing that way, on a |
| 60 | // file whose first line says "the selected chat tile". |
| 61 | await page.waitForSelector('#session-list .session-box', { timeout: 8000 }).catch(() => {}); |
| 62 | const boxes = await page.$$('#session-list .session-box'); |
| 63 | if (boxes.length) { await boxes[0].click({ force: true }); await page.waitForTimeout(500); } |
| 64 | |
| 65 | const m = await page.evaluate(() => { |
| 66 | const box = document.querySelector('#session-list .session-box.active') |
| 67 | || document.querySelector('#session-list .session-box'); |
| 68 | if (!box) return { err: 'no session box' }; |
| 69 | const list = box.closest('.session-list'); |
| 70 | const cs = getComputedStyle(box); |
| 71 | const b = box.getBoundingClientRect(); |
| 72 | const l = list ? list.getBoundingClientRect() : null; |
| 73 | const lcs = list ? getComputedStyle(list) : null; |
| 74 | return { |
| 75 | skin: document.documentElement.getAttribute('data-skin'), |
| 76 | shadow: cs.boxShadow, |
| 77 | // An inset ring paints within these edges; an outer one does not. |
| 78 | inset: cs.boxShadow.includes('inset'), |
| 79 | boxLeft: +b.left.toFixed(2), boxRight: +b.right.toFixed(2), |
| 80 | listLeft: l ? +l.left.toFixed(2) : null, listRight: l ? +l.right.toFixed(2) : null, |
| 81 | overflowX: lcs ? lcs.overflowX : null, |
| 82 | leftRoom: l ? +(b.left - l.left).toFixed(2) : null, |
| 83 | rightRoom: l ? +(l.right - b.right).toFixed(2) : null, |
| 84 | active: box.classList.contains('active'), |
| 85 | }; |
| 86 | }); |
| 87 | console.log(JSON.stringify(m, null, 1)); |
| 88 | |
| 89 | // Without a tile in the CHAT list there is nothing under test, and every |
| 90 | // measurement below would be `undefined` — which is not a pass. |
| 91 | check('there is a chat tile in the chat list to measure', !m.err && m.listLeft !== null, |
| 92 | m.err || `list ${m.listLeft}..${m.listRight}, tile ${m.boxLeft}..${m.boxRight}`); |
| 93 | check('the tile the ring belongs to is the selected one', !!m.active, `active=${m.active}`); |
| 94 | check('the Breathe spacing is on', m.skin === 'warm', `data-skin=${m.skin}`); |
| 95 | check('THE SELECTED TILE\'S RING IS DRAWN INSIDE ITS BOX', !!m.inset, m.shadow); |
| 96 | check('and the tiles have room for their lift either side', |
| 97 | m.leftRoom >= 2 && m.rightRoom >= 2, `left ${m.leftRoom}, right ${m.rightRoom}, list clips ${m.overflowX}`); |
| 98 | |
| 99 | const box = await page.$('.session-box.active') || (await page.$('.session-box')); |
| 100 | if (box) await box.screenshot({ path: `${SP}/tile-after.png` }); |
| 101 | await shot(s, 'tile-warm'); |
| 102 | |
| 103 | const errs = errors(s).filter(e => !/502|Bad Gateway/.test(e)); |
| 104 | check('nothing threw', errs.length === 0, errs.slice(0, 2).join(' | ')); |
| 105 | |
| 106 | await s.close(); |
| 107 | console.log(`\n${ok.length} passed, ${bad.length} failed`); |
| 108 | if (bad.length) { bad.forEach(x => console.log(' FAILED: ' + x)); process.exit(1); } |