UNPKG

@logtail/next

Version:

Better Stack Telemetry Next.js client

121 lines (102 loc) 4.07 kB
import { log } from '../src/logger'; import { test, expect, vi, vitest, Mock } from 'vitest'; vi.hoisted(() => { vi.stubEnv('NEXT_PUBLIC_BETTER_STACK_INGESTING_URL', 'https://example.co/api/test'); vi.stubEnv('NEXT_PUBLIC_BETTER_STACK_SOURCE_TOKEN', 'mytoken'); }); vi.useFakeTimers(); test('sending logs from browser', async () => { global.fetch = vi.fn(async () => { const resp = new Response('', { status: 200 }); return Promise.resolve(resp); }) as Mock<typeof fetch>; log.info('hello, world!'); expect(fetch).toHaveBeenCalledTimes(0); vi.advanceTimersByTime(1000); expect(fetch).toHaveBeenCalledTimes(1); log.info('hello, world!'); expect(fetch).toHaveBeenCalledTimes(1); await log.flush(); expect(fetch).toHaveBeenCalledTimes(2); }); test('with', async () => { global.fetch = vi.fn(async () => { const resp = new Response('', { status: 200 }); return Promise.resolve(resp); }); const logger = log.with({ foo: 'bar' }); logger.info('hello, world!', { bar: 'baz' }); expect(fetch).toHaveBeenCalledTimes(0); vi.advanceTimersByTime(1000); expect(fetch).toHaveBeenCalledTimes(1); const mockedFetch = fetch as Mock<typeof fetch>; const sentPayload = mockedFetch.mock.calls[0][1]?.body?.toString(); const payload = JSON.parse(sentPayload ? sentPayload : '{}'); expect(payload.length).toBe(1); const fst = payload[0]; expect(fst.level).toBe('info'); expect(fst.message).toBe('hello, world!'); expect(Object.keys(fst.fields).length).toBe(2); expect(fst.fields.foo).toBe('bar'); expect(fst.fields.bar).toBe('baz'); }); test('passing non-object', async () => { global.fetch = vi.fn(async () => { const resp = new Response('', { status: 200 }); return Promise.resolve(resp); }) as Mock<typeof fetch>; const logger = log.with({ foo: 'bar' }); const args = 'baz'; logger.info('hello, world!', args as unknown as object); expect(fetch).toHaveBeenCalledTimes(0); vi.advanceTimersByTime(1000); expect(fetch).toHaveBeenCalledTimes(1); const mockedFetch = fetch as Mock<typeof fetch>; const sentPayload = mockedFetch.mock.calls[0][1]?.body?.toString(); const payload = JSON.parse(sentPayload ? sentPayload : '{}'); expect(payload.length).toBe(1); const fst = payload[0]; expect(fst.level).toBe('info'); expect(fst.message).toBe('hello, world!'); expect(fst.fields.foo).toBe('bar'); expect(fst.fields.args).toBe('baz'); }); test('flushing child loggers', async () => { global.fetch = vitest.fn(async () => { const resp = new Response('', { status: 200 }); return Promise.resolve(resp); }); log.info('hello, world!'); const logger1 = log.with({ foo: 'bar' }); logger1.debug('logger1'); const logger2 = logger1.with({ bar: 'foo' }); logger2.debug('logger2'); expect(fetch).toHaveBeenCalledTimes(0); await log.flush(); expect(fetch).toHaveBeenCalledTimes(3); const mockedFetch = fetch as Mock<typeof fetch>; const sentPayload = mockedFetch.mock.calls[2][1]?.body?.toString(); const payload = JSON.parse(sentPayload ? sentPayload : '{}'); expect(Object.keys(payload[0].fields).length).toEqual(2); expect(payload[0].fields.foo).toEqual('bar'); expect(payload[0].fields.bar).toEqual('foo'); // ensure there is nothing was left unflushed await log.flush(); expect(fetch).toHaveBeenCalledTimes(3); }); test('throwing exception', async () => { global.fetch = vitest.fn(async () => { const resp = new Response('', { status: 200 }); return Promise.resolve(resp); }) as Mock<typeof fetch>; const err = new Error('test'); log.error('hello, world!', err); await log.flush(); expect(fetch).toHaveBeenCalledTimes(1); const mockedFetch = fetch as Mock<typeof fetch>; const sentPayload = mockedFetch.mock.calls[0][1]?.body?.toString(); const payload = JSON.parse(sentPayload ? sentPayload : '{}'); expect(Object.keys(payload[0].fields).length).toEqual(3); // { name, message, stack } expect(payload[0].fields.message).toEqual(err.message); expect(payload[0].fields.name).toEqual(err.name); });