diff --git a/package.json b/package.json index ed2c6c0..896df4c 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "@byu-oit/logger", - "version": "1.0.2", + "version": "2.0.0", "description": "Default configuration for pino logger", "engines": { - "node": ">=18" + "node": ">=20" }, "contributors": [ { @@ -35,14 +35,14 @@ "dist" ], "scripts": { - "build": "rimraf dist && concurrently \"npm:build:*\" -c cyanBright", + "build": "npm run clean && concurrently \"npm:build:*\" -c cyanBright", "build:cjs": "tsc -p tsconfig.cjs.json && echo-cli \"{\\\"type\\\": \\\"commonjs\\\"}\" > dist/cjs/package.json", "build:esm": "tsc -p tsconfig.json && echo-cli \"{\\\"type\\\": \\\"module\\\"}\" > dist/esm/package.json", "clean": "rimraf dist", - "coverage": "c8 ava", + "coverage": "c8 npm run test", "lint": "npx ts-standard | snazzy", "lint:fix": "npx ts-standard --fix | snazzy", - "test": "ava", + "test": "node --import tsimp --test test/*.spec.ts", "prepublishOnly": "npm run build" }, "author": "Brigham Young University - Office of Information Technology", @@ -60,32 +60,20 @@ "pino-http": "^10.2.0" }, "devDependencies": { - "@tsconfig/node18": "^18.2.4", - "@types/node": "^18.19.42", - "@types/sinon": "^17.0.3", - "ava": "^6.1.3", + "@tsconfig/node-lts": "^20.1.3", + "@tsconfig/node20": "^20.1.4", + "@types/node": "^22.7.5", "c8": "^10.1.2", "concurrently": "^8.2.2", "echo-cli": "^2.0.0", "pino-pretty": "^11.2.2", "rimraf": "^6.0.1", - "sinon": "^18.0.0", "snazzy": "^9.0.0", + "ts-standard": "^12.0.2", "tsimp": "^2.0.11", "typescript": "^5.5.4" }, "optionalDependencies": { "pino-pretty": ">=7" - }, - "lint-staged": { - "*.ts": "npm run lint:fix" - }, - "ava": { - "extensions": { - "ts": "module" - }, - "nodeArguments": [ - "--import=tsimp" - ] } } diff --git a/test/production.spec.ts b/test/production.spec.ts index a3304a3..01d99b9 100644 --- a/test/production.spec.ts +++ b/test/production.spec.ts @@ -1,82 +1,94 @@ -import ava, { TestFn } from 'ava' -import sinon, { SinonFakeTimers } from 'sinon' +import { describe, mock, test } from 'node:test' +import * as assert from 'node:assert' import { Logger } from 'pino' import { ByuLogger } from '../src/logger.js' interface Context { logged: string logger: Logger - clock: SinonFakeTimers now: Date } -const test = ava as TestFn +const ctx: Context = { + logged: '', + logger: ByuLogger(), + now: new Date(1000) +} test.before((t) => { /* Stub the date time */ - const jan1st = new Date(2021, 0, 1) - t.context.now = jan1st - t.context.clock = sinon.useFakeTimers(jan1st.getTime()) + mock.timers.enable({ apis: ['Date'] }) + mock.timers.setTime(1000) }) test.beforeEach((t) => { /* Capture the stdout pipe */ process.stdout.write = (buffer: string) => { - t.context.logged += buffer + ctx.logged += buffer return true } - process.env.NODE_ENV = 'production' - t.context.logged = '' - t.context.logger = ByuLogger() + process.env.NODE_ENV = 'test' + ctx.logged = '' + ctx.logger = ByuLogger() + ctx.now = new Date(1000) }) test.after((t) => { - t.context.clock.restore() + mock.timers.reset() }) -test.serial('default logger should default to info level', (t) => { - t.context.logger.debug('debug does not work') - - t.is(t.context.logger.level, 'info') - t.is(t.context.logged, '') // no logs should have happened +void describe('Default logger level is info', () => { + void test('default logger should default to info level', (context) => { + try { + ctx.logger.debug('debug does not work') + assert.equal(ctx.logger.level, 'info') + assert.equal(ctx.logged, '') // no logs should have happened + } catch (e) { + console.log(e) + assert.fail('Logger level not info') + } + }) }) -test.serial('default logger displays logs in JSON format', (t) => { - t.context.logger.info('json works') - - try { - const parsedLog = JSON.parse(t.context.logged) - t.truthy(parsedLog.message) - t.truthy(parsedLog.level) - t.truthy(parsedLog.time) - } catch (e) { - t.log(e) - t.fail('The log format should be stringified JSON but parsing failed. See the logged error for details.') - } +void describe('Default logger in JSON', () => { + void test('default logger displays logs in JSON format', (context) => { + ctx.logger.info('json works') + try { + const parsedLog = JSON.parse(ctx.logged) + assert.ok(parsedLog.message) + assert.ok(parsedLog.level) + assert.ok(parsedLog.time) + } catch (e) { + console.log(e) + assert.fail('No json output') + } + }) }) -test.serial('default logger should display info logs', (t) => { - t.context.logger.info('info works') - - try { - const parsedLog = JSON.parse(t.context.logged) - t.is(parsedLog.message, 'info works') - t.is(parsedLog.level, 'info') - } catch (e) { - t.log(e) - t.fail('The log format should be stringified JSON but parsing failed. See the logged error for details.') - } +void describe('Default logger contains "info"', () => { + void test('default logger should display info logs', (context) => { + ctx.logger.info('info works') + try { + const parsedLog = JSON.parse(ctx.logged) + assert.equal(parsedLog.message, 'info works') + assert.equal(parsedLog.level, 'info') + } catch (e) { + console.log(e) + assert.fail('Incorrect logger level') + } + }) }) -test.serial('default logger displays logs with epoch datetime format', (t) => { - t.context.logger.info('iso date works') - - try { - const parsedLog = JSON.parse(t.context.logged) - t.is(parsedLog.time, t.context.now.getTime()) - } catch (e) { - t.log(e) - t.fail('The log format should be stringified JSON but parsing failed. See the logged error for details.') - } +void describe('Display correct date format', () => { + void test('default logger displays logs with epoch datetime format', (context) => { + ctx.logger.info('iso date works') + try { + const parsedLog = JSON.parse(ctx.logged) + assert.equal(parsedLog.time, Date.now()) + } catch (e) { + console.log(e) + assert.fail('Incorrect date format logged') + } + }) }) diff --git a/test/test.spec.ts b/test/test.spec.ts index 8c98003..2ec73ff 100644 --- a/test/test.spec.ts +++ b/test/test.spec.ts @@ -1,49 +1,46 @@ -import ava, { TestFn } from 'ava' -import sinon, { SinonFakeTimers } from 'sinon' +import { test, mock } from 'node:test' +import assert from 'node:assert' import { Logger } from 'pino' import { ByuLogger } from '../src/logger.js' interface Context { logged: string logger: Logger - clock: SinonFakeTimers - now: Date } -const test = ava as TestFn +const context: Context = { + logged: '', + logger: ByuLogger() +} test.before((t) => { /* Stub the date time */ - const jan1st = new Date(2021, 0, 1) - t.context.now = jan1st - t.context.clock = sinon.useFakeTimers(jan1st.getTime()) + mock.timers.enable({ apis: ['Date'] }) + mock.timers.setTime(1000) }) test.beforeEach((t) => { /* Capture the stdout pipe */ process.stdout.write = (buffer: string) => { - t.context.logged += buffer + context.logged += buffer return true } - process.env.NODE_ENV = 'test' - t.context.logged = '' - t.context.logger = ByuLogger() + context.logged = '' + context.logger = ByuLogger() }) test.after((t) => { - t.context.clock.restore() + mock.timers.reset() }) -test.serial('default logger should default to silent level', (t) => { - t.context.logger.debug('debug does not work') - - t.is(t.context.logger.level, 'silent') - t.is(t.context.logged, '') // no logs should have happened +void test('default logger should default to silent level', (t) => { + context.logger.debug('debug does not work') + assert.equal(context.logger.level, 'silent') + assert.equal(context.logged, '') // no logs should have happened }) -test.serial('default logger should not display logs', (t) => { - t.context.logger.info('info works') - - t.is(t.context.logged, '') +void test('default logger should not display logs', (t) => { + context.logger.info('info works') + assert.equal(context.logged, '') })