/* global it, describe, beforeEach, afterEach */ const os = require('os') const path = require('path') const fs = require('fs') const LOG = require('./index') const hostname = os.hostname() function getDate () { var tzoffset = (new Date()).getTimezoneOffset() * 60000 // offset in milliseconds var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -1) return localISOTime.split('.')[0].trim() } const manualhostname = 'testhost' const name = 'testapp' let file = 'testfile' const filePath = '/tmp' function createLogLine(level, msg) { return getDate() + '\t' + hostname + '\t@general/log\t' + level + '\t' + msg } describe('@general/log', () => { describe('Contructor', () => { it('should log default with no options', () => { let log = new LOG(); expect(log.loglevel).toBe(2) expect(log.delimeter).toBe(' ') expect(log.name).toBe('@general/log') expect(log.hostname).toBe(hostname) expect(log.format).toBe('{timestamp}\t{hostname}\t{name}\t{loglevel}\t{message}') }) it('should use option hostname', () => { let log = new LOG({ hostname: 'test' }); expect(log.loglevel).toBe(2) expect(log.delimeter).toBe(' ') expect(log.name).toBe('@general/log') expect(log.hostname).toBe('test') expect(log.format).toBe('{timestamp}\t{hostname}\t{name}\t{loglevel}\t{message}') }) it('should use option name', () => { let log = new LOG({ name: 'test' }); expect(log.loglevel).toBe(2) expect(log.delimeter).toBe(' ') expect(log.name).toBe('test') expect(log.hostname).toBe(hostname) expect(log.format).toBe('{timestamp}\t{hostname}\t{name}\t{loglevel}\t{message}') }) it('should use option delimeter', () => { let log = new LOG({ delimeter: ';' }); expect(log.loglevel).toBe(2) expect(log.delimeter).toBe(';') expect(log.name).toBe('@general/log') expect(log.hostname).toBe(hostname) expect(log.format).toBe('{timestamp}\t{hostname}\t{name}\t{loglevel}\t{message}') }) it('should use option loglevel', () => { let log = new LOG({ loglevel: 'FATAL' }); expect(log.loglevel).toBe(0) expect(log.delimeter).toBe(' ') expect(log.name).toBe('@general/log') expect(log.hostname).toBe(hostname) expect(log.format).toBe('{timestamp}\t{hostname}\t{name}\t{loglevel}\t{message}') }) it('should use option format', () => { let log = new LOG({ format: '{message}' }); expect(log.loglevel).toBe(2) expect(log.delimeter).toBe(' ') expect(log.name).toBe('@general/log') expect(log.hostname).toBe(hostname) expect(log.format).toBe('{message}') }) }) describe('log by level', () => { it('should log fatal only if level is appropriate', () => { let log = new LOG({loglevel: 'FATAL'}); let logged = log.fatal('test') expect(logged).toBe(createLogLine('FATAL', 'test')) log = new LOG({loglevel: 'ERROR'}); logged = log.fatal('test') expect(logged).toBe(createLogLine('FATAL', 'test')) log = new LOG({loglevel: 'WARN'}); logged = log.fatal('test') expect(logged).toBe(createLogLine('FATAL', 'test')) log = new LOG({loglevel: 'NOTICE'}); logged = log.fatal('test') expect(logged).toBe(createLogLine('FATAL', 'test')) log = new LOG({loglevel: 'INFO'}); logged = log.fatal('test') expect(logged).toBe(createLogLine('FATAL', 'test')) log = new LOG({loglevel: 'DEBUG'}); logged = log.fatal('test') expect(logged).toBe(createLogLine('FATAL', 'test')) }) it('should log error only if level is appropriate', () => { let log = new LOG({loglevel: 'FATAL'}); let logged = log.error('test') expect(logged).toBe('') log = new LOG({loglevel: 'ERROR'}); logged = log.error('test') expect(logged).toBe(createLogLine('ERROR', 'test')) log = new LOG({loglevel: 'WARN'}); logged = log.error('test') expect(logged).toBe(createLogLine('ERROR', 'test')) log = new LOG({loglevel: 'NOTICE'}); logged = log.error('test') expect(logged).toBe(createLogLine('ERROR', 'test')) log = new LOG({loglevel: 'INFO'}); logged = log.error('test') expect(logged).toBe(createLogLine('ERROR', 'test')) log = new LOG({loglevel: 'DEBUG'}); logged = log.error('test') expect(logged).toBe(createLogLine('ERROR', 'test')) }) it('should log warnings only if level is appropriate', () => { let log = new LOG({loglevel: 'FATAL'}); let logged = log.warn('test') expect(logged).toBe('') log = new LOG({loglevel: 'ERROR'}); logged = log.warn('test') expect(logged).toBe('') log = new LOG({loglevel: 'WARN'}); logged = log.warn('test') expect(logged).toBe(createLogLine('WARN', 'test')) log = new LOG({loglevel: 'NOTICE'}); logged = log.warn('test') expect(logged).toBe(createLogLine('WARN', 'test')) log = new LOG({loglevel: 'INFO'}); logged = log.warn('test') expect(logged).toBe(createLogLine('WARN', 'test')) log = new LOG({loglevel: 'DEBUG'}); logged = log.warn('test') expect(logged).toBe(createLogLine('WARN', 'test')) }) it('should log notices only if level is appropriate', () => { let log = new LOG({loglevel: 'FATAL'}); let logged = log.notice('test') expect(logged).toBe('') log = new LOG({loglevel: 'ERROR'}); logged = log.notice('test') expect(logged).toBe('') log = new LOG({loglevel: 'WARN'}); logged = log.notice('test') expect(logged).toBe('') log = new LOG({loglevel: 'NOTICE'}); logged = log.notice('test') expect(logged).toBe(createLogLine('NOTICE', 'test')) log = new LOG({loglevel: 'INFO'}); logged = log.notice('test') expect(logged).toBe(createLogLine('NOTICE', 'test')) log = new LOG({loglevel: 'DEBUG'}); logged = log.notice('test') expect(logged).toBe(createLogLine('NOTICE', 'test')) }) it('should log info only if level is appropriate', () => { let log = new LOG({loglevel: 'FATAL'}); let logged = log.info('test') expect(logged).toBe('') log = new LOG({loglevel: 'ERROR'}); logged = log.info('test') expect(logged).toBe('') log = new LOG({loglevel: 'WARN'}); logged = log.info('test') expect(logged).toBe('') log = new LOG({loglevel: 'NOTICE'}); logged = log.info('test') expect(logged).toBe('') log = new LOG({loglevel: 'INFO'}); logged = log.info('test') expect(logged).toBe(createLogLine('INFO', 'test')) log = new LOG({loglevel: 'DEBUG'}); logged = log.info('test') expect(logged).toBe(createLogLine('INFO', 'test')) }) it('should log debug only if level is appropriate', () => { let log = new LOG({loglevel: 'FATAL'}); let logged = log.debug('test') expect(logged).toBe('') log = new LOG({loglevel: 'ERROR'}); logged = log.debug('test') expect(logged).toBe('') log = new LOG({loglevel: 'WARN'}); logged = log.debug('test') expect(logged).toBe('') log = new LOG({loglevel: 'NOTICE'}); logged = log.debug('test') expect(logged).toBe('') log = new LOG({loglevel: 'INFO'}); logged = log.debug('test') expect(logged).toBe('') log = new LOG({loglevel: 'DEBUG'}); logged = log.debug('test') expect(logged).toBe(createLogLine('DEBUG', 'test')) }) }) describe('log messages', () => { it('should log a string as is', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug('test') let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\ttest' expect(logged).toBe(expected) }) it('should log multiple strings with the delimeter', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug('test', 'test', 'test') let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\ttest test test' expect(logged).toBe(expected) }) it('should log a number as a string', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug(8) let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\t8' expect(logged).toBe(expected) }) it('should log a float as a string', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug(8.23) let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\t8.23' expect(logged).toBe(expected) }) it('should log a boolean as a string', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug(true) let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\ttrue' expect(logged).toBe(expected) }) it('should log an array as a string', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug(['test', 'test']) let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\ttest,test' expect(logged).toBe(expected) }) it('should log a json-object as a string', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug({some: 'value'}) let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\t{"some":"value"}' expect(logged).toBe(expected) }) it('should log a mixed entry as a string', () => { let log = new LOG({loglevel: 'DEBUG'}); let logged = log.debug('test', 7, 3.45, false, ['value', 'more'], {some: 'value'}) let expected = getDate() + '\t' + hostname + '\t@general/log\tDEBUG\ttest 7 3.45 false value,more {"some":"value"}' expect(logged).toBe(expected) }) }) describe('log formatting', () => { it('should log message only if set', () => { let log = new LOG({ format: '{message}', loglevel: 'DEBUG' }); let logged = log.debug('test') let expected = 'test' expect(logged).toBe(expected) }) it('should log hostname only if set', () => { let log = new LOG({ format: '{hostname}', loglevel: 'DEBUG' }); let logged = log.debug('test') let expected = hostname expect(logged).toBe(expected) }) it('should log name only if set', () => { let log = new LOG({ format: '{name}', loglevel: 'DEBUG' }); let logged = log.debug('test') let expected = '@general/log' expect(logged).toBe(expected) }) it('should log timestamp only if set', () => { let log = new LOG({ format: '{timestamp}', loglevel: 'DEBUG' }); let logged = log.debug('test') let expected = getDate() expect(logged).toBe(expected) }) it('should log loglevel only if set', () => { let log = new LOG({ format: '{loglevel}', loglevel: 'DEBUG' }); let logged = log.debug('test') let expected = 'DEBUG' expect(logged).toBe(expected) }) it('should log json like message if set', () => { let log = new LOG({ format: '{"timestamp":"{timestamp}", "level":"{loglevel}", "message":"{message}"}', loglevel: 'DEBUG' }); let logged = log.debug('test') let expected = '{"timestamp":"' + getDate() + '", "level":"DEBUG", "message":"test"}' expect(logged).toBe(expected) }) }) describe('log to file', () => { it('should create the folder if not exists', () => { let logPath = os.tmpdir() + '/log-test' + Math.floor(Math.random() * 1000) expect(() => { fs.accessSync(logPath, fs.constants.R_OK | fs.constants.W_OK) }).toThrow(); let log = new LOG({ path: logPath, file: 'test.log' }); expect(fs.accessSync(logPath, fs.constants.R_OK | fs.constants.W_OK)).toBeUndefined() }) it('should create the file if not exists', () => { let logPath = os.tmpdir() + '/log-test' + Math.floor(Math.random() * 1000) expect(() => { fs.accessSync(logPath + '/test.log', fs.constants.R_OK | fs.constants.W_OK) }).toThrow(); let log = new LOG({ path: logPath, file: 'test.log' }); expect(fs.accessSync(logPath + '/test.log', fs.constants.R_OK | fs.constants.W_OK)).toBeUndefined() }) it('should log to a file', (done) => { let logPath = os.tmpdir() + '/log-test' + Math.floor(Math.random() * 1000) let log = new LOG({ path: logPath, file: 'test.log' }); log.fatal('filetest') let expected = getDate() + '\t' + hostname + '\t@general/log\tFATAL\tfiletest\n' setTimeout(()=>{ expect(fs.readFileSync(logPath + '/test.log', 'utf8')).toBe(expected) done() },500 ) }) }) // TODO: log to loki // TODO: add mutation test })