Skip to content

Commit 53414e5

Browse files
authored
Feature/371/logging provider (#456)
* (#371) Added first definition of log provider interface * (#371) First draft implementation of a log provider * (#371) Register log provider in registry * (#371) Export function to connect external logger * (#371) First test log * (#371) Restructured log providers * (#371) Restructured logging code, extended functionality of ConsoleLogProvider for timestamps and log levels * (#371) Removed dev code from mouse.class * (#371) Added log output to provider registry * (#371) Updated exports * (#371) Introduced dedicated folder for log providers * (#371) Started adding log output to window.function.ts, sleep.function.ts and screen.class.ts * (#371) More log output for screen.class.ts * (#371) Clipboard logging * (#371) Fixed tests * Deleted debug file * (#371) Updated .gitignore * (#371) Added early returns to image processor + test case * (#371) ConsoleLogProvider test
1 parent 21f1971 commit 53414e5

21 files changed

+671
-120
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,5 @@ fabric.properties
140140
/foo_asdf.jpg
141141
/.scratch/
142142
docs
143+
scratch.js
144+
debug.js

Diff for: index.ts

+7
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ export { Region } from "./lib/region.class";
3939
export { Window } from "./lib/window.class";
4040
export { FileType } from "./lib/file-type.enum";
4141
export { ColorMode } from "./lib/colormode.enum";
42+
export { LogProviderInterface } from "./lib/provider/log-provider.interface";
43+
export {
44+
useLogger,
45+
useConsoleLogger,
46+
ConsoleLogLevel,
47+
} from "./lib/logging.function";
4248

4349
const lineHelper = new LineHelper();
4450

@@ -63,6 +69,7 @@ const imageResource = (fileName: string) =>
6369
screen.config.resourceDirectory,
6470
fileName
6571
);
72+
6673
export { fetchFromUrl } from "./lib/imageResources.function";
6774

6875
export {

Diff for: lib/clipboard.class.spec.ts

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ClipboardClass } from "./clipboard.class";
22
import { ProviderRegistry } from "./provider/provider-registry.class";
33
import { mockPartial } from "sneer";
44
import { ClipboardProviderInterface } from "./provider";
5+
import { NoopLogProvider } from "./provider/log/noop-log-provider.class";
56

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

@@ -21,6 +22,7 @@ describe("Clipboard class", () => {
2122
copy: copyMock,
2223
})
2324
);
25+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
2426
const textToCopy = "bar";
2527

2628
// WHEN
@@ -40,6 +42,7 @@ describe("Clipboard class", () => {
4042
paste: pasteMock,
4143
})
4244
);
45+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
4346

4447
// WHEN
4548
SUT.paste();

Diff for: lib/clipboard.class.ts

+2
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ export class ClipboardClass {
1515
* @param text The text to copy
1616
*/
1717
public copy(text: string): Promise<void> {
18+
this.providerRegistry.getLogProvider().debug(`Saving to clipboard`);
1819
return this.providerRegistry.getClipboard().copy(text);
1920
}
2021

2122
/**
2223
* {@link paste} returns the current content of the system clipboard (limited to text)
2324
*/
2425
public paste(): Promise<string> {
26+
this.providerRegistry.getLogProvider().debug(`Fetching clipboard content`);
2527
return this.providerRegistry.getClipboard().paste();
2628
}
2729
}

Diff for: lib/logging.function.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { LogProviderInterface } from "./provider";
2+
import { ConsoleLogLevel, ConsoleLogProvider, ConsoleLogProviderConfig } from "./provider/log/console-log-provider.class";
3+
import providerRegistry from "./provider/provider-registry.class";
4+
5+
export const useLogger = (logger: LogProviderInterface) => {
6+
providerRegistry.registerLogProvider(logger);
7+
};
8+
9+
export const useConsoleLogger = (config?: ConsoleLogProviderConfig) => {
10+
providerRegistry.registerLogProvider(new ConsoleLogProvider(config));
11+
}
12+
13+
export { ConsoleLogLevel }

Diff for: lib/mouse.class.spec.ts

+14
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { LineHelper } from "./util/linehelper.class";
55
import { ProviderRegistry } from "./provider/provider-registry.class";
66
import { mockPartial } from "sneer";
77
import { MouseProviderInterface } from "./provider";
8+
import { NoopLogProvider } from "./provider/log/noop-log-provider.class";
89

910
beforeEach(() => {
1011
jest.clearAllMocks();
@@ -43,6 +44,7 @@ describe("Mouse class", () => {
4344
scrollLeft: scrollMock,
4445
})
4546
);
47+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
4648

4749
// WHEN
4850
const result = await SUT.scrollLeft(scrollAmount);
@@ -64,6 +66,7 @@ describe("Mouse class", () => {
6466
scrollRight: scrollMock,
6567
})
6668
);
69+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
6770

6871
// WHEN
6972
const result = await SUT.scrollRight(scrollAmount);
@@ -85,6 +88,7 @@ describe("Mouse class", () => {
8588
scrollDown: scrollMock,
8689
})
8790
);
91+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
8892

8993
// WHEN
9094
const result = await SUT.scrollDown(scrollAmount);
@@ -106,6 +110,7 @@ describe("Mouse class", () => {
106110
scrollUp: scrollMock,
107111
})
108112
);
113+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
109114

110115
// WHEN
111116
const result = await SUT.scrollUp(scrollAmount);
@@ -127,6 +132,7 @@ describe("Mouse class", () => {
127132
setMousePosition: setPositionMock,
128133
})
129134
);
135+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
130136

131137
// WHEN
132138
const result = await SUT.move(path);
@@ -152,6 +158,7 @@ describe("Mouse class", () => {
152158
releaseButton: releaseButtonMock,
153159
})
154160
);
161+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
155162

156163
// WHEN
157164
const result = await SUT.drag(path);
@@ -182,6 +189,7 @@ describe("Mouse class", () => {
182189
releaseButton: releaseButtonMock,
183190
})
184191
);
192+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
185193

186194
// WHEN
187195
const pressed = await SUT.pressButton(input);
@@ -209,6 +217,7 @@ describe("Mouse class", () => {
209217
pressButton: mouseMock,
210218
})
211219
);
220+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
212221

213222
// WHEN
214223
const start = Date.now();
@@ -232,6 +241,7 @@ describe("Mouse class", () => {
232241
releaseButton: mouseMock,
233242
})
234243
);
244+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
235245

236246
// WHEN
237247
const start = Date.now();
@@ -262,6 +272,7 @@ describe("Mouse class", () => {
262272
click: clickMock,
263273
})
264274
);
275+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
265276

266277
// WHEN
267278
await SUT.click(input);
@@ -289,6 +300,7 @@ describe("Mouse class", () => {
289300
doubleClick: clickMock,
290301
})
291302
);
303+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
292304

293305
// WHEN
294306
await SUT.doubleClick(input);
@@ -312,6 +324,7 @@ describe("Mouse class", () => {
312324
click: clickMock,
313325
})
314326
);
327+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
315328

316329
// WHEN
317330
const result = await SUT.leftClick();
@@ -336,6 +349,7 @@ describe("Mouse class", () => {
336349
click: clickMock,
337350
})
338351
);
352+
providerRegistryMock.getLogProvider = () => new NoopLogProvider();
339353

340354
// WHEN
341355
const result = await SUT.rightClick();

Diff for: lib/mouse.class.ts

+4
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,15 @@ export class MouseClass {
5050
`setPosition requires a Point, but received ${JSON.stringify(target)}`
5151
);
5252
}
53+
this.providerRegistry
54+
.getLogProvider()
55+
.info("Setting mouse position", target);
5356
return new Promise<MouseClass>(async (resolve, reject) => {
5457
try {
5558
await this.providerRegistry.getMouse().setMousePosition(target);
5659
resolve(this);
5760
} catch (e) {
61+
this.providerRegistry.getLogProvider().error(e as Error);
5862
reject(e);
5963
}
6064
});
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Image } from "../../image.class";
2+
import { Point } from "../../point.class";
3+
import JimpImageProcessor from "./jimp-image-processor.class";
4+
5+
const imageWidth = 10;
6+
const imageHeight = 20;
7+
8+
describe("JimpImageProcessor", () => {
9+
it.each([[new Point(-1, 5)], [new Point(imageWidth + 5, 5)]])(
10+
`should reject on out of bounds x coordinates`,
11+
async (outOfBoundsPoint: Point) => {
12+
// GIVEN
13+
const inputImage = new Image(
14+
imageWidth,
15+
imageHeight,
16+
Buffer.from([0, 0, 0]),
17+
3,
18+
"input_image",
19+
4,
20+
4
21+
);
22+
const SUT = new JimpImageProcessor();
23+
24+
// WHEN
25+
const result = SUT.colorAt(inputImage, outOfBoundsPoint);
26+
27+
// THEN
28+
await expect(result).rejects.toBe(
29+
`Query location out of bounds. Should be in range 0 <= x < image.width, is ${outOfBoundsPoint.x}`
30+
);
31+
}
32+
);
33+
34+
it.each([[new Point(5, -1)], [new Point(5, imageHeight + 10)]])(
35+
`should reject on out of bounds y coordinates`,
36+
async (outOfBoundsPoint: Point) => {
37+
// GIVEN
38+
const imageWidth = 10;
39+
const imageHeight = 20;
40+
const inputImage = new Image(
41+
imageWidth,
42+
imageHeight,
43+
Buffer.from([0, 0, 0]),
44+
3,
45+
"input_image",
46+
4,
47+
4
48+
);
49+
const SUT = new JimpImageProcessor();
50+
51+
// WHEN
52+
const result = SUT.colorAt(inputImage, outOfBoundsPoint);
53+
54+
// THEN
55+
await expect(result).rejects.toBe(
56+
`Query location out of bounds. Should be in range 0 <= y < image.height, is ${outOfBoundsPoint.y}`
57+
);
58+
}
59+
);
60+
});

Diff for: lib/provider/image/jimp-image-processor.class.ts

+2
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ export default class implements ImageProcessor {
1717
reject(
1818
`Query location out of bounds. Should be in range 0 <= x < image.width, is ${location.x}`
1919
);
20+
return;
2021
}
2122
if (location.y < 0 || location.y >= img.height) {
2223
reject(
2324
`Query location out of bounds. Should be in range 0 <= y < image.height, is ${location.y}`
2425
);
26+
return;
2527
}
2628
const jimpImage = imageToJimp(img);
2729
const rgba = Jimp.intToRGBA(

Diff for: lib/provider/index.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
export { ClipboardProviderInterface } from "./clipboard-provider.interface";
2-
export { DataSinkInterface } from "./data-sink.interface";
3-
export { DataSourceInterface } from "./data-source.interface";
4-
export { ImageFinderInterface } from "./image-finder.interface";
5-
export { ImageReader } from "./image-reader.type";
6-
export { ImageWriter, ImageWriterParameters } from "./image-writer.type";
7-
export { KeyboardProviderInterface } from "./keyboard-provider.interface";
8-
export { MouseProviderInterface } from "./mouse-provider.interface";
9-
export { ScreenProviderInterface } from "./screen-provider.interface";
10-
export { WindowProviderInterface } from "./window-provider.interface";
1+
export {ClipboardProviderInterface} from "./clipboard-provider.interface";
2+
export {DataSinkInterface} from "./data-sink.interface";
3+
export {DataSourceInterface} from "./data-source.interface";
4+
export {ImageFinderInterface} from "./image-finder.interface";
5+
export {ImageReader} from "./image-reader.type";
6+
export {ImageWriter, ImageWriterParameters} from "./image-writer.type";
7+
export {KeyboardProviderInterface} from "./keyboard-provider.interface";
8+
export {MouseProviderInterface} from "./mouse-provider.interface";
9+
export {ScreenProviderInterface} from "./screen-provider.interface";
10+
export {WindowProviderInterface} from "./window-provider.interface";
11+
export {LogProviderInterface} from "./log-provider.interface";

Diff for: lib/provider/log-provider.interface.ts

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export type LogFunction = (message: string, data?: {}) => void;
2+
export type ErrorLogFunction = (error: Error, data?: {}) => void;
3+
4+
const logIdentifier = "[nut.js]";
5+
6+
export interface LogProviderInterface {
7+
trace: LogFunction;
8+
debug: LogFunction;
9+
info: LogFunction;
10+
warn: LogFunction;
11+
error: ErrorLogFunction;
12+
}
13+
14+
const nonErrorLevels = ['info', 'warn', 'debug', 'trace'];
15+
const errorLevels = ['error'];
16+
17+
type NonErrorLogger = Omit<LogProviderInterface, 'error'>;
18+
type ErrorLogger = Pick<LogProviderInterface, 'error'>;
19+
20+
export function wrapLogger(originalLogger: LogProviderInterface): LogProviderInterface {
21+
for (const level of nonErrorLevels) {
22+
const originalMethod = originalLogger[level as keyof NonErrorLogger];
23+
originalLogger[level as keyof NonErrorLogger] = (message: string, data?: {}) => {
24+
const wrappedMessage = `${logIdentifier} - ${message}`;
25+
originalMethod(wrappedMessage, data);
26+
}
27+
}
28+
for (const level of errorLevels) {
29+
const originalMethod = originalLogger[level as keyof ErrorLogger];
30+
originalLogger[level as keyof ErrorLogger] = (message: Error, data?: {}) => {
31+
const wrappedMessage = `${logIdentifier} - ${message}`;
32+
message.message = wrappedMessage;
33+
originalMethod(message, data);
34+
}
35+
}
36+
37+
return originalLogger;
38+
}

0 commit comments

Comments
 (0)