| |
| |
|
|
| const assert = require('assert') |
| const { loadImage, createCanvas } = require('canvas') |
| const generateMethod = require('./methods/generate') |
| const QuoteGenerate = require('./utils/quote-generate') |
|
|
| |
| function leftColumnInk (img, colW) { |
| const canvas = createCanvas(img.width, img.height) |
| const ctx = canvas.getContext('2d') |
| ctx.drawImage(img, 0, 0) |
| const data = ctx.getImageData(0, 0, colW, img.height).data |
| let n = 0 |
| for (let i = 3; i < data.length; i += 4) if (data[i] > 32) n++ |
| return n |
| } |
|
|
| async function main () { |
| const scale = 2 |
| const msg = (chatId, text) => ({ |
| chatId, |
| avatar: true, |
| from: { id: chatId, name: `User ${chatId}`, photo: {} }, |
| text |
| }) |
|
|
| |
| |
| |
| |
| const grouped = await generateMethod({ messages: [msg(7, 'перше'), msg(7, 'друге')], scale }) |
| const ungrouped = await generateMethod({ messages: [msg(7, 'перше'), msg(8, 'друге')], scale }) |
| assert.ok(!grouped.error && !ungrouped.error, 'generate failed') |
|
|
| const colW = 50 * scale |
| const inkGrouped = leftColumnInk(await loadImage(Buffer.from(grouped.image, 'base64')), colW) |
| const inkUngrouped = leftColumnInk(await loadImage(Buffer.from(ungrouped.image, 'base64')), colW) |
| const ratio = inkGrouped / inkUngrouped |
| assert.ok(ratio > 0.35 && ratio < 0.65, |
| `grouped/ungrouped avatar ink ratio ${ratio.toFixed(2)} — expected ≈ 0.5 (one avatar of two)`) |
|
|
| |
| |
| |
| |
| const { drawVoiceRow } = require('./utils/quote-generate/attachments') |
| const { NAME_COLORS_DARK } = require('./utils/quote-generate/constants') |
| const waveform = Array.from({ length: 60 }, (_, i) => (i * 7) % 32) |
| const qg = new QuoteGenerate('0:x') |
| const voice = await qg.generate('#1b1429', '#1b1429', { |
| from: { id: 1, name: 'V' }, |
| voice: { waveform, duration: 42 }, |
| avatar: false |
| }, 512, 512, scale, 'apple') |
| |
| const row = drawVoiceRow(waveform, 42, NAME_COLORS_DARK[1], '#fff', scale, 512 * scale * 2 / 3) |
| assert.ok(row.width <= Math.ceil(512 * scale * 2 / 3), `voice row ${row.width} exceeds ⅔ cap`) |
| const expectedW = (50 + 10) * scale + (row.width + 2 * 16 * scale) + 12 * scale |
| assert.ok(Math.abs(voice.width - expectedW) <= 2, |
| `voice bubble width ${voice.width} != expected ${expectedW}`) |
|
|
| |
| |
| |
| const brightness = (p) => (p.r * 299 + p.g * 587 + p.b * 114) / 1000 |
| for (const [bgColor, label] of [['#252e44', 'dark'], ['#e8ecf3', 'light']]) { |
| const img = await generateMethod({ messages: [msg(7, 'контраст фону')], scale, type: 'image', backgroundColor: bgColor }) |
| assert.ok(!img.error, 'image generate failed') |
| const pic = await loadImage(Buffer.from(img.image, 'base64')) |
| const c = createCanvas(pic.width, pic.height) |
| const cx = c.getContext('2d') |
| cx.drawImage(pic, 0, 0) |
| const get = (x, y) => { |
| const d = cx.getImageData(x, y, 1, 1).data |
| return { r: d[0], g: d[1], b: d[2] } |
| } |
| |
| |
| const wallPx = get(8, 8) |
| const wall = brightness(wallPx) |
| const bubble = brightness(get(95 * scale / 2 + (50 + 10 + 20) * scale, Math.round(pic.height / 2))) |
| assert.ok(Math.abs(bubble - wall) >= 18, |
| `${label}: bubble (${bubble.toFixed(0)}) blends into wallpaper (${wall.toFixed(0)})`) |
| |
| if (label === 'light') { |
| const chroma = Math.max(wallPx.r, wallPx.g, wallPx.b) - Math.min(wallPx.r, wallPx.g, wallPx.b) |
| assert.ok(chroma >= 15, `light wallpaper is gray (chroma ${chroma}) — expected a pastel tint`) |
| } |
| console.log(` image/${label}: bubble ${bubble.toFixed(0)} vs wallpaper ${wall.toFixed(0)} (Δ${Math.abs(bubble - wall).toFixed(0)})`) |
| } |
|
|
| console.log('OK: fixes assertions passed') |
| console.log(` avatar ink ratio grouped/ungrouped = ${ratio.toFixed(3)} (≈0.5)`) |
| console.log(` voice bubble width = ${voice.width} (expected ${expectedW}, row ${row.width})`) |
| } |
|
|
| main().catch((err) => { |
| console.error('FAIL:', err.message) |
| process.exit(1) |
| }) |
|
|