Files
ApiCore/ApiCore-Backend/src/telegram/telegram-texts.spec.ts
T
Nick SzaunigandClaude Opus 5.5 16cc557462
Backend Image / build-and-push (push) Successful in 4m26s
Frontend Image / build-and-push (push) Successful in 7m19s
Manifests / validate (push) Successful in 17s
feat: T4b/T4c wave 9 - phenology reports, autopilot A4-A10, honey ledger, Telegram delivery
- Phenology reports API with corrections and revokes; recompute per
  apiary via PhenologyRecomputeRequested, allowBackward for corrections;
  season changes are announced in the morning digest (changes since the
  previous digest, each once)
- Season autopilot A4-A10 with per-apiary sync (Apiary before Colony
  locks) and WinterCheckRecorded
- Honey batch ledger at runtime: initial amount, BOTTLING bookings,
  manual movements, one gram rounding, untracked bottlings never book
- Telegram delivery: planning, Berlin delivery times incl. DST, quiet
  hours, permission re-check and stale skip at send time, rate limits,
  cleanup of old deliveries
- ARCHITECTURE.md: assumptions 47-50 and updated sections 11.x

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-14 21:13:23 +02:00

106 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
renderTelegramText,
TELEGRAM_TEMPLATES,
TelegramTemplateCode,
} from './telegram-texts';
const ORIGIN = 'https://app.example.org';
describe('TELEGRAM_TEMPLATES', () => {
it('has the exact texts of the bot replies', () => {
expect(TELEGRAM_TEMPLATES).toEqual({
LINKED:
'Verbunden mit ApiCore. Hier kommen deine Erinnerungen. /stop beendet das.',
LINK_INVALID:
'Der Link ist ungültig oder abgelaufen. Bitte in ApiCore neu verbinden.',
STOPPED: 'Abgemeldet. Du bekommst keine Nachrichten mehr.',
HELP: 'Dieser Bot schickt Erinnerungen aus ApiCore. Verbinden geht nur in ApiCore unter Profil > Benachrichtigungen. /stop beendet.',
} satisfies Record<TelegramTemplateCode, string>);
});
});
describe('renderTelegramText', () => {
it('sends the message, a blank line and the app link', () => {
const text = renderTelegramText(
{ message: 'Heute fällig: Futter bestellen', link: '/tasks' },
true,
ORIGIN,
);
expect(text).toBe(
'Heute fällig: Futter bestellen\n\nhttps://app.example.org/tasks',
);
});
it('falls back to /dashboard without a link', () => {
const text = renderTelegramText({ message: 'm', link: null }, true, ORIGIN);
expect(text).toBe('m\n\nhttps://app.example.org/dashboard');
});
it('without details only says there is a new message, plus the link', () => {
const text = renderTelegramText(
{ message: 'Heute fällig: Schwarmzelle Völker', link: '/tasks' },
false,
ORIGIN,
);
expect(text).toBe(
'Neue Meldung in ApiCore.\n\nhttps://app.example.org/tasks',
);
expect(text).not.toContain('Schwarm');
});
it('tolerates a trailing slash of the origin', () => {
const text = renderTelegramText(
{ message: 'm', link: '/tasks' },
true,
`${ORIGIN}/`,
);
expect(text.endsWith('https://app.example.org/tasks')).toBe(true);
});
it('cuts a long message to at most 600 characters and keeps the link whole', () => {
const text = renderTelegramText(
{ message: 'ä'.repeat(2000), link: '/tasks' },
true,
ORIGIN,
);
expect([...text].length).toBeLessThanOrEqual(600);
expect(text.endsWith('\n\nhttps://app.example.org/tasks')).toBe(true);
expect(text).toContain('…\n\n');
});
it('counts code points, not UTF-16 units', () => {
const text = renderTelegramText(
{ message: '🐝'.repeat(1000), link: '/tasks' },
true,
ORIGIN,
);
expect([...text].length).toBeLessThanOrEqual(600);
expect(text).not.toMatch(/[\ud800-\udbff](?![\udc00-\udfff])/);
});
it('removes control characters and invisible characters from the message', () => {
const text = renderTelegramText(
{ message: 'a\u0007b‮c​d\r\ne', link: '/tasks' },
true,
ORIGIN,
);
expect(text).toBe('abcd\ne\n\nhttps://app.example.org/tasks');
});
it('without an origin sends the text alone, no link', () => {
expect(
renderTelegramText({ message: 'Hallo', link: '/tasks' }, true, null),
).toBe('Hallo');
expect(
renderTelegramText({ message: 'Hallo', link: '/tasks' }, false, null),
).toBe('Neue Meldung in ApiCore.');
});
});