const { describe, it } = require('node:test'); const assert = require('node:assert/strict'); const { parseEventToMeeting, formatEventChoice, isRecurring } = require('../lib/o365-calendar.js'); describe('parseEventToMeeting', () => { it('extracts meeting data from Graph API event', () => { const event = { id: 'AAMkAG123', subject: 'IT Team Weekly', start: { dateTime: '2026-04-14T09:00:00', timeZone: 'Europe/Berlin' }, end: { dateTime: '2026-04-14T10:00:00', timeZone: 'Europe/Berlin' }, body: { content: '
Agenda: Status updates
', contentType: 'html' }, attendees: [ { emailAddress: { name: 'Christopher Klein', address: 'c.klein@krah.de' }, type: 'required' }, { emailAddress: { name: 'Philip Losch', address: 'p.losch@krah.de' }, type: 'required' } ], seriesMasterId: 'AAMkSeries456' }; const result = parseEventToMeeting(event); assert.equal(result.id, 'AAMkAG123'); assert.equal(result.title, 'IT Team Weekly'); assert.equal(result.date, '2026-04-14'); assert.equal(result.start, '09:00'); assert.equal(result.end, '10:00'); assert.equal(result.bodyText, 'Agenda: Status updates'); assert.equal(result.attendees.length, 2); assert.equal(result.attendees[0].email, 'c.klein@krah.de'); assert.equal(result.attendees[0].name, 'Christopher Klein'); assert.equal(result.isRecurring, true); }); it('handles event without attendees', () => { const event = { id: 'AAMkAG789', subject: 'Focus Time', start: { dateTime: '2026-04-14T14:00:00', timeZone: 'Europe/Berlin' }, end: { dateTime: '2026-04-14T15:00:00', timeZone: 'Europe/Berlin' }, body: { content: '', contentType: 'text' }, attendees: [] }; const result = parseEventToMeeting(event); assert.equal(result.attendees.length, 0); assert.equal(result.isRecurring, false); assert.equal(result.bodyText, ''); }); }); describe('formatEventChoice', () => { it('formats event for selection list', () => { const meeting = { title: 'IT Team Weekly', date: '2026-04-14', start: '09:00', end: '10:00' }; const result = formatEventChoice(meeting); assert.equal(result, '📅 09:00-10:00 IT Team Weekly'); }); }); describe('isRecurring', () => { it('returns true when seriesMasterId exists', () => { assert.equal(isRecurring({ seriesMasterId: 'ABC' }), true); }); it('returns false when no seriesMasterId', () => { assert.equal(isRecurring({}), false); assert.equal(isRecurring({ seriesMasterId: null }), false); }); }); const { extractJoinUrlFromBody, getEventById } = require('../lib/o365-calendar.js'); describe('extractJoinUrlFromBody', () => { it('extracts teams meeting join URL from body html', () => { const html = 'Join'; assert.equal( extractJoinUrlFromBody(html), 'https://teams.microsoft.com/l/meetup-join/19%3aabc/0?context=foo' ); }); it('returns null when no teams url present', () => { assert.equal(extractJoinUrlFromBody('nothing
'), null); }); }); describe('getEventById', () => { it('throws TypeError when eventId is empty string', async () => { await assert.rejects( () => getEventById(''), { name: 'TypeError', message: /eventId must be a non-empty string/ } ); }); it('throws TypeError when eventId is not a string', async () => { await assert.rejects( () => getEventById(null), { name: 'TypeError', message: /eventId must be a non-empty string/ } ); }); it('throws TypeError when eventId is whitespace only', async () => { await assert.rejects( () => getEventById(' '), { name: 'TypeError', message: /eventId must be a non-empty string/ } ); }); });