import { describe, expect, it } from 'vitest'; import { ObjectId } from 'mongodb'; import { buildEmail, buildPush, dateLongFormat, normalizeLang, staticMapUrl, subjectTruncate, t, trim, } from '../src/messages.js'; import type { NotificationDoc } from '../src/types.js'; function fakeNotif(overrides: Partial = {}): NotificationDoc { return { _id: new ObjectId('0123456789abcdef01234567'), userId: 'user-1', subsId: new ObjectId('aaaaaaaaaaaaaaaaaaaaaaaa'), content: '🔥 Fuego cerca de tu zona en Galicia:', geo: { type: 'Point', coordinates: [-8.5, 42.3] }, // [lng, lat] type: 'mobile', when: new Date('2026-07-12T18:30:00Z'), sealed: 'fire-abc', ...overrides, }; } describe('trim (ported from NotificationsObserver/util.js)', () => { it('strips leading 🔥 and trailing colon', () => { expect(trim('🔥 Fuego cerca:')).toBe('Fuego cerca'); }); it('leaves other text intact', () => { expect(trim('Fuego en el monte')).toBe('Fuego en el monte'); }); }); describe('i18n strings (pinned from Meteor locales)', () => { it('title per language', () => { expect(t('Alerta de fuego', 'es')).toBe('Alerta de fuego'); expect(t('Alerta de fuego', 'en')).toBe('Alert of fire'); }); it('AppName per language', () => { expect(t('AppName', 'es')).toBe('Tod@s contra el Fuego'); expect(t('AppName', 'en')).toBe('All Against the Fire'); }); it('fireDetectedAt interpolates {{when}}', () => { expect(t('fireDetectedAt', 'es', { when: 'X' })).toBe('fuego detectado el X'); expect(t('fireDetectedAt', 'en', { when: 'X' })).toBe('fire detected on X'); }); }); describe('normalizeLang', () => { it('maps unknown langs to es', () => { expect(normalizeLang('fr')).toBe('es'); expect(normalizeLang(undefined)).toBe('es'); expect(normalizeLang('en-US')).toBe('en'); expect(normalizeLang('gl')).toBe('gl'); }); }); describe('subjectTruncate (ported)', () => { it('keeps short strings', () => { expect(subjectTruncate('short', 70)).toBe('short'); }); it('truncates on word boundary with ellipsis', () => { const s = 'a'.repeat(40) + ' ' + 'b'.repeat(40); const out = subjectTruncate(s, 70); expect(out.endsWith('...')).toBe(true); expect(out.length).toBeLessThanOrEqual(73); }); }); describe('buildPush (equivalent to old gcm.Message)', () => { it('produces title/body and full data payload', () => { const p = buildPush(fakeNotif(), 'es'); expect(p.title).toBe('Alerta de fuego'); expect(p.body).toBe('Fuego cerca de tu zona en Galicia'); // trimmed expect(p.clickAction).toBe('FLUTTER_NOTIFICATION_CLICK'); expect(p.sound).toBe('default'); expect(p.icon).toBe('launch_image'); expect(p.collapseKey).toBe('0123456789abcdef01234567'); expect(p.data.id).toBe('0123456789abcdef01234567'); expect(p.data.description).toBe('Fuego cerca de tu zona en Galicia'); expect(p.data.lat).toBe('42.3'); // coordinates[1] expect(p.data.lon).toBe('-8.5'); // coordinates[0] expect(p.data.sealed).toBe('fire-abc'); expect(p.data.subsId).toBe('aaaaaaaaaaaaaaaaaaaaaaaa'); }); it('handles missing subsId', () => { const p = buildPush(fakeNotif({ subsId: undefined }), 'en'); expect(p.data.subsId).toBe(''); expect(p.title).toBe('Alert of fire'); }); }); describe('buildEmail (equivalent to old processNotif web branch)', () => { it('builds subject, message and template vars', () => { const notif = fakeNotif({ type: 'web', content: '🔥 Incendio en A Coruña:' }); const e = buildEmail(notif, 'es', 'Ana', { rootUrl: 'https://fuegos.comunes.org/', gmapsKey: 'KEY', fireIconUrl: 'https://x/icon.png', }); expect(e.templateVars.firstName).toBe('Ana'); expect(e.templateVars.applicationName).toBe('Tod@s contra el Fuego'); expect(e.templateVars.message).toMatch(/^Incendio en A Coruña \(fuego detectado el .+\)\.$/); expect(e.templateVars.fireUrl).toBe('https://fuegos.comunes.org/fire/fire-abc'); expect(e.templateVars.subsUrl).toBe('https://fuegos.comunes.org/subscriptions'); expect(e.templateVars.img).toContain('maps.googleapis.com'); expect(e.subject.length).toBeLessThanOrEqual(73); }); it('normalizes rootUrl without trailing slash', () => { const e = buildEmail(fakeNotif({ type: 'web' }), 'en', 'Bob', { rootUrl: 'https://fires.comunes.org', }); expect(e.templateVars.fireUrl).toBe('https://fires.comunes.org/fire/fire-abc'); }); }); describe('staticMapUrl', () => { it('includes fire icon marker and coordinates', () => { const url = staticMapUrl(42.3, -8.5, { key: 'K', fireIconUrl: 'https://x/i.png' }); expect(url).toContain('center=42.3%2C-8.5'); expect(url).toContain('maptype=hybrid'); expect(url).toContain('zoom=16'); expect(url).toContain('key=K'); }); }); describe('dateLongFormat', () => { it('returns a localized long date with zone', () => { const s = dateLongFormat(new Date('2026-07-12T18:30:00Z'), 'es', 'Europe/Madrid'); expect(s).toMatch(/2026/); expect(s).toMatch(/\(.+\)$/); // zone in parens }); });