Repository: pinojs/pino
Pull request #2034 (2024-08-22 15:55:20)

feat: accept level in capitals
### 💬**BASED ON**:
https://github.com/pinojs/pino/issues/2022#issuecomment-2304332920

### 🚀**UPDATES**: 
- converted level to lower case if passed in capitals.

✅ Added UnitTests.

balaji-atoa: HELP NEEDED! 
- Tried reproducing the same in my local by using the exact environment versions for node and npm. but, this passed.
![image](https://github.com/user-attachments/assets/a7bacf8c-8fea-4a95-8b21-7140b5f41121)

- ran `npm run test-ci` & it passed in my local.
```
$ npm run test-ci

> pino@9.3.2 test-ci
> npm run lint && npm run transpile && tap --ts --no-check-coverage --coverage-report=lcovonly && npm run test-types


> pino@9.3.2 lint
> eslint .


> pino@9.3.2 transpile
> node ./test/fixtures/ts/transpile.cjs

​ SKIP ​ test/broken-pipe.test.js
 ~ skipping on windows

​ SKIP ​ TAP
 ~ test/browser-early-console-freeze.test.js

​ SKIP ​ test/http.test.js
 ~ http request support via serializer without request connection

​ SKIP ​ test/transport/module-link.test.js
 ~ pino.transport with package

​ SKIP ​ test/transport/module-link.test.js                                                                                                                     
 ~ pino.transport with package as a target                                                                                                                      

​ SKIP ​ test/transport/module-link.test.js
 ~ pino({ transport })

​ SKIP ​ test/transport/module-link.test.js
 ~ pino({ transport }) from a wrapped dependency

​ SKIP ​ test/broken-pipe.test.js 1 skip of 1 3.142ms
 ~ skipping on windows

​ SKIP ​ test/browser-early-console-freeze.test.js 2s
​ SKIP ​ test/http.test.js 1 skip of 16 155.235ms
 ~ http request support via serializer without request connection

​ SKIP ​ test/transport/module-link.test.js 4 skip of 4 19.466ms
 ~ pino.transport with package
 ~ pino.transport with package as a target
 ~ pino({ transport })
 ~ pino({ transport }) from a wrapped dependency

Suites:   ​44 passed​, ​1 skip​, ​45 of 45 completed​
Asserts:  ​​​1334 passed​, ​7 skip​, ​of 1341​

> pino@9.3.2 test-types
> tsc && tsd && ts-node test/types/pino.ts

[16:39:30.633] CUSTOMDEBUG (9012): test3
[16:39:30.640] INFO (9012): test4
[16:39:30.641] CUSTOMERROR (9012): test5
[16:39:30.642] CUSTOMNETWORK (9012): test6
[16:39:30.622] INFO (9012): test2
    some: "bindings"
[16:39:30.625] INFO (9012): test2
[16:39:30.626] INFO (9012): test2
```

Patch:
diff --git a/pino.js b/pino.js
index 740b97d..2398e5a 100644
--- a/pino.js
+++ b/pino.js
@@ -88,6 +88,9 @@ const serializers = Object.assign(Object.create(null), stdSerializers)
 function pino (...args) {
   const instance = {}
   const { opts, stream } = normalize(instance, caller(), ...args)
+
+  if (opts.level && typeof opts.level === 'string' && DEFAULT_LEVELS[opts.level.toLowerCase()] !== undefined) opts.level = opts.level.toLowerCase()
+
   const {
     redact,
     crlf,


Test patch:
diff --git a/test/levels.test.js b/test/levels.test.js
index 1581bc1..cdf650c 100644
--- a/test/levels.test.js
+++ b/test/levels.test.js
@@ -704,3 +704,69 @@ test('trying to get levels when `this` is no longer a Pino instance returns an e
   const blankedLevelValue = notPinoInstance.getLevel()
   equal(blankedLevelValue, '')
 })
+
+test('accepts capital letter for INFO level', async ({ equal }) => {
+  const stream = sink()
+  const logger = pino({
+    level: 'INFO'
+  }, stream)
+
+  logger.info('test')
+  const { level } = await once(stream, 'data')
+  equal(level, 30)
+})
+
+test('accepts capital letter for FATAL level', async ({ equal }) => {
+  const stream = sink()
+  const logger = pino({
+    level: 'FATAL'
+  }, stream)
+
+  logger.fatal('test')
+  const { level } = await once(stream, 'data')
+  equal(level, 60)
+})
+
+test('accepts capital letter for ERROR level', async ({ equal }) => {
+  const stream = sink()
+  const logger = pino({
+    level: 'ERROR'
+  }, stream)
+
+  logger.error('test')
+  const { level } = await once(stream, 'data')
+  equal(level, 50)
+})
+
+test('accepts capital letter for WARN level', async ({ equal }) => {
+  const stream = sink()
+  const logger = pino({
+    level: 'WARN'
+  }, stream)
+
+  logger.warn('test')
+  const { level } = await once(stream, 'data')
+  equal(level, 40)
+})
+
+test('accepts capital letter for DEBUG level', async ({ equal }) => {
+  const stream = sink()
+  const logger = pino({
+    level: 'DEBUG'
+  }, stream)
+
+  logger.debug('test')
+  const { level } = await once(stream, 'data')
+  equal(level, 20)
+})
+
+test('accepts capital letter for TRACE level', async ({ equal }) => {
+  const stream = sink()
+  const logger = pino({
+    level: 'TRACE'
+  }, stream)
+
+  logger.trace('test')
+  const { level } = await once(stream, 'data')
+  equal(level, 10)
+})