oxedyne/daimond/dev/probe_passeye.mjs
2.5 KiB, 1 run
created by r2519314175:61, 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 | // probe_passeye.mjs — does the typed passphrase run under the reveal eye? |
| 2 | import { open, shot } from './harness.mjs'; |
| 3 | const s = await open({ name: 'passeye', signIn: false, connect: false }); |
| 4 | const { page } = s; |
| 5 | await page.waitForTimeout(1500); |
| 6 | // The warm skin is the one whose input padding shorthand wiped the reservation, |
| 7 | // so it is the one to measure under. |
| 8 | await page.evaluate(() => document.documentElement.setAttribute('data-skin', 'warm')); |
| 9 | await page.waitForTimeout(300); |
| 10 | const el = await page.$('#id-pass'); |
| 11 | if (el) { |
| 12 | await el.fill('correct-horse-battery-staple-correct-horse-battery-staple'); |
| 13 | await page.waitForTimeout(400); |
| 14 | } |
| 15 | const m = await page.evaluate(() => { |
| 16 | const inp = document.getElementById('id-pass'); |
| 17 | const eye = document.querySelector('#id-pass-row .pass-eye'); |
| 18 | if (!inp || !eye) return { missing: !inp ? 'input' : 'eye' }; |
| 19 | const ir = inp.getBoundingClientRect(), er = eye.getBoundingClientRect(); |
| 20 | const cs = getComputedStyle(inp); |
| 21 | // Where the text may actually reach: the content box's right edge. |
| 22 | const textRight = ir.right - parseFloat(cs.paddingRight) - parseFloat(cs.borderRightWidth); |
| 23 | // And how wide the value really is, measured rather than guessed. |
| 24 | const c = document.createElement('canvas').getContext('2d'); |
| 25 | c.font = `${cs.fontStyle} ${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`; |
| 26 | const inkW = c.measureText(inp.value).width; |
| 27 | return { |
| 28 | padRight: cs.paddingRight, |
| 29 | input: { l: Math.round(ir.left), r: Math.round(ir.right), w: Math.round(ir.width) }, |
| 30 | eye: { l: Math.round(er.left), r: Math.round(er.right), w: Math.round(er.width) }, |
| 31 | textRightEdge: Math.round(textRight), |
| 32 | overlap: +(textRight - er.left).toFixed(1), // > 0 means the text can run under the eye |
| 33 | inkWidth: Math.round(inkW), |
| 34 | scrolls: inp.scrollWidth > inp.clientWidth, |
| 35 | shown: inp.type, |
| 36 | // WHICH RULE WINS, asked of the browser rather than inferred from the file. |
| 37 | rules: (() => { |
| 38 | const out = []; |
| 39 | for (const sheet of document.styleSheets) { |
| 40 | let rules; try { rules = sheet.cssRules; } catch (e) { continue; } |
| 41 | for (const r of rules) { |
| 42 | if (!r.selectorText || !r.style || !r.style.padding && !r.style.paddingRight) continue; |
| 43 | try { if (!inp.matches(r.selectorText)) continue; } catch (e) { continue; } |
| 44 | out.push(`${(sheet.href || '').split('/').pop()} :: ${r.selectorText} { padding:${r.style.padding || '-'} padding-right:${r.style.paddingRight || '-'} }`); |
| 45 | } |
| 46 | } |
| 47 | return out; |
| 48 | })(), |
| 49 | }; |
| 50 | }); |
| 51 | console.log(JSON.stringify(m, null, 1)); |
| 52 | await shot(s, 'passeye'); |
| 53 | await s.browser.close(); |