webdriverio/packages/wdio-logger/tests/node.test.ts
Christian Bromann 80779bb429
breaking(build): migrate to Esbuild for bundling (#13338)
* breaking(build): migrate to Rollup for bundling

* migrate more packages

* progress

* delete unnecessary tsconfigs

* migrate to esbuild

* revert npmignore changes

* more tweaks

* update pnpm-lock

* more tweaks

* compile scripts within browser environment

* fix ts issue in webdriverio

* add infra/compiler to readme

* fix lock file

* remove virtual:wdio from lock file

* update docs

* fix tests

* fix component tests

* fix unit tests

* clean up

* remove original build script

* more cleanups

* more cleanups

* last cleanup
2024-08-08 23:47:30 -07:00

309 lines
11 KiB
TypeScript

import fs from 'node:fs'
import { it, describe, expect, vi, afterEach, beforeEach, afterAll } from 'vitest'
import nodeLogger from '../src/index.js'
import nodeLogger2 from '../build/index.js'
import type log from 'loglevel'
vi.useFakeTimers()
vi.mock('chalk')
describe('wdio-logger node', () => {
describe('log level', () => {
const log = nodeLogger('test:setLevel')
it('DEFAULT_LEVEL', () => {
expect(log.getLevel()).toEqual(2)
})
const scenarios: {
level: log.LogLevelDesc,
logLevel: log.LogLevelNumbers
}[] = [{
level: 'trace',
logLevel: 0
}, {
level: 'debug',
logLevel: 1
}, {
level: 'info',
logLevel: 2
}, {
level: 'warn',
logLevel: 3
}, {
level: 'error',
logLevel: 4
}, {
level: 'silent',
logLevel: 5
}]
scenarios.forEach((scenario) => {
it(`should be possible to set ${scenario.level} logLevel`, () => {
nodeLogger.setLevel('test:setLevel', scenario.level)
expect(log.getLevel()).toEqual(scenario.logLevel)
})
})
})
describe('getLogger', () => {
const sameLog1 = nodeLogger('test:getLogger')
const sameLog2 = nodeLogger('test:getLogger')
const anotherLog = nodeLogger('test:getLogger:test')
it('should be possible to get same instance of logger', () => {
expect(sameLog1).toEqual(sameLog2)
})
it('should be possible to create new instance', () => {
expect(sameLog1).not.toEqual(anotherLog)
})
})
describe('setLogLevelsConfig', () => {
const scenarios: {
name: string
logger: string
config?: Record<string, log.LogLevelDesc>
logLevel: number
}[] = [{
name: 'should be possible to set logLevel in config',
logger: 'test-setLogLevelsConfig-3',
config: { 'test-setLogLevelsConfig-3': 'silent' },
logLevel: 5
}, {
name: 'should be possible to set logLevel in WDIO_LOG_LEVEL',
logger: 'test-setLogLevelsConfig-4',
get config() {
process.env.WDIO_LOG_LEVEL = 'info'
return undefined
},
logLevel: 2
}, {
name: 'should be possible to override WDIO_LOG_LEVEL in config',
logger: 'test-setLogLevelsConfig-5',
get config() {
process.env.WDIO_LOG_LEVEL = 'info'
return { 'test-setLogLevelsConfig-5': 'warn' as log.LogLevelDesc }
},
logLevel: 3
}, {
name: 'should be possible to set logLevel in config for all sub levels',
logger: 'test-setLogLevelsConfig-6:foo',
config: { 'test-setLogLevelsConfig-6:bar': 'error' as log.LogLevelDesc },
logLevel: 4
}]
scenarios.forEach((scenario) => {
it(scenario.name, () => {
nodeLogger.setLogLevelsConfig(scenario.config)
const log = nodeLogger(scenario.logger)
expect(log.getLevel()).toEqual(scenario.logLevel)
})
})
it('should apply logLevels after loggers are created', () => {
const log1 = nodeLogger('test-applyLogLevelsConfig1')
const log2 = nodeLogger('test-applyLogLevelsConfig1:foobar')
expect(log1.getLevel()).toEqual(2)
expect(log2.getLevel()).toEqual(2)
nodeLogger.setLogLevelsConfig({ 'test-applyLogLevelsConfig1': 'error' })
expect(log1.getLevel()).toEqual(4)
expect(log2.getLevel()).toEqual(4)
})
it('should not change logLevel if not provided in config', () => {
const log = nodeLogger('test-applyLogLevelsConfig')
expect(log.getLevel()).toEqual(2)
nodeLogger.setLogLevelsConfig(undefined)
expect(log.getLevel()).toEqual(2)
})
it('should set wdio logLevel passed as argument', () => {
const log = nodeLogger('test-wdio-log-level')
expect(log.getLevel()).toEqual(2)
nodeLogger.setLogLevelsConfig(undefined, 'error')
expect(log.getLevel()).toEqual(4)
})
afterEach(() => {
delete process.env.WDIO_LOG_LEVEL
})
})
describe('logFile', () => {
const write = vi.fn(logText => logText)
const logInfoSpy = vi.spyOn(fs, 'createWriteStream')
const logCacheAddSpy = vi.spyOn(Set.prototype, 'add')
const logCacheForEachSpy = vi.spyOn(Set.prototype, 'forEach')
let writableBuffer: any = null
logInfoSpy.mockImplementation((path: fs.PathLike): fs.WriteStream => ({
path: path as string,
write,
writable: true,
// @ts-ignore
get writableBuffer () {
// @ts-ignore
return writableBuffer
},
end: vi.fn()
}))
beforeEach(() => {
logCacheAddSpy.mockClear()
})
it('should be possible to add to cache', () => {
const log = nodeLogger('test-logFile1')
log.info('foo')
log.info('bar')
const logCache = logCacheAddSpy.mock.results[0].value
expect(logCacheAddSpy).toBeCalledTimes(2)
expect(logCache.size).toBe(2)
const logCacheValues = logCache.values()
expect(logCacheValues.next().value).toContain('test-logFile1: foo')
expect(logCacheValues.next().value).toContain('test-logFile1: bar')
// after
logCache.clear()
})
it('should be possible to create and write to logFile, with cache', () => {
const log = nodeLogger('test-logFile3')
log.info('foo')
const logCache = logCacheAddSpy.mock.results[0].value
process.env.WDIO_LOG_PATH = 'wdio.test.log'
log.info('bar')
expect(logInfoSpy).toBeCalledTimes(1)
expect(logCache.size).toBe(0)
expect(logCacheForEachSpy).toBeCalledTimes(1)
})
it('should be possible to create and write to logFile, no cache', () => {
process.env.WDIO_LOG_PATH = 'wdio.test.log'
const log = nodeLogger('test-logFile2')
log.info('foo')
log.info('bar')
expect(write.mock.calls.length).toBe(2)
expect(write.mock.results[0].value).toContain('test-logFile2: foo')
expect(write.mock.results[1].value).toContain('test-logFile2: bar')
expect(write.mock.results[1].value).not.toContain('test-logFile2: foo')
expect(logCacheForEachSpy).toBeCalledTimes(0)
})
it('serializers', () => {
process.env.WDIO_LOG_PATH = 'wdio.test.log'
const log = nodeLogger('test-logFile4')
log.info('DATA')
log.info('RESULT')
log.info('COMMAND')
log.info(new Error('bar'))
expect(write.mock.calls.length).toBe(4)
expect(write.mock.results[0].value).toContain('test-logFile4: yellow DATA')
expect(write.mock.results[1].value).toContain('test-logFile4: cyan RESULT')
expect(write.mock.results[2].value).toContain('test-logFile4: magenta COMMAND')
expect(write.mock.results[3].value).toContain('test-logFile4: Error: bar')
})
it('is not confused by multiple copies of source code', () => {
process.env.WDIO_LOG_PATH = 'wdio.test.log'
const log = nodeLogger('test-logFile4')
const log2 = nodeLogger2('test-logFile4')
log.info('foo')
log2.error(new Error('bar'))
expect(write.mock.calls.length).toBe(2)
expect(write.mock.results[0].value).toContain('test-logFile4: foo')
expect(write.mock.results[1].value).toContain('test-logFile4: Error: bar')
})
describe('clearLogger', () => {
it('should be possible to change output directory', () => {
process.env.WDIO_LOG_PATH = 'wdio.test.log'
const log = nodeLogger('test-logFile5')
log.info('foo')
nodeLogger.clearLogger()
process.env.WDIO_LOG_PATH = 'wdio.test.log2'
log.info('bar')
expect(write.mock.instances[0].path).toContain('wdio.test.log')
expect(write.mock.instances[1].path).toContain('wdio.test.log2')
})
})
describe('waitForBuffer with logFile', () => {
const scenarios = [{
name: 'should be ok buffer is empty',
writableBuffer: [],
logPath: 'wdio.test.log'
}, {
name: 'should flush if buffer is not defined',
writableBuffer: undefined,
logPath: 'wdio.test.log'
}]
scenarios.forEach((scenario, idx) => {
it(scenario.name, async () => {
process.env.WDIO_LOG_PATH = scenario.logPath
const log = nodeLogger(`test-logFile-buffer-${idx}`)
log.info('foo')
writableBuffer = scenario.writableBuffer
expect(await nodeLogger.waitForBuffer()).toBe(undefined)
})
})
it('should wait for buffer to be empty', async () => {
process.env.WDIO_LOG_PATH = 'wdio.test.log'
const log = nodeLogger('test-logFile-buffer-wait')
log.info('foo')
writableBuffer = ['bar']
const waitPromise = nodeLogger.waitForBuffer()
vi.advanceTimersByTime(30)
writableBuffer = []
vi.advanceTimersByTime(30)
expect(await waitPromise).toBe(undefined)
})
})
beforeEach(() => {
delete process.env.WDIO_LOG_PATH
nodeLogger.clearLogger()
nodeLogger2.clearLogger()
})
afterEach(() => {
logCacheForEachSpy.mockClear()
logCacheAddSpy.mockClear()
logInfoSpy.mockClear()
write.mockClear()
writableBuffer = undefined
})
afterAll(() => {
logInfoSpy.mockRestore()
})
})
describe('waitForBuffer with no logFile', () => {
it('should be ok if logFile is undefined', async () => {
expect(await nodeLogger.waitForBuffer()).toBe(undefined)
})
})
})