Skip to content

Commit

Permalink
Finish test and add changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
cesxhin committed Sep 29, 2024
1 parent e196946 commit ca6ddb1
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 58 deletions.
8 changes: 8 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 29-09-2024
51 changes: 43 additions & 8 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,71 @@
import chalk from "chalk";
import {DateTime} from "luxon";
import _ from "lodash";
import {config} from "dotenv";
config();

type ILevel = "debug" | "info" | "warn" | "error" | "fatal";

class Logger {
nameService: string | null = null;
instanceLogger: Function = console.log;
level: ILevel = "info";

constructor(nameService: string, instanceLogger?: Function){
this.nameService = nameService.toUpperCase();

if (!_.isNil(instanceLogger)){
this.instanceLogger = instanceLogger;
}

const level = (process.env.LOG_LEVEL).toLowerCase() as ILevel;
switch(level){

Check failure on line 22 in index.ts

View workflow job for this annotation

GitHub Actions / test

Expected space(s) after "switch"
case "debug":
case "error":
case "info":
case "warn":
case "fatal":
this.level = level;
break;
default:
if(!_.isNil(level) && level !== "null" && level !== "undefined" && level !== ""){

Check failure on line 31 in index.ts

View workflow job for this annotation

GitHub Actions / test

Expected space(s) after "if"
this.#baseLog("fatal", "Not exist current level:", `"${level}"`, "select one of this: [debug|error|info|warn|fatal]")

Check failure on line 32 in index.ts

View workflow job for this annotation

GitHub Actions / test

Missing semicolon
process.exit(1);
}
}
}

debug(...args: Array<any>){
this.#baseLog("debug", ...args);
if(this.level === "debug"){

Check failure on line 39 in index.ts

View workflow job for this annotation

GitHub Actions / test

Expected space(s) after "if"
this.#baseLog("debug", ...args);
}
}

info(...args: Array<any>){
this.#baseLog("info", ...args);
if((["info", "debug"] as Array<ILevel>).includes(this.level)){

Check failure on line 45 in index.ts

View workflow job for this annotation

GitHub Actions / test

Expected space(s) after "if"
this.#baseLog("info", ...args);
}
}

warn(...args: Array<any>){
this.#baseLog("warning", ...args);
if((["info", "debug", "warn"] as Array<ILevel>).includes(this.level)){

Check failure on line 51 in index.ts

View workflow job for this annotation

GitHub Actions / test

Expected space(s) after "if"
this.#baseLog("warn", ...args);
}
}

error(...args: Array<any>){
this.#baseLog("error", ...args);
if((["info", "debug", "warn", "error"] as Array<ILevel>).includes(this.level)){

Check failure on line 57 in index.ts

View workflow job for this annotation

GitHub Actions / test

Expected space(s) after "if"
this.#baseLog("error", ...args);
}
}

fatal(...args: Array<any>){
this.#baseLog("fatal", ...args);
if((["info", "debug", "warn", "error", "fatal"] as Array<ILevel>).includes(this.level)){

Check failure on line 63 in index.ts

View workflow job for this annotation

GitHub Actions / test

Expected space(s) after "if"
this.#baseLog("fatal", ...args);
}
}

#baseLog(type: "debug" | "info" | "warning" | "error" | "fatal", ...args: Array<any>){
#baseLog(type: ILevel, ...args: Array<any>){
let message = `[${DateTime.now().toFormat("dd-MM-yyyy hh:mm:ssZZ")}] [${type.toUpperCase()}] [${this.nameService}]`;

args = args.map((message) => {
Expand All @@ -52,7 +83,7 @@ class Logger {
case "info":
message = chalk.blue(message, ...args);
break;
case "warning":
case "warn":
message = chalk.yellow(message, ...args);
break;
case "error":
Expand All @@ -67,4 +98,8 @@ class Logger {
}
}

export default Logger;
export default Logger;

export {
ILevel
}

Check failure on line 105 in index.ts

View workflow job for this annotation

GitHub Actions / test

Missing semicolon
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"typecheck": "tsc --noEmit",
"eslint": "eslint",
"eslint-fix": "eslint --fix",
"test_dev": "cd ./test && vitest",
"test-dev": "cd ./test && vitest",
"test": "cd ./test && FORCE_COLOR=1 vitest run",
"build": "tsc"
},
Expand All @@ -22,6 +22,7 @@
"@types/luxon": "^3.4.2",
"@types/node": "^22.7.4",
"chalk": "^5.3.0",
"dotenv": "^16.4.5",
"eslint": "^9.11.1",
"lodash": "^4.17.21",
"luxon": "^3.5.0",
Expand Down
218 changes: 169 additions & 49 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,178 @@
import Logger from "../index";
import { describe, it, expect, assert } from "vitest";
let output = "";
import { describe, it, expect, assert, vi } from "vitest";

function captureLog(message: any){
import Logger, { ILevel } from "../index";
import {alternateCase, listLevel} from "./utils/utils"

Check failure on line 4 in test/index.test.ts

View workflow job for this annotation

GitHub Actions / test

Missing semicolon

let output: any = null;

function captureLog(message: string){
//@ts-ignore
output = JSON.stringify(message).replaceAll("\"", "");
}

process.env.LOG_LEVEL = "debug";

describe("Test format", () => {
const logRegex = /\\u001b\[\d{1,3}m\[\d{2}-\d{2}-\d{4} \d{2}:\d{2}:\d{2}\+\d{2}:\d{2}\] \[(DEBUG|INFO|WARNING|ERROR|FATAL)\] \[TEST] .+?\\u001b\[\d{1,3}m/;
const logger = new Logger("test", captureLog);

it("check format debug", () => {
logger.debug("Hi!");
assert.match(output, logRegex, "Format isn't correct");
});
it("check format error", () => {

logger.error("Hi!");
assert.match(output, logRegex, "Format isn't correct");
});
it("check format fatal", () => {
logger.fatal("Hi!");
assert.match(output, logRegex, "Format isn't correct");
});
it("check format info", () => {
logger.info("Hi!");
assert.match(output, logRegex, "Format isn't correct");
});
it("check format warning", () => {
logger.warn("Hi!");
assert.match(output, logRegex, "Format isn't correct");
});
for (const objectLevel of listLevel) {
it(`check format ${objectLevel.level}`, () => {
output = null;
let logRegex = `\\\\u001b\\[\\d{1,3}m\\[\\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}:\\d{2}\\+\\d{2}:\\d{2}\\] \\[${objectLevel.level.toUpperCase()}\\] \\[TEST] .+?\\\\u001b\\[\\d{1,3}m`;

const logger = new Logger("test", captureLog);

logger[objectLevel.level]("Hi!");

assert.match(output, new RegExp(logRegex), `Format isn't correct for level --> ${objectLevel.level}`);
});
}
});

describe("Test colors", () => {
const logger = new Logger("test", captureLog);
it("check color debug", () => {
logger.debug("Hi!");
expect(output.startsWith("\\u001b[90m") && output.endsWith("\\u001b[39m")).eq(true);
});
it("check color error", () => {
logger.error("Hi!");
expect(output.startsWith("\\u001b[31m") && output.endsWith("\\u001b[39m")).eq(true);
});
it("check color fatal", () => {
logger.fatal("Hi!");
expect(output.startsWith("\\u001b[91m") && output.endsWith("\\u001b[39m")).eq(true);
});
it("check color info", () => {
logger.info("Hi!");
expect(output.startsWith("\\u001b[34m") && output.endsWith("\\u001b[39m")).eq(true);
});
it("check color warning", () => {
logger.warn("Hi!");
expect(output.startsWith("\\u001b[33m") && output.endsWith("\\u001b[39m")).eq(true);
});
for (const objectLevel of listLevel) {
it(`check color ${objectLevel.level}`, () => {
output = null;

const logger = new Logger("test", captureLog);
logger[objectLevel.level]("Hi!");
expect(output.startsWith(objectLevel.color) && output.endsWith("\\u001b[39m")).eq(true);
});
}
});

describe("Test log level from ENV", () => {
it("Log level: (empty)", () => {
output = null;
process.env.LOG_LEVEL = "";

const logger = new Logger("test", captureLog);
output = "";
logger.debug("Hi! custom");

expect(output).empty
})

it("Log level: null", () => {
output = null;
//@ts-ignore
process.env.LOG_LEVEL = null;

const logger = new Logger("test", captureLog);
output = "";
logger.debug("Hi! custom");

expect(output).empty
})

it("Log level: undefined", () => {
output = null;
process.env.LOG_LEVEL = undefined;

const logger = new Logger("test", captureLog);
output = "";
logger.debug("Hi! custom");

expect(output).empty
})

for (const objectLevel of listLevel) {
it(`Log level: ${objectLevel.level}`, () => {
output = null;
process.env.LOG_LEVEL = objectLevel.level;

const logger = new Logger("test", captureLog);
logger[objectLevel.level]("Hi!");
expect(output).not.null
});
}

for (const objectLevel of listLevel) {
it(`Log level: ${objectLevel.level.toUpperCase()}`, () => {
output = null;
process.env.LOG_LEVEL = objectLevel.level.toUpperCase();

const logger = new Logger("test", captureLog);
logger[objectLevel.level]("Hi!");
expect(output).not.null
});
}

for (const objectLevel of listLevel) {
it(`Log level: ${alternateCase(objectLevel.level)}`, () => {
output = null;
process.env.LOG_LEVEL = alternateCase(objectLevel.level);

const logger = new Logger("test", captureLog);
logger[objectLevel.level]("Hi!");
expect(output).not.null
});
}

it("Log level: debrn (not exist)", () => {
process.env.LOG_LEVEL = "debrn";
const exitCode = vi.spyOn(process, 'exit');

try{
new Logger("test", captureLog);
}catch{
//ignore
}

expect(exitCode).toHaveBeenCalledWith(1);
})

it("Log level: 1234 (not exist)", () => {
//@ts-ignore
process.env.LOG_LEVEL = 1234;
const exitCode = vi.spyOn(process, 'exit');

try{
new Logger("test", captureLog);
}catch{
//ignore
}

expect(exitCode).toHaveBeenCalledWith(1);
})
})


describe("Test print log level", () => {
for (const objectLevel of listLevel) {
it(`Log level: ${objectLevel.level}`, () => {
for (const singleLevel of listLevel.map((singleObjectlevel) => singleObjectlevel.level)) {
output = null;
process.env.LOG_LEVEL = singleLevel;

const logger = new Logger("test", captureLog);
logger[singleLevel]("Hi!");

if(objectLevel.level === "debug"){
expect(output).not.null
continue;
}

if((["debug", "info"] as Array<ILevel>)){
expect(output).not.null
continue;
}

if((["debug", "info", "warn"] as Array<ILevel>)){
expect(output).not.null
continue;
}

if((["debug", "info", "error"] as Array<ILevel>)){
expect(output).not.null
continue;
}

if((["debug", "info", "error", "fatal"] as Array<ILevel>)){
expect(output).not.null
continue;
}

expect(output).null;
}
});
}
});
32 changes: 32 additions & 0 deletions test/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ILevel } from "../..";

const listLevel: Array<{level: ILevel, color: string}> = [{
level: "debug",
color: "\\u001b[90m"
},{
level: "error",
color: "\\u001b[31m"
},{
level: "fatal",
color: "\\u001b[91m"
},{
level: "info",
color: "\\u001b[34m"
},{
level: "warn",
color: "\\u001b[33m"
}];

function alternateCase(text: string){
return text
.split('')
.map((char, index) =>
index % 2 === 0 ? char.toLowerCase() : char.toUpperCase()
)
.join('');
}

export {
alternateCase,
listLevel
}

0 comments on commit ca6ddb1

Please sign in to comment.