recording-timestamps.test.ts3.5 KBView on GitHub
import {
  clockToSeconds,
  fathomEmbedUrl,
  providerUrlAtSecond,
  secondsToClock,
} from '@/modules/documents/recording/timestamps';

describe('clockToSeconds', () => {
  it('reads the three shapes documents actually contain', () => {
    expect(clockToSeconds('12:40')).toBe(760);
    expect(clockToSeconds('01:12:40')).toBe(4360);
    expect(clockToSeconds('125')).toBe(125);
    expect(clockToSeconds('0:00')).toBe(0);
  });

  it('refuses anything it cannot read rather than guessing', () => {
    // A wrong seek is worse than no seek: the reader has no way to tell the player went to
    // the wrong second, so every unreadable value has to come back null.
    expect(clockToSeconds('twelve forty')).toBeNull();
    expect(clockToSeconds('12:40:11:02')).toBeNull();
    expect(clockToSeconds('-5')).toBeNull();
    expect(clockToSeconds('12:4a')).toBeNull();
    expect(clockToSeconds('')).toBeNull();
    expect(clockToSeconds(null)).toBeNull();
    expect(clockToSeconds(undefined)).toBeNull();
  });

  it('round-trips through secondsToClock', () => {
    expect(secondsToClock(760)).toBe('12:40');
    expect(secondsToClock(4360)).toBe('1:12:40');
    expect(secondsToClock(0)).toBe('0:00');
    expect(clockToSeconds(secondsToClock(760))).toBe(760);
  });
});

describe('providerUrlAtSecond', () => {
  const share = 'https://fathom.video/share/5mga_KS6XbvzmFJiRxRpzD-YFyGCMAQy';

  it('uses each provider spelling of a timestamp', () => {
    // Verified live 2026-08-27: ?timestamp=125 makes the share page report currentTime 125.
    expect(providerUrlAtSecond(share, 'fathom', 125)).toBe(`${share}?timestamp=125`);

    // Gong needs a span, not a point.
    const gong = providerUrlAtSecond('https://us-4796.app.gong.io/call?id=99', 'gong', 125);
    expect(gong).toContain('from=125');
    expect(gong).toContain('to=155');
    expect(gong).toContain('id=99');
  });

  it('leaves a provider with no known parameter untouched', () => {
    const cb = 'https://circleback.ai/view/abc';
    expect(providerUrlAtSecond(cb, 'circleback', 125)).toBe(cb);
    expect(providerUrlAtSecond(cb, null, 125)).toBe(cb);
  });

  it('passes the URL through when there is no timestamp, and null when there is no URL', () => {
    expect(providerUrlAtSecond(share, 'fathom', null)).toBe(share);
    expect(providerUrlAtSecond(null, 'fathom', 125)).toBeNull();
    expect(providerUrlAtSecond(undefined, 'fathom', 125)).toBeNull();
  });

  it('does not throw on a malformed URL', () => {
    expect(providerUrlAtSecond('not a url', 'fathom', 125)).toBe('not a url');
  });
});

describe('fathomEmbedUrl', () => {
  it('rewrites a share link onto the frameable embed route', () => {
    // /share/ sends X-Frame-Options: SAMEORIGIN; /embed/ sends neither that nor
    // frame-ancestors. Same token, different route. Verified live 2026-08-27.
    expect(fathomEmbedUrl('https://fathom.video/share/5mga_KS6Xbvz')).toBe(
      'https://fathom.video/embed/5mga_KS6Xbvz?autoplay=0',
    );
    expect(fathomEmbedUrl('https://fathom.video/share/5mga_KS6Xbvz/')).toBe(
      'https://fathom.video/embed/5mga_KS6Xbvz?autoplay=0',
    );
  });

  it('returns null for anything that is not a Fathom share link', () => {
    expect(fathomEmbedUrl('https://fathom.video/calls/123')).toBeNull();
    expect(fathomEmbedUrl('https://evil.example/share/abc')).toBeNull();
    expect(fathomEmbedUrl('https://circleback.ai/view/abc')).toBeNull();
    expect(fathomEmbedUrl(null)).toBeNull();
    expect(fathomEmbedUrl('nonsense')).toBeNull();
  });
});