Repository: octokit/webhooks.js
Pull request #462 (2021-02-12 21:42:23)

refactor: move `createLogger` into its own file
Lets us test the logger creation in isolation, so we can get full coverage easily.


Patch:
diff --git a/src/createLogger.ts b/src/createLogger.ts
new file mode 100644
index 0000000..8529966
--- /dev/null
+++ b/src/createLogger.ts
@@ -0,0 +1,14 @@
+export interface Logger {
+  debug: (message: string) => unknown;
+  info: (message: string) => unknown;
+  warn: (message: string) => unknown;
+  error: (message: string) => unknown;
+}
+
+export const createLogger = (logger?: Partial<Logger>): Logger => ({
+  debug: () => {},
+  info: () => {},
+  warn: console.warn.bind(console),
+  error: console.error.bind(console),
+  ...logger,
+});
diff --git a/src/event-handler/index.ts b/src/event-handler/index.ts
index 38018b2..cc878d4 100644
--- a/src/event-handler/index.ts
+++ b/src/event-handler/index.ts
@@ -1,8 +1,8 @@
+import { createLogger } from "../createLogger";
 import type {
   EmitterWebhookEvent,
   EmitterWebhookEventName,
   HandlerFunction,
-  Logger,
   Options,
   State,
   WebhookEventHandlerError,
@@ -49,13 +49,3 @@ export function createEventHandler<TTransformed>(
     receive: receive.bind(null, state),
   };
 }
-
-export function createLogger(logger?: Partial<Logger>) {
-  return {
-    debug: () => {},
-    info: /* istanbul ignore next: unused */ () => {},
-    warn: console.warn.bind(console),
-    error: console.error.bind(console),
-    ...logger,
-  };
-}
diff --git a/src/index.ts b/src/index.ts
index 618dd29..3848c88 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,6 @@
 import { IncomingMessage, ServerResponse } from "http";
-import { createEventHandler, createLogger } from "./event-handler/index";
+import { createLogger } from "./createLogger";
+import { createEventHandler } from "./event-handler/index";
 import { createMiddleware } from "./middleware/index";
 import { middleware } from "./middleware/middleware";
 import { verifyAndReceive } from "./middleware/verify-and-receive";
diff --git a/src/middleware/index.ts b/src/middleware/index.ts
index ff515e5..015602f 100644
--- a/src/middleware/index.ts
+++ b/src/middleware/index.ts
@@ -1,5 +1,6 @@
 import { debug } from "debug";
-import { createEventHandler, createLogger } from "../event-handler/index";
+import { createLogger } from "../createLogger";
+import { createEventHandler } from "../event-handler/index";
 import { middleware } from "./middleware";
 import { Options, State } from "../types";
 
diff --git a/src/types.ts b/src/types.ts
index d4de02b..7e3bd72 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -3,6 +3,7 @@ import type {
   WebhookEventMap,
   WebhookEventName,
 } from "@octokit/webhooks-definitions/schema";
+import { Logger } from "./createLogger";
 import type { emitterEventNames } from "./generated/webhook-names";
 
 export type EmitterWebhookEventName = typeof emitterEventNames[number];
@@ -38,13 +39,6 @@ type Hooks = {
   [key: string]: Function[];
 };
 
-export interface Logger {
-  debug: (message: string) => unknown;
-  info: (message: string) => unknown;
-  warn: (message: string) => unknown;
-  error: (message: string) => unknown;
-}
-
 export interface State extends Options<any> {
   eventHandler?: any;
   hooks: Hooks;


Test patch:
diff --git a/test/unit/createLogger-test.ts b/test/unit/createLogger-test.ts
new file mode 100644
index 0000000..568a6fd
--- /dev/null
+++ b/test/unit/createLogger-test.ts
@@ -0,0 +1,46 @@
+import { createLogger } from "../../src/createLogger";
+
+const noop = () => {};
+
+describe("createLogger", () => {
+  jest.spyOn(console, "warn").mockImplementation(noop);
+  jest.spyOn(console, "error").mockImplementation(noop);
+
+  describe("when nothing is passed", () => {
+    it("provides default implementations for all log levels", () => {
+      const logger = createLogger();
+
+      expect(() => logger.debug("hello world")).not.toThrow();
+      expect(() => logger.info("hello world")).not.toThrow();
+      expect(() => logger.warn("hello world")).not.toThrow();
+      expect(() => logger.error("hello world")).not.toThrow();
+    });
+  });
+
+  describe("when some log levels are provided", () => {
+    const partialLogger = {
+      debug: jest.fn(),
+      error: jest.fn(),
+    };
+
+    it("uses the provided implementations for the given log levels", () => {
+      const logger = createLogger(partialLogger);
+
+      logger.debug("hello world");
+      logger.error("hello world");
+
+      expect(partialLogger.debug).toHaveBeenCalledTimes(1);
+      expect(partialLogger.debug).toHaveBeenCalledWith("hello world");
+
+      expect(partialLogger.error).toHaveBeenCalledTimes(1);
+      expect(partialLogger.error).toHaveBeenCalledWith("hello world");
+    });
+
+    it("provides default implementations for the remaining log levels", () => {
+      const logger = createLogger(partialLogger);
+
+      expect(() => logger.info("hello world")).not.toThrow();
+      expect(() => logger.warn("hello world")).not.toThrow();
+    });
+  });
+});