Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add logger to property inspector, and support multiple log targets #35

Merged
merged 10 commits into from
Apr 18, 2024
68 changes: 68 additions & 0 deletions src/common/logging/__tests__/console-target.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { ConsoleTarget } from "../console-target";
import { LogLevel } from "../level";

describe("ConsoleTarget", () => {
/**
* Asserts {@link ConsoleTarget.write} logs to the error console.
*/
it("Error writes to error", () => {
// Arrange.
const target = new ConsoleTarget();
const spyOnConsoleError = jest.spyOn(console, "error").mockImplementationOnce(() => jest.fn());

// Act.
target.write({
data: ["Hello world"],
level: LogLevel.ERROR,
scope: "Test"
});

// Assert.
expect(spyOnConsoleError).toHaveBeenCalledTimes(1);
expect(spyOnConsoleError).toHaveBeenCalledWith("Hello world");
});

/**
* Asserts {@link ConsoleTarget.write} logs to the warn console.
*/
it("Warn writes to warn", () => {
// Arrange.
const target = new ConsoleTarget();
const spyOnConsoleWarn = jest.spyOn(console, "warn").mockImplementationOnce(() => jest.fn());

// Act.
target.write({
data: ["Hello world"],
level: LogLevel.WARN,
scope: "Test"
});

// Assert.
expect(spyOnConsoleWarn).toHaveBeenCalledTimes(1);
expect(spyOnConsoleWarn).toHaveBeenCalledWith("Hello world");
});

/**
* Asserts {@link ConsoleTarget.write} logs to the error console.
*/
it.each([
{ name: "Info", level: LogLevel.INFO },
{ name: "Debug", level: LogLevel.DEBUG },
{ name: "Trace", level: LogLevel.TRACE }
])("$name writes to log", ({ level }) => {
// Arrange.
const target = new ConsoleTarget();
const spyOnConsoleLog = jest.spyOn(console, "log").mockImplementationOnce(() => jest.fn());

// Act.
target.write({
data: ["Hello world"],
level,
scope: "Test"
});

// Assert.
expect(spyOnConsoleLog).toHaveBeenCalledTimes(1);
expect(spyOnConsoleLog).toHaveBeenCalledWith("Hello world");
});
});
174 changes: 174 additions & 0 deletions src/common/logging/__tests__/format.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { LogLevel } from "../../../common/logging";
import { stringFormatter } from "../format";

describe("stringFormatter", () => {
describe("data only", () => {
/**
* Asserts {@link stringFormatter} aggregates the data.
*/
test("without error", () => {
// Arrange, act.
const format = stringFormatter({ dataOnly: true });
const actual = format({
data: ["Hello", "World", { foo: "bar" }, true],
level: LogLevel.INFO,
scope: "Test"
});

// Assert.
expect(actual).toEqual(`Hello World {"foo":"bar"} true`);
});

/**
* Asserts {@link stringFormatter} aggregates data when one of the parameters is an error.
*/
test("with error", () => {
// Arrange, act.
const err = new Error("I am the error");
const format = stringFormatter({ dataOnly: true });
const actual = format({
data: ["Encountered an error", err, true],
level: LogLevel.INFO,
scope: ""
});

expect(actual).toEqual(`Encountered an error \n${err.stack}\ntrue`);
});
});

describe("full", () => {
const mockedDate = new Date(2000, 11, 25, 10, 30, 0, 123);
const mockedDateString = "2000-12-25T10:30:00.123Z";

beforeEach(() => jest.useFakeTimers().setSystemTime(mockedDate));

describe("aggregating data", () => {
/**
* Asserts {@link stringFormatter} aggregates the data.
*/
it("without error", () => {
// Arrange, act.
const format = stringFormatter();
const actual = format({
data: ["Hello", "World", { foo: "bar" }, true],
level: LogLevel.INFO,
scope: "Test"
});

// Assert.
expect(actual).toEqual(`${mockedDateString} INFO Test: Hello World {"foo":"bar"} true`);
});

/**
* Asserts {@link stringFormatter} aggregates data when one of the parameters is an error.
*/
it("with error", () => {
// Arrange, act.
const err = new Error("I am the error");
const format = stringFormatter();
const actual = format({
data: ["Encountered an error", err, true],
level: LogLevel.INFO,
scope: ""
});

expect(actual).toEqual(`${mockedDateString} INFO Encountered an error \n${err.stack}\ntrue`);
});
});

describe("log each level", () => {
/**
* Asserts {@link stringFormatter} for each log-level, without a scope.
*/
describe("without scope", () => {
const testCases = [
{
name: "ERROR",
level: LogLevel.ERROR,
expected: `${mockedDateString} ERROR Hello world`
},
{
name: "WARN",
level: LogLevel.WARN,
expected: `${mockedDateString} WARN Hello world`
},
{
name: "INFO",
level: LogLevel.INFO,
expected: `${mockedDateString} INFO Hello world`
},
{
name: "DEBUG",
level: LogLevel.DEBUG,
expected: `${mockedDateString} DEBUG Hello world`
},
{
name: "TRACE",
level: LogLevel.TRACE,
expected: `${mockedDateString} TRACE Hello world`
}
];

it.each(testCases)("$name message", ({ level, expected }) => {
// Arrange, act.
const format = stringFormatter();
const actual = format({
data: ["Hello world"],
level,
scope: ""
});

// Assert.
expect(actual).toEqual(expected);
});
});

/**
* Asserts {@link stringFormatter} for each log-level, with a scope.
*/
describe("with scope", () => {
const scope = "Test->Logger";
const testCases = [
{
name: "ERROR",
level: LogLevel.ERROR,
expected: `${mockedDateString} ERROR ${scope}: Hello world`
},
{
name: "WARN",
level: LogLevel.WARN,
expected: `${mockedDateString} WARN ${scope}: Hello world`
},
{
name: "INFO",
level: LogLevel.INFO,
expected: `${mockedDateString} INFO ${scope}: Hello world`
},
{
name: "DEBUG",
level: LogLevel.DEBUG,
expected: `${mockedDateString} DEBUG ${scope}: Hello world`
},
{
name: "TRACE",
level: LogLevel.TRACE,
expected: `${mockedDateString} TRACE ${scope}: Hello world`
}
];

it.each(testCases)("$name message", ({ level, expected }) => {
// Arrange, act.
const format = stringFormatter();
const actual = format({
data: ["Hello world"],
level,
scope
});

// Assert.
expect(actual).toEqual(expected);
});
});
});
});
});
Loading