Skip to content

Commit

Permalink
feat: add tests for logger
Browse files Browse the repository at this point in the history
  • Loading branch information
frytg committed Dec 12, 2024
1 parent c879848 commit 8fb424d
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 34 deletions.
36 changes: 15 additions & 21 deletions check-required-env/check-required-env.test.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,39 @@
import process from 'node:process'
import { test } from '@cross/test'
import { assertEquals, assertExists } from '@std/assert'
import { assertExists } from '@std/assert'
import sinon from 'sinon'

import { checkRequiredEnv } from './check-required-env.ts'

test('checkRequiredEnv - returns when env variable exists', () => {
// Setup
const testVarName = 'TEST_ENV_VAR'
process.env[testVarName] = 'test-value'
const envStub = sinon.stub(process, 'env').value({
TEST_ENV_VAR: 'test-value',
})

// Test
checkRequiredEnv(testVarName)
checkRequiredEnv('TEST_ENV_VAR')

// Verify
assertExists(process.env[testVarName])
assertExists(process.env.TEST_ENV_VAR)

// Cleanup
delete process.env[testVarName]
envStub.restore()
})

test('checkRequiredEnv - exits when env variable is missing', () => {
// Setup
const testVarName = 'MISSING_ENV_VAR'
const originalExit = process.exit
let exitCalled = false
let exitCode: number | undefined

// Mock process.exit
process.exit = ((code?: number) => {
exitCalled = true
exitCode = code
// Don't actually exit
}) as typeof process.exit
const envStub = sinon.stub(process, 'env').value({})
const exitStub = sinon.stub(process, 'exit')

// Test
checkRequiredEnv(testVarName)
checkRequiredEnv('MISSING_ENV_VAR')

// Verify
assertEquals(exitCalled, true)
assertEquals(exitCode, 1)
sinon.assert.calledOnce(exitStub)
sinon.assert.calledWith(exitStub, 1)

// Cleanup
process.exit = originalExit
exitStub.restore()
envStub.restore()
})
3 changes: 2 additions & 1 deletion deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@biomejs/biome": "npm:@biomejs/biome@^1.9.4",
"@types/node": "npm:@types/node@^22.10.2",
"@cross/test": "jsr:@cross/test@^0.0.10",
"@std/assert": "jsr:@std/assert@^1.0.9"
"@std/assert": "jsr:@std/assert@^1.0.9",
"sinon": "npm:sinon@^17.0.1"
}
}
75 changes: 74 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 61 additions & 0 deletions logger/logger-context.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import process from 'node:process'
import { test } from '@cross/test'
import { assertEquals, assertExists } from '@std/assert'
import sinon from 'sinon'

import logger from './logger.ts'

test('logger - includes global context in log events', () => {
// Setup
const envStub = sinon.stub(process, 'env').value({
K_REVISION: 'test-revision',
SERVICE_NAME: 'test-service',
STAGE: 'test',
npm_package_version: '1.0.0',
})

const writeStub = sinon.stub(process.stdout, 'write')
let loggedOutput = ''
writeStub.callsFake((str: string) => {
loggedOutput = str
return true
})

// Test
logger.info('test message', {
source: 'test-source',
data: { test: 'data' },
})

// Verify
const loggedData = JSON.parse(loggedOutput)
assertEquals(loggedData.host, 'test-revision')
assertEquals(loggedData.serviceName, 'test-service')
assertEquals(loggedData.stage, 'test')
assertEquals(loggedData.version, '1.0.0')
assertExists(loggedData.runtime)

// Cleanup
writeStub.restore()
envStub.restore()
})

test('logger - sets debug level correctly', () => {
// Test & Verify
assertEquals(logger.level, process.env.STAGE === 'dev' ? 'debug' : 'info')
})

test('logger - has correct syslog levels', () => {
const expectedLevels = {
emerg: 0,
alert: 1,
crit: 2,
error: 3,
warning: 4,
notice: 5,
info: 6,
debug: 7,
}

assertEquals(logger.levels, expectedLevels)
})
33 changes: 33 additions & 0 deletions logger/logger-format.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import process from 'node:process'
import { test } from '@cross/test'
import { assertEquals, assertExists } from '@std/assert'
import sinon from 'sinon'

import logger from './logger.ts'

test('logger - formats errors correctly', () => {
// Setup
const testError = new Error('test error')
const writeStub = sinon.stub(process.stdout, 'write')
let loggedOutput = ''
writeStub.callsFake((str: string) => {
loggedOutput = str
return true
})

// Test
logger.error('error occurred', {
source: 'test-source',
error: testError,
})

// Verify
const loggedData = JSON.parse(loggedOutput)
assertExists(loggedData.error.message)
assertExists(loggedData.error.stack)
assertEquals(loggedData.error.message, 'test error')
assertExists(loggedData.runtime)

// Cleanup
writeStub.restore()
})
20 changes: 9 additions & 11 deletions logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,14 @@ const convertGlobals = format((event) => {
})

// Set up format based on environment
let formatConfig: Logform.Format = format.combine(convertError(), convertGlobals(), format.json())
if (process.env.IS_LOCAL === 'true') {
formatConfig = format.combine(
convertError(),
convertGlobals(),
format.timestamp(),
format.json({ space: 4 }),
format.colorize({ all: true }),
)
}
const formatConfig: Logform.Format = format.combine(convertError(), convertGlobals(), format.json())
const formatConfigLocal: Logform.Format = format.combine(
convertError(),
convertGlobals(),
format.timestamp(),
format.json({ space: 4 }),
format.colorize({ all: true }),
)

/**
* Use the exported logger to log messages.
Expand Down Expand Up @@ -97,7 +95,7 @@ export const logger: Logger = createLogger({
level: process.env.STAGE === 'dev' ? 'debug' : 'info',
levels: config.syslog.levels,
exitOnError: false,
format: formatConfig,
format: process.env.IS_LOCAL === 'true' ? formatConfigLocal : formatConfig,
transports: [new transports.Console()],
})

Expand Down

0 comments on commit 8fb424d

Please sign in to comment.