Skip to content

Feature/371/logging provider #456

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

Merged
merged 20 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,5 @@ fabric.properties
/foo_asdf.jpg
/.scratch/
docs
scratch.js
debug.js
7 changes: 7 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export { Region } from "./lib/region.class";
export { Window } from "./lib/window.class";
export { FileType } from "./lib/file-type.enum";
export { ColorMode } from "./lib/colormode.enum";
export { LogProviderInterface } from "./lib/provider/log-provider.interface";
export {
useLogger,
useConsoleLogger,
ConsoleLogLevel,
} from "./lib/logging.function";

const lineHelper = new LineHelper();

Expand All @@ -63,6 +69,7 @@ const imageResource = (fileName: string) =>
screen.config.resourceDirectory,
fileName
);

export { fetchFromUrl } from "./lib/imageResources.function";

export {
Expand Down
3 changes: 3 additions & 0 deletions lib/clipboard.class.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ClipboardClass } from "./clipboard.class";
import { ProviderRegistry } from "./provider/provider-registry.class";
import { mockPartial } from "sneer";
import { ClipboardProviderInterface } from "./provider";
import { NoopLogProvider } from "./provider/log/noop-log-provider.class";

jest.mock("jimp", () => {});

Expand All @@ -21,6 +22,7 @@ describe("Clipboard class", () => {
copy: copyMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
const textToCopy = "bar";

// WHEN
Expand All @@ -40,6 +42,7 @@ describe("Clipboard class", () => {
paste: pasteMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
SUT.paste();
Expand Down
2 changes: 2 additions & 0 deletions lib/clipboard.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ export class ClipboardClass {
* @param text The text to copy
*/
public copy(text: string): Promise<void> {
this.providerRegistry.getLogProvider().debug(`Saving to clipboard`);
return this.providerRegistry.getClipboard().copy(text);
}

/**
* {@link paste} returns the current content of the system clipboard (limited to text)
*/
public paste(): Promise<string> {
this.providerRegistry.getLogProvider().debug(`Fetching clipboard content`);
return this.providerRegistry.getClipboard().paste();
}
}
13 changes: 13 additions & 0 deletions lib/logging.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { LogProviderInterface } from "./provider";
import { ConsoleLogLevel, ConsoleLogProvider, ConsoleLogProviderConfig } from "./provider/log/console-log-provider.class";
import providerRegistry from "./provider/provider-registry.class";

export const useLogger = (logger: LogProviderInterface) => {
providerRegistry.registerLogProvider(logger);
};

export const useConsoleLogger = (config?: ConsoleLogProviderConfig) => {
providerRegistry.registerLogProvider(new ConsoleLogProvider(config));
}

export { ConsoleLogLevel }
14 changes: 14 additions & 0 deletions lib/mouse.class.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LineHelper } from "./util/linehelper.class";
import { ProviderRegistry } from "./provider/provider-registry.class";
import { mockPartial } from "sneer";
import { MouseProviderInterface } from "./provider";
import { NoopLogProvider } from "./provider/log/noop-log-provider.class";

beforeEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -43,6 +44,7 @@ describe("Mouse class", () => {
scrollLeft: scrollMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.scrollLeft(scrollAmount);
Expand All @@ -64,6 +66,7 @@ describe("Mouse class", () => {
scrollRight: scrollMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.scrollRight(scrollAmount);
Expand All @@ -85,6 +88,7 @@ describe("Mouse class", () => {
scrollDown: scrollMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.scrollDown(scrollAmount);
Expand All @@ -106,6 +110,7 @@ describe("Mouse class", () => {
scrollUp: scrollMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.scrollUp(scrollAmount);
Expand All @@ -127,6 +132,7 @@ describe("Mouse class", () => {
setMousePosition: setPositionMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.move(path);
Expand All @@ -152,6 +158,7 @@ describe("Mouse class", () => {
releaseButton: releaseButtonMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.drag(path);
Expand Down Expand Up @@ -182,6 +189,7 @@ describe("Mouse class", () => {
releaseButton: releaseButtonMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const pressed = await SUT.pressButton(input);
Expand Down Expand Up @@ -209,6 +217,7 @@ describe("Mouse class", () => {
pressButton: mouseMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const start = Date.now();
Expand All @@ -232,6 +241,7 @@ describe("Mouse class", () => {
releaseButton: mouseMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const start = Date.now();
Expand Down Expand Up @@ -262,6 +272,7 @@ describe("Mouse class", () => {
click: clickMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
await SUT.click(input);
Expand Down Expand Up @@ -289,6 +300,7 @@ describe("Mouse class", () => {
doubleClick: clickMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
await SUT.doubleClick(input);
Expand All @@ -312,6 +324,7 @@ describe("Mouse class", () => {
click: clickMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.leftClick();
Expand All @@ -336,6 +349,7 @@ describe("Mouse class", () => {
click: clickMock,
})
);
providerRegistryMock.getLogProvider = () => new NoopLogProvider();

// WHEN
const result = await SUT.rightClick();
Expand Down
4 changes: 4 additions & 0 deletions lib/mouse.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,15 @@ export class MouseClass {
`setPosition requires a Point, but received ${JSON.stringify(target)}`
);
}
this.providerRegistry
.getLogProvider()
.info("Setting mouse position", target);
return new Promise<MouseClass>(async (resolve, reject) => {
try {
await this.providerRegistry.getMouse().setMousePosition(target);
resolve(this);
} catch (e) {
this.providerRegistry.getLogProvider().error(e as Error);
reject(e);
}
});
Expand Down
60 changes: 60 additions & 0 deletions lib/provider/image/jimp-image-processor.class.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Image } from "../../image.class";
import { Point } from "../../point.class";
import JimpImageProcessor from "./jimp-image-processor.class";

const imageWidth = 10;
const imageHeight = 20;

describe("JimpImageProcessor", () => {
it.each([[new Point(-1, 5)], [new Point(imageWidth + 5, 5)]])(
`should reject on out of bounds x coordinates`,
async (outOfBoundsPoint: Point) => {
// GIVEN
const inputImage = new Image(
imageWidth,
imageHeight,
Buffer.from([0, 0, 0]),
3,
"input_image",
4,
4
);
const SUT = new JimpImageProcessor();

// WHEN
const result = SUT.colorAt(inputImage, outOfBoundsPoint);

// THEN
await expect(result).rejects.toBe(
`Query location out of bounds. Should be in range 0 <= x < image.width, is ${outOfBoundsPoint.x}`
);
}
);

it.each([[new Point(5, -1)], [new Point(5, imageHeight + 10)]])(
`should reject on out of bounds y coordinates`,
async (outOfBoundsPoint: Point) => {
// GIVEN
const imageWidth = 10;
const imageHeight = 20;
const inputImage = new Image(
imageWidth,
imageHeight,
Buffer.from([0, 0, 0]),
3,
"input_image",
4,
4
);
const SUT = new JimpImageProcessor();

// WHEN
const result = SUT.colorAt(inputImage, outOfBoundsPoint);

// THEN
await expect(result).rejects.toBe(
`Query location out of bounds. Should be in range 0 <= y < image.height, is ${outOfBoundsPoint.y}`
);
}
);
});
2 changes: 2 additions & 0 deletions lib/provider/image/jimp-image-processor.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ export default class implements ImageProcessor {
reject(
`Query location out of bounds. Should be in range 0 <= x < image.width, is ${location.x}`
);
return;
}
if (location.y < 0 || location.y >= img.height) {
reject(
`Query location out of bounds. Should be in range 0 <= y < image.height, is ${location.y}`
);
return;
}
const jimpImage = imageToJimp(img);
const rgba = Jimp.intToRGBA(
Expand Down
21 changes: 11 additions & 10 deletions lib/provider/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export { ClipboardProviderInterface } from "./clipboard-provider.interface";
export { DataSinkInterface } from "./data-sink.interface";
export { DataSourceInterface } from "./data-source.interface";
export { ImageFinderInterface } from "./image-finder.interface";
export { ImageReader } from "./image-reader.type";
export { ImageWriter, ImageWriterParameters } from "./image-writer.type";
export { KeyboardProviderInterface } from "./keyboard-provider.interface";
export { MouseProviderInterface } from "./mouse-provider.interface";
export { ScreenProviderInterface } from "./screen-provider.interface";
export { WindowProviderInterface } from "./window-provider.interface";
export {ClipboardProviderInterface} from "./clipboard-provider.interface";
export {DataSinkInterface} from "./data-sink.interface";
export {DataSourceInterface} from "./data-source.interface";
export {ImageFinderInterface} from "./image-finder.interface";
export {ImageReader} from "./image-reader.type";
export {ImageWriter, ImageWriterParameters} from "./image-writer.type";
export {KeyboardProviderInterface} from "./keyboard-provider.interface";
export {MouseProviderInterface} from "./mouse-provider.interface";
export {ScreenProviderInterface} from "./screen-provider.interface";
export {WindowProviderInterface} from "./window-provider.interface";
export {LogProviderInterface} from "./log-provider.interface";
38 changes: 38 additions & 0 deletions lib/provider/log-provider.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export type LogFunction = (message: string, data?: {}) => void;
export type ErrorLogFunction = (error: Error, data?: {}) => void;

const logIdentifier = "[nut.js]";

export interface LogProviderInterface {
trace: LogFunction;
debug: LogFunction;
info: LogFunction;
warn: LogFunction;
error: ErrorLogFunction;
}

const nonErrorLevels = ['info', 'warn', 'debug', 'trace'];
const errorLevels = ['error'];

type NonErrorLogger = Omit<LogProviderInterface, 'error'>;
type ErrorLogger = Pick<LogProviderInterface, 'error'>;

export function wrapLogger(originalLogger: LogProviderInterface): LogProviderInterface {
for (const level of nonErrorLevels) {
const originalMethod = originalLogger[level as keyof NonErrorLogger];
originalLogger[level as keyof NonErrorLogger] = (message: string, data?: {}) => {
const wrappedMessage = `${logIdentifier} - ${message}`;
originalMethod(wrappedMessage, data);
}
}
for (const level of errorLevels) {
const originalMethod = originalLogger[level as keyof ErrorLogger];
originalLogger[level as keyof ErrorLogger] = (message: Error, data?: {}) => {
const wrappedMessage = `${logIdentifier} - ${message}`;
message.message = wrappedMessage;
originalMethod(message, data);
}
}

return originalLogger;
}
Loading